Improve mobile responsive layout and site content
4435
package-lock.json
generated
Normal file
@@ -10,9 +10,14 @@
|
||||
"dev": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"start": "node server.js",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^6.2.2"
|
||||
"@aws-sdk/client-ses": "^3.1075.0",
|
||||
"astro": "^6.2.2",
|
||||
"cors": "^2.8.6",
|
||||
"express": "^5.2.1",
|
||||
"nodemailer": "^9.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
BIN
public/android-chrome-192x192.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
public/android-chrome-512x512.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
public/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
public/favicon-180x180.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
public/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
public/favicon-48x48.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
public/favicon.ico
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
public/favicon.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
1
public/images/astro-logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Astro</title><path d="M8.358 20.162c-1.186-1.07-1.532-3.316-1.038-4.944.856 1.026 2.043 1.352 3.272 1.535 1.897.283 3.76.177 5.522-.678.202-.098.388-.229.608-.36.166.473.209.95.151 1.437-.14 1.185-.738 2.1-1.688 2.794-.38.277-.782.525-1.175.787-1.205.804-1.531 1.747-1.078 3.119l.044.148a3.158 3.158 0 0 1-1.407-1.188 3.31 3.31 0 0 1-.544-1.815c-.004-.32-.004-.642-.048-.958-.106-.769-.472-1.113-1.161-1.133-.707-.02-1.267.411-1.415 1.09-.012.053-.028.104-.045.165h.002zm-5.961-4.445s3.24-1.575 6.49-1.575l2.451-7.565c.092-.366.36-.614.662-.614.302 0 .57.248.662.614l2.45 7.565c3.85 0 6.491 1.575 6.491 1.575L16.088.727C15.93.285 15.663 0 15.303 0H8.697c-.36 0-.615.285-.784.727l-5.516 14.99z"/></svg>
|
||||
|
After Width: | Height: | Size: 779 B |
28
public/images/blog-ai-unsplash.jpg
Normal file
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<title>Application Error</title>
|
||||
<style media="screen">
|
||||
html,body,iframe {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html,body {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="https://www.herokucdn.com/error-pages/application-error.html"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
BIN
public/images/blog-ai.jpg
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
28
public/images/blog-automation-unsplash.jpg
Normal file
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<title>Application Error</title>
|
||||
<style media="screen">
|
||||
html,body,iframe {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html,body {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="https://www.herokucdn.com/error-pages/application-error.html"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
BIN
public/images/blog-automation.jpg
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
28
public/images/blog-marketing-unsplash.jpg
Normal file
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<title>Application Error</title>
|
||||
<style media="screen">
|
||||
html,body,iframe {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html,body {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="https://www.herokucdn.com/error-pages/application-error.html"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
BIN
public/images/blog-marketing.jpg
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
1
public/images/blog-placeholder.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns='http://www.w3.org/2000/svg' width='800' height='420'><rect width='800' height='420' fill='#fed400' opacity='0.12'/><rect x='40' y='40' width='720' height='340' rx='20' fill='none' stroke='#fed400' stroke-width='2' opacity='0.4'/><text x='400' y='160' text-anchor='middle' font-family='sans-serif' font-size='64' font-weight='900' fill='#13120d' opacity='0.3'>More</text><text x='400' y='240' text-anchor='middle' font-family='sans-serif' font-size='64' font-weight='900' fill='#13120d' opacity='0.3'>mini</text><text x='400' y='320' text-anchor='middle' font-family='sans-serif' font-size='64' font-weight='900' fill='#13120d' opacity='0.3'>More</text></svg>
|
||||
|
After Width: | Height: | Size: 671 B |
28
public/images/blog-website-tmp.jpg
Normal file
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<title>Application Error</title>
|
||||
<style media="screen">
|
||||
html,body,iframe {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html,body {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="https://www.herokucdn.com/error-pages/application-error.html"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
BIN
public/images/blog-website.jpg
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
public/images/social/line-icon.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
1
public/images/wordpress-logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>WordPress</title><path d="M21.469 6.825c.84 1.537 1.318 3.3 1.318 5.175 0 3.979-2.156 7.456-5.363 9.325l3.295-9.527c.615-1.54.82-2.771.82-3.864 0-.405-.026-.78-.07-1.11m-7.981.105c.647-.03 1.232-.105 1.232-.105.582-.075.514-.93-.067-.899 0 0-1.755.135-2.88.135-1.064 0-2.85-.15-2.85-.15-.585-.03-.661.855-.075.885 0 0 .54.061 1.125.09l1.68 4.605-2.37 7.08L5.354 6.9c.649-.03 1.234-.1 1.234-.1.585-.075.516-.93-.065-.896 0 0-1.746.138-2.874.138-.2 0-.438-.008-.69-.015C4.911 3.15 8.235 1.215 12 1.215c2.809 0 5.365 1.072 7.286 2.833-.046-.003-.091-.009-.141-.009-1.06 0-1.812.923-1.812 1.914 0 .89.513 1.643 1.06 2.531.411.72.89 1.643.89 2.977 0 .915-.354 1.994-.821 3.479l-1.075 3.585-3.9-11.61.001.014zM12 22.784c-1.059 0-2.081-.153-3.048-.437l3.237-9.406 3.315 9.087c.024.053.05.101.078.149-1.12.393-2.325.609-3.582.609M1.211 12c0-1.564.336-3.05.935-4.39L7.29 21.709C3.694 19.96 1.212 16.271 1.211 12M12 0C5.385 0 0 5.385 0 12s5.385 12 12 12 12-5.385 12-12S18.615 0 12 0"/></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
171
server.js
Normal file
@@ -0,0 +1,171 @@
|
||||
/**
|
||||
* MoreminiMore production server.
|
||||
*
|
||||
* Serves Astro static build (dist/) + handles POST /api/contact via Amazon SES.
|
||||
*
|
||||
* Env vars:
|
||||
* SES_ACCESS_KEY_ID — AWS IAM key with ses:SendEmail
|
||||
* SES_SECRET_ACCESS_KEY — AWS IAM secret
|
||||
* SES_REGION — default: ap-southeast-1
|
||||
* PORT — default: 4321
|
||||
*/
|
||||
|
||||
import express from 'express';
|
||||
import cors from 'cors';
|
||||
import nodemailer from 'nodemailer';
|
||||
import { SESClient } from '@aws-sdk/client-ses';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { readFileSync, existsSync } from 'node:fs';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const PORT = parseInt(process.env.PORT || '4321', 10);
|
||||
const DIST = join(__dirname, 'dist');
|
||||
|
||||
// ── SES ────────────────────────────────────────────────────────────
|
||||
const sesConfigured = !!process.env.SES_ACCESS_KEY_ID;
|
||||
|
||||
let transporter;
|
||||
if (sesConfigured) {
|
||||
const ses = new SESClient({
|
||||
region: process.env.SES_REGION || 'ap-southeast-1',
|
||||
credentials: {
|
||||
accessKeyId: process.env.SES_ACCESS_KEY_ID,
|
||||
secretAccessKey: process.env.SES_SECRET_ACCESS_KEY,
|
||||
},
|
||||
});
|
||||
transporter = nodemailer.createTransport({
|
||||
SES: { ses, aws: { SendRawEmailCommand: undefined } },
|
||||
});
|
||||
}
|
||||
|
||||
// ── Helpers ────────────────────────────────────────────────────────
|
||||
const problemLabels = {
|
||||
website_no_leads: 'เว็บมีอยู่แล้ว แต่ไม่ค่อยมีลูกค้าทัก',
|
||||
ads_not_worth_it: 'ยิงแอดอยู่ แต่ยอดขายไม่คุ้ม',
|
||||
wrong_leads: 'มีคนทักมา แต่ไม่ใช่ลูกค้าที่ใช่',
|
||||
slow_or_error_work: 'ทีมงานทำงานช้า หรือผิดพลาดบ่อย',
|
||||
ai_not_sure: 'อยากใช้ AI แต่ไม่รู้เริ่มตรงไหน',
|
||||
not_sure: 'ยังไม่แน่ใจว่าควรแก้อะไรก่อน',
|
||||
};
|
||||
|
||||
function esc(text) {
|
||||
return String(text)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"');
|
||||
}
|
||||
|
||||
// ── Routes ─────────────────────────────────────────────────────────
|
||||
const app = express();
|
||||
app.use(cors());
|
||||
app.use(express.json({ limit: '16kb' }));
|
||||
|
||||
// POST /api/contact
|
||||
app.post('/api/contact', async (req, res) => {
|
||||
try {
|
||||
if (!sesConfigured) {
|
||||
console.warn('[api/contact] SES not configured — logging payload');
|
||||
console.info('[api/contact]', JSON.stringify(req.body, null, 2));
|
||||
return res.json({ ok: true, devMode: true });
|
||||
}
|
||||
|
||||
const { name, phone, email, problems = [], message = '', pageUrl = '', userAgent = '', website = '' } = req.body;
|
||||
|
||||
// Validation
|
||||
if (!name || !String(name).trim()) {
|
||||
return res.status(400).json({ ok: false, error: 'กรุณากรอกชื่อ' });
|
||||
}
|
||||
if ((!phone || !String(phone).trim()) && (!email || !String(email).trim())) {
|
||||
return res.status(400).json({ ok: false, error: 'กรุณากรอกเบอร์โทรหรืออีเมลอย่างน้อยหนึ่งอย่าง' });
|
||||
}
|
||||
|
||||
// Honeypot
|
||||
if (website && String(website).trim().length > 0) {
|
||||
console.warn('[api/contact] Honeypot triggered');
|
||||
return res.json({ ok: true }); // silent success for bots
|
||||
}
|
||||
|
||||
const problemsText = problems.length
|
||||
? problems.map((k) => `- ${problemLabels[k] || k}`).join('\n')
|
||||
: '(ไม่ได้เลือก)';
|
||||
|
||||
const msg = String(message || '(ไม่ได้กรอก)');
|
||||
const displayPhone = String(phone || '(ไม่ได้กรอก)');
|
||||
const displayEmail = String(email || '(ไม่ได้กรอก)');
|
||||
|
||||
await transporter.sendMail({
|
||||
from: 'MoreminiMore <hello@moreminimore.com>',
|
||||
to: 'hello@moreminimore.com',
|
||||
replyTo: email && email.includes('@') ? email : undefined,
|
||||
subject: `Contact: ${name} — ${problems.length} ปัญหา`,
|
||||
text: [
|
||||
`ข้อความใหม่จาก ${name}`,
|
||||
'',
|
||||
`ปัญหาที่เลือก:`,
|
||||
problemsText,
|
||||
'',
|
||||
`รายละเอียด:`,
|
||||
msg,
|
||||
'',
|
||||
`ข้อมูลติดต่อ:`,
|
||||
`ชื่อ: ${name}`,
|
||||
`เบอร์: ${displayPhone}`,
|
||||
`อีเมล: ${displayEmail}`,
|
||||
'',
|
||||
`---`,
|
||||
`ส่งจากหน้า: ${pageUrl}`,
|
||||
`UA: ${userAgent}`,
|
||||
].join('\n'),
|
||||
html: [
|
||||
`<h2>ข้อความใหม่จาก ${esc(name)}</h2>`,
|
||||
`<h3>ปัญหาที่เลือก</h3>`,
|
||||
`<p>${esc(problemsText).replace(/\n/g, '<br>')}</p>`,
|
||||
`<h3>รายละเอียด</h3>`,
|
||||
`<p>${esc(msg)}</p>`,
|
||||
`<h3>ข้อมูลติดต่อ</h3>`,
|
||||
`<table>`,
|
||||
` <tr><td><strong>ชื่อ</strong></td><td>${esc(name)}</td></tr>`,
|
||||
` <tr><td><strong>เบอร์</strong></td><td>${esc(displayPhone)}</td></tr>`,
|
||||
` <tr><td><strong>อีเมล</strong></td><td>${esc(displayEmail)}</td></tr>`,
|
||||
`</table>`,
|
||||
`<hr>`,
|
||||
`<p style="color:#888;font-size:12px">ส่งจาก <code>${esc(pageUrl)}</code><br>UA: ${esc(userAgent)}</p>`,
|
||||
].join('\n'),
|
||||
});
|
||||
|
||||
console.info(`[api/contact] Sent email from ${name} <${email || 'no email'}>`);
|
||||
return res.json({ ok: true });
|
||||
} catch (err) {
|
||||
console.error('[api/contact] Error:', err);
|
||||
return res.status(500).json({
|
||||
ok: false,
|
||||
error: err instanceof Error ? err.message : 'เกิดข้อผิดพลาด กรุณาลองใหม่ภายหลัง',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Static files
|
||||
if (existsSync(DIST)) {
|
||||
app.use(express.static(DIST, { maxAge: '1y', etag: true }));
|
||||
|
||||
// SPA-style fallback for client-side routes
|
||||
// Express 5 + path-to-regexp v8: use /{*splat} syntax instead of '*'
|
||||
app.get('/{*splat}', (req, res) => {
|
||||
// Don't intercept API or asset requests
|
||||
if (req.path.startsWith('/api/') || req.path.includes('.')) {
|
||||
return res.status(404).end();
|
||||
}
|
||||
res.sendFile(join(DIST, '404.html'));
|
||||
});
|
||||
} else {
|
||||
console.warn(`[server] dist/ not found — static files not served`);
|
||||
}
|
||||
|
||||
// ── Start ──────────────────────────────────────────────────────────
|
||||
app.listen(PORT, '0.0.0.0', () => {
|
||||
console.log(`[server] Listening on http://0.0.0.0:${PORT}`);
|
||||
console.log(`[server] SES: ${sesConfigured ? 'configured ✓' : 'NOT configured (dev mode)'}`);
|
||||
console.log(`[server] Static: ${existsSync(DIST) ? `dist/ ✓` : 'dist/ NOT found'}`);
|
||||
});
|
||||
@@ -12,14 +12,22 @@ const currentYear = new Date().getFullYear();
|
||||
<img src="/images/logos/logo-long-black.png" width="160" height="28" alt="MoreminiMore" />
|
||||
</a>
|
||||
|
||||
<a class="footer-link" href="https://line.me/ti/p/@moreminimore" target="_blank" rel="noopener">LINE @moreminimore</a>
|
||||
<a class="footer-link footer-phone" href="tel:+66809955945">
|
||||
<svg class="footer-phone-icon" aria-hidden="true" viewBox="0 0 24 24" focusable="false">
|
||||
<a class="footer-link" href="tel:+668****5945">
|
||||
<svg class="footer-icon" aria-hidden="true" viewBox="0 0 24 24" focusable="false">
|
||||
<path d="M6.6 10.8c1.4 2.8 3.8 5.1 6.6 6.6l2.2-2.2c.3-.3.8-.4 1.2-.3 1.3.4 2.6.6 4 .6.7 0 1.2.5 1.2 1.2v3.5c0 .7-.5 1.2-1.2 1.2C10.6 21.4 2.6 13.4 2.6 3.4c0-.7.5-1.2 1.2-1.2h3.5c.7 0 1.2.5 1.2 1.2 0 1.4.2 2.7.6 4 .1.4 0 .8-.3 1.2l-2.2 2.2Z" />
|
||||
</svg>
|
||||
<span>080-995-5945</span>
|
||||
</a>
|
||||
<a class="footer-link" href="mailto:contact@moreminimore.com">contact@moreminimore.com</a>
|
||||
<a class="footer-link" href="mailto:contact@moreminimore.com">
|
||||
<svg class="footer-icon" aria-hidden="true" viewBox="0 0 24 24" focusable="false">
|
||||
<path d="M22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6zm-2 0l-8 5-8-5h16zm0 12H4V8l8 5 8-5v10z" />
|
||||
</svg>
|
||||
<span>contact@moreminimore.com</span>
|
||||
</a>
|
||||
<a class="footer-link" href="https://line.me/ti/p/@moreminimore" target="_blank" rel="noopener">
|
||||
<img class="footer-icon" src="/images/social/line-icon.png" alt="" width="18" height="18" />
|
||||
<span>@moreminimore</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="footer-legal">
|
||||
@@ -66,9 +74,9 @@ const currentYear = new Date().getFullYear();
|
||||
transition: opacity .2s var(--ease);
|
||||
}
|
||||
|
||||
.footer-phone-icon {
|
||||
width: .82em;
|
||||
height: .82em;
|
||||
.footer-icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
fill: currentColor;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ const {
|
||||
<meta name="twitter:image" content={new URL(image, Astro.site).toString()} />
|
||||
|
||||
<!-- Favicons -->
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||
@@ -121,7 +121,7 @@ const {
|
||||
</button>
|
||||
|
||||
<nav id="nav-menu" class="nav-menu" aria-label="เมนูหลัก" data-nav-menu>
|
||||
<a href="/">หน้าแรก</a>
|
||||
<a href="/">หน้าหลัก</a>
|
||||
<div class="nav-service">
|
||||
<button type="button" aria-expanded="false" data-service-toggle>บริการ</button>
|
||||
<div class="service-mega" data-service-menu>
|
||||
@@ -134,9 +134,8 @@ const {
|
||||
</div>
|
||||
</div>
|
||||
<a href="/portfolio/">ผลงาน</a>
|
||||
<a href="/about/">เกี่ยวกับ</a>
|
||||
<a href="/about/">เกี่ยวกับเรา</a>
|
||||
<a href="/blog/">บทความ</a>
|
||||
<a href="/contact/">ติดต่อ</a>
|
||||
</nav>
|
||||
|
||||
<button class="nav-cta" type="button" data-open-lead>ส่งโจทย์ให้เราดู</button>
|
||||
|
||||
@@ -3,6 +3,7 @@ title: "ยิงแอดแล้วไม่คุ้ม อาจไม่
|
||||
description: "บางครั้งปัญหาอยู่ที่ intent ของคนที่เข้ามา ข้อความหน้าเว็บ หรือการวัดผลที่ยังไม่บอกคุณภาพลูกค้า"
|
||||
pubDate: 2026-06-19
|
||||
category: "Marketing"
|
||||
heroImage: "/images/blog-marketing.jpg"
|
||||
tags: ["marketing", "ads", "analytics"]
|
||||
draft: false
|
||||
---
|
||||
|
||||
@@ -3,6 +3,7 @@ title: "AI สำหรับ SME ไทย: เริ่มจากงาน
|
||||
description: "AI ไม่จำเป็นต้องเริ่มจากระบบใหญ่ เริ่มจากคำถามซ้ำ งานเอกสารซ้ำ หรือข้อมูลที่ทีมใช้ตัดสินใจก่อนจะคุ้มกว่า"
|
||||
pubDate: 2026-06-22
|
||||
category: "AI Consult"
|
||||
heroImage: "/images/blog-ai.jpg"
|
||||
tags: ["AI", "SME", "workflow"]
|
||||
draft: false
|
||||
---
|
||||
|
||||
@@ -3,6 +3,7 @@ title: "Marketing Automation ควรช่วยลดงาน ไม่ใ
|
||||
description: "ก่อนเลือกเครื่องมือ ควรดู workflow จริงก่อนว่าขั้นตอนไหนซ้ำ ช้า หรือผิดพลาดบ่อย แล้วค่อยออกแบบระบบช่วย"
|
||||
pubDate: 2026-06-21
|
||||
category: "Automation"
|
||||
heroImage: "/images/blog-automation.jpg"
|
||||
tags: ["automation", "marketing", "workflow"]
|
||||
draft: false
|
||||
---
|
||||
|
||||
@@ -3,6 +3,7 @@ title: "เว็บ SME ที่ดีควรถามได้ว่าล
|
||||
description: "เว็บไซต์ไม่ใช่แค่หน้าแนะนำบริษัท แต่ควรช่วยให้ลูกค้าเข้าใจปัญหา เห็นทางเลือก และรู้ว่าควรติดต่อเรื่องอะไร"
|
||||
pubDate: 2026-06-20
|
||||
category: "Website"
|
||||
heroImage: "/images/blog-website.jpg"
|
||||
tags: ["website", "SME", "conversion"]
|
||||
draft: false
|
||||
---
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Google Apps Script Web App URL — deploy ตาม google-apps-script/SETUP.md
|
||||
// ถ้ายังไม่มี ให้เว้นว่างไว้ ฟอร์มจะแสดงข้อความแจ้ง
|
||||
// Production: ตั้ง PUBLIC_FORM_ENDPOINT=https://script.google.com/macros/s/.../exec
|
||||
export const formEndpoint = (typeof import.meta !== 'undefined' && import.meta.env?.PUBLIC_FORM_ENDPOINT) || '';
|
||||
// Contact form endpoint — posts to our own Astro API route (SES backend)
|
||||
// In production, Astro resolves this relative URL against the site origin
|
||||
export const formEndpoint = '/api/contact';
|
||||
|
||||
export const problems = [
|
||||
['website_no_leads', 'เว็บมีอยู่แล้ว แต่ไม่ค่อยมีลูกค้าทัก'],
|
||||
@@ -21,10 +20,49 @@ export const services = [
|
||||
headline: 'เว็บไชต์ที่ช่วยหาลีดหรือช่วยให้จำแบรนด์',
|
||||
copy: 'เหมาะกับธุรกิจที่มีเว็บแล้วแต่ลูกค้ายังไม่ค่อยติดต่อ หรืออยากเริ่มเว็บใหม่ให้วัดผลได้ตั้งแต่วันแรก รวมถึงธุรกิจที่มีปัญหาเรื่อง SEO และ GEO',
|
||||
detail: 'เริ่มจากถามว่าเว็บนี้ทำเพื่ออะไร ขายของ เก็บ lead หรือสร้างความน่าเชื่อถือ แล้วออกแบบหน้าและข้อความให้ทำหน้าที่นั้นได้จริง',
|
||||
painPoints: ['เว็บดูมีอยู่ แต่ลูกค้ายังไม่รู้ว่าควรทักเรื่องอะไร', 'หน้าเว็บไม่ช่วยคัด lead หรืออธิบายข้อเสนอให้ชัด', 'อยากเริ่มเว็บใหม่ให้พร้อมวัดผลตั้งแต่วันแรก'],
|
||||
approach: ['เว็บไซต์เน้นตอบโจทย์ธุรกิจ เช่น การหาลีด หรือ การสร้าง Awareness', 'เว็บไชต์แบบ Responsive พร้อมระบบ SEO และ GEO', 'ระบบเว็บไชต์เน้นการใช้งานง่าย ให้ลูกค้าสามารถแก้ไขได้เอง'],
|
||||
deliverables: ['โครงหน้าและ copy หลัก', 'เว็บไซต์ responsive พร้อมใช้งาน', 'พื้นฐาน SEO และ analytics ที่จำเป็น'],
|
||||
painPoints: ['มีเว็บไซต์แต่ไม่มีคนเข้าเว็บ หรือมีน้อยมาก', 'เว็บไซต์มีคนเข้าเว็บแต่ไม่มีคนทักเลย', 'ไม่มีเว็บไซต์ หรือมีเว็บไซต์แล้ว แต่ไม่มีระบบเก็บสถิติเลย'],
|
||||
approach: ['ศึกษาสินค้าและกลุ่มเป้าหมายก่อนเริ่มงาน เพื่อให้เว็บไซต์ตรงกับรูปแบบที่กลุ่มเป้าหมายต้องการมากที่สุด', 'มีระบบเก็บสถิติให้ โดยลูกค้าเป็นเจ้าของข้อมูลนั้นเอง', 'คำนึงถึงความง่ายในการปรับแต่ง ให้ลูกค้าสามารถแก้ไขเว็บไซต์ได้ด้วยตัวเองเป็นหลัก', 'ให้คำแนะนำแนวทาง content strategy เบื้องต้น เพราะเราคาดหวังให้ลูกค้าได้กำไรจากผลงาน'],
|
||||
deliverables: ['เว็บไซต์เน้นตอบโจทย์ธุรกิจ เช่น การหาลีด หรือ การสร้าง Awareness', 'เว็บไซต์แบบ Responsive พร้อมระบบ SEO และ GEO', 'ระบบ Backend ที่ลูกค้าสามารถปรับแต่งเว็บไซต์ได้เองง่าย ๆ', 'แผนการตลาดระยะสั้นที่ใช้เว็บไซต์เป็นพื้นฐาน — เว็บเสร็จแล้วมีแนวทางให้ทำต่อ เพื่อเพิ่มโอกาสในการขาย'],
|
||||
proof: 'เหมาะกับธุรกิจที่ต้องใช้เว็บไซต์เป็นฐานความน่าเชื่อถือและช่องทางรับ lead',
|
||||
whyItMatters: {
|
||||
heading: 'ทุกวันที่เว็บไม่พร้อม คือวันที่เสียโอกาสให้คู่แข่งที่มีเว็บไซต์และระบบที่ดีกว่า',
|
||||
cards: [
|
||||
{ label: 'SEO & คนเข้าเว็บ', desc: 'เว็บไซต์มีคนเข้าเว็บ น้อย — เพราะ SEO ทำไว้ไม่ดี คู่แข่งที่ลงทุนกับ SEO จะแซงหน้าคุณทุกวัน' },
|
||||
{ label: 'Content & Conversion', desc: 'เว็บไซต์มีคนเข้าเว็บ แต่ไม่มีคนทัก — เพราะเน้นสวยแต่ไม่สนใจ content strategy คนที่เข้าเว็บอาจไม่ใช่กลุ่มเป้าหมาย หรือใช่แต่ไม่เข้าใจสิ่งที่จะสื่อ' },
|
||||
{ label: 'Hidden Signals', desc: 'เว็บไซต์ที่ไม่มีระบบเก็บสถิติ — เสียโอกาสมากที่สุด เพราะข้อมูลซ่อนเร้น (hidden signals) บอกได้ว่าสินค้าไหนที่ลูกค้าสนใจ หรือ pain point ของลูกค้า' },
|
||||
],
|
||||
},
|
||||
packages: [
|
||||
{
|
||||
name: 'Astro Website',
|
||||
suit: 'เว็บเร็ว ราคาถูก — เหมาะกับเว็บที่ไม่ซับซ้อน',
|
||||
features: ['เร็ว โหลดไว', 'Static Site — สร้างเป็นไฟล์ HTML ล้วน ไม่รัน script ทุกครั้งที่เปิดหน้า', 'SEO คะแนนสูงตั้งแต่แรก — Lighthouse 90+ โดยไม่ต้องปรับแต่งมาก', 'แก้ไขเนื้อหาผ่าน Chatbot (Telegram/Line) ได้', 'เหมาะกับ: เว็บแนะนำธุรกิจ, Landing Page, เว็บแสดงข้อมูล'],
|
||||
price: '0',
|
||||
hosting: '5,000',
|
||||
icon: 'astro',
|
||||
},
|
||||
{
|
||||
name: 'WordPress Website',
|
||||
suit: 'ระบบยืดหยุ่น เชื่อมต่อได้ — เหมาะกับเว็บที่ต้องการความซับซ้อน',
|
||||
features: ['มี Backend จัดการเว็บไซต์ได้ง่าย', 'Plugin กว่า 60,000 ตัว — เพิ่มฟีเจอร์ได้ไม่จำกัด โดยไม่ต้องเขียนโค้ดใหม่', 'ระบบผู้ใช้หลายระดับ — จัดการสิทธิ์การเข้าถึง เหมาะกับองค์กรที่มีหลายแผนก', 'AI เชื่อมระบบหลังบ้านอัตโนมัติ ลดงานมือ และใช้วิเคราะห์สถิติ', 'เหมาะกับ: E-commerce, ระบบสมาชิก, เชื่อม ERP'],
|
||||
price: '30,000',
|
||||
hosting: '0',
|
||||
icon: 'wordpress',
|
||||
},
|
||||
],
|
||||
packageNote: 'ราคาที่แสดงเป็นราคาเริ่มต้น ราคาจะปรับเปลี่ยนตามความซับซ้อนของเว็บไซต์ เช่น การเพิ่มระบบชำระเงิน การเชื่อม API กับระบบอื่น การออกแบบที่กำหนดเอง เป็นต้น',
|
||||
faqs: [
|
||||
{ question: 'Astro กับ WordPress เลือกอะไรดี?', answer: 'Astro: เว็บเร็ว ราคาถูก แก้ไขผ่าน Chatbot ได้ — เหมาะกับเว็บแสดงข้อมูล, Landing Page / WordPress: Backend จัดการง่าย เชื่อม API ได้ Plugin 60,000+ ตัว — เหมาะกับ E-commerce, ระบบสมาชิก, เชื่อม ERP เราจะช่วยคุณเลือกตามโจทย์จริง ไม่ยัดเยียด' },
|
||||
{ question: 'ทำเว็บใช้เวลากี่วัน?', answer: 'Astro: 14-30 วัน / WordPress: 30-60 วัน หรือมากกว่านั้น ขึ้นอยู่กับจำนวนหน้าและฟีเจอร์ และความพร้อมของลูกค้า เราจะบอกระยะเวลาชัดเจนใน Proposal ก่อนเริ่มงานทุกครั้ง' },
|
||||
{ question: 'เว็บที่ทำจะติดหน้าแรก Google ไหม?', answer: 'เราทำ SEO พื้นฐานให้ทุกเว็บ — โครงสร้างเว็บ, meta tags, ความเร็ว และ responsive ซึ่งการติดหน้าแรกจะขึ้นกับคู่แข่งของแต่ละ keyword ด้วย แต่เราจะแนะนำแผนเบื้องต้นเพื่อให้เว็บสามารถแข่งขันกับคู่แข่งได้ในระดับหนึ่งแน่นอน ถึงจะไม่ติดหน้าแรก แต่ควรได้อันดับดีกว่าเว็บเก่าแน่นอน' },
|
||||
{ question: 'Chatbot AI ทำงานยังไง?', answer: 'Chatbot ช่วยให้คุณแก้ไขเนื้อหาเว็บไซต์ได้เองผ่าน Telegram หรือ LINE โดยใช้การคุยเหมือนคุยกับพนักงานคนหนึ่งได้เลย — อธิบายให้ชัดเจน ก็จะได้งานตามต้องการ' },
|
||||
{ question: 'Chatbot มีข้อจำกัดอะไรไหม?', answer: 'มี — Chatbot จะใช้ได้เฉพาะงานเกี่ยวกับเว็บไซต์ของลูกค้าเท่านั้น คุยเรื่องอื่นไม่ได้ AI จะดึงให้กลับมาคุยแต่เรื่องเว็บไซต์ และมีข้อจำกัดจำนวนการใช้งาน token ซึ่ง token ที่เราให้ใช้นั้นมากพอที่จะปรับแต่งเว็บไซต์ หรือเขียนบทความได้ 2-4 บทความต่อเดือน นี่คือหนึ่งในอาวุธที่เราให้ลูกค้าใช้ เพื่อเพิ่มโอกาสสร้างรายได้จากเว็บไซต์นั่นเอง' },
|
||||
{ question: 'Chatbot จะปลดล็อกข้อจำกัดได้ไหม?', answer: 'ได้ — ถ้าลูกค้าต้องการใช้ Chatbot แบบไม่มีลิมิต จะมีค่าใช้จ่าย 2 อย่างเพิ่ม: (1) ค่า Server Chatbot 500 บาท/เดือน หรือ 5,000 บาท/ปี (2) AI API key ของลูกค้าเอง เมื่อปลดล็อกแล้ว ลูกค้าจะสั่ง Chatbot ได้ทุกอย่าง โดยจ่ายค่า token เอง และไม่กระทบลูกค้าคนอื่น เพราะมี Server ส่วนตัวแยกออกมา' },
|
||||
{ question: 'Hosting ราคาเท่าไหร่? ต้องจ่ายทุกปีไหม?', answer: 'Astro: 5,000 บาท/ปี / WordPress: เริ่มต้น 10,000 บาท/ปี (ฟรีปีแรก) — ไม่รวมค่าจดโดเมน .com หรือ .co.th เพราะเราต้องการให้ลูกค้าเป็นเจ้าของโดเมนเว็บไซต์ของตัวเอง จะดีที่สุด ราคา hosting อาจปรับเพิ่มถ้าเว็บไซต์มีคนเข้าเยอะมากจน host รับไม่ไหว แต่การจะมีค่าใช้จ่ายนี้เพิ่ม จำนวนคนเข้าเว็บน่าจะไม่ต่ำกว่า 10,000 คนต่อวัน ซึ่งลูกค้าน่าจะมีรายได้มากพอกับรายจ่ายที่เพิ่มแล้ว' },
|
||||
{ question: 'Content Strategy คืออะไร? เราได้อะไร?', answer: 'เราจะวิเคราะห์กลุ่มเป้าหมายและสินค้าของคุณ แล้วแนะนำแผนกลยุทธ์ที่จะทำต่อหลังจากมีเว็บไซต์แล้ว — ว่าควรทำอะไรต่อไปบ้าง เป็นขั้นตอนชัดเจน เพื่อให้เว็บไซต์ที่สร้างมาสร้างผลลัพธ์ได้จริง ไม่ใช่แค่มีเว็บแล้วจบ' },
|
||||
{ question: 'ทำเว็บแล้วต้องจ่ายค่าดูแลต่อไหม?', answer: 'ไม่จำเป็น — เราไม่มีค่าดูแลเพิ่มเติมอีก แม้แต่ Chatbot ก็ฟรีด้วย (แบบจำกัด token) ในกรณีที่ลูกค้าต้องการให้เราปรับเว็บไซต์นิดหน่อย เช่น เปลี่ยนรูป เปลี่ยน layout บางจุด เราก็ไม่คิดค่าบริการอะไรเพิ่มเติม' },
|
||||
{ question: 'ถ้ามีเว็บเดิมอยู่แล้ว จะย้ายมาได้ไหม?', answer: 'ได้ — เราจะวิเคราะห์เว็บเดิมก่อนว่าอะไรดีอยู่แล้ว อะไรควรปรับ จากนั้นทำเว็บใหม่โดยเก็บสิ่งที่ดีไว้ และปรับปรุงส่วนที่ขาด ช่วงเปลี่ยนผ่าน เราจะจัดการ redirect ให้คนเข้าเว็บไม่หาย' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Marketing Consult',
|
||||
@@ -32,12 +70,23 @@ export const services = [
|
||||
badge: 'ที่ปรึกษาการตลาดออนไลน์',
|
||||
objective: 'เพิ่มยอดขาย',
|
||||
headline: 'วางกลยุทธ์การตลาดจากสถิติ',
|
||||
copy: 'เหมาะกับธุรกิจที่ยิงโฆษณาอยู่ แต่ยอดขายไม่คุ้ม หรือมีคนทักมาแล้วไม่ใช่ลูกค้าที่ควรได้ รวมถึงธุรกิจที่ยิงโฆษณา โดยไม่รู้ว่าแอคที่ยิงนั้นคุ้มค่าหรือยัง?',
|
||||
copy: 'เหมาะกับธุรกิจที่ยิงโฆษณาอยู่ แต่ยอดขายไม่คุ้ม หรือมีคนทักมาแล้วไม่ใช่ลูกค้าที่ควรได้ รวมถึงธุรกิจที่ยิงโฆษณา โดยไม่รู้ว่าโฆษณาที่ลงทุนไปนั้นคุ้มค่าหรือยัง?',
|
||||
detail: 'ดูสถิติคนเข้าเว็บ คนคลิกโฆษณา ยอดขาย และกลุ่มลูกค้าก่อน แล้วค่อยเลือกช่องทาง ข้อความ และงบประมาณที่ควรใช้',
|
||||
painPoints: ['ยิงแอดแล้วมีคนคลิก แต่ยอดขายไม่คุ้ม', 'มี lead เข้ามา แต่คุณภาพลูกค้ายังไม่ตรง', 'ไม่แน่ใจว่างบควรอยู่ที่ช่องทางไหน'],
|
||||
approach: ['วางระบบเก็บข้อมูลทางสถิติสำหรับเว็บไชต์, โฆษณา และยอดขาย', 'การวางกลยุทธ์จะใช้ข้อมูลสถิติเป็นพื้นฐาน', 'แต่ละช่องทางและแต่ละกลุ่มลูกค้าจะมีกลยุทธ์แตกต่างกัน'],
|
||||
deliverables: ['diagnosis จากข้อมูลจริง', 'แผนปรับกลุ่มเป้าหมายและข้อความ', 'แนวทางวัดผลที่ช่วยดูคุณภาพลูกค้า'],
|
||||
painPoints: ['ยิงโฆษณาแล้วมีคนคลิก แต่ยอดขายไม่คุ้ม', 'มีคนติดต่อเข้ามาแต่ขายไม่ได้', 'เพิ่มงบโฆษณาแล้ว แต่ยอดขายไม่เพิ่มขึ้นเลย'],
|
||||
approach: ['วางระบบเก็บข้อมูลทางสถิติสำหรับเว็บไซต์ โฆษณา และยอดขาย', 'การวางกลยุทธ์จะใช้ข้อมูลสถิติเป็นพื้นฐาน', 'แต่ละช่องทางและแต่ละกลุ่มลูกค้าจะมีกลยุทธ์แตกต่างกัน'],
|
||||
deliverables: ['ยอดขายที่เพิ่มขึ้น', 'ยอดคลิกมากขึ้น และตรงกลุ่มเป้าหมาย', 'ต้นทุนต่อยอดขายจากโฆษณาลดลง'],
|
||||
proof: 'เหมาะกับธุรกิจที่มี activity การตลาดอยู่แล้ว แต่อยากรู้ว่าเงินหายไปตรงไหน',
|
||||
whyItMatters: 'ยิงโฆษณาต่อไปโดยไม่วิเคราะห์ข้อมูล หรือดูข้อมูลไม่มากพอ หรือแผนกลยุทธ์ไม่รัดกุมพอ — จะทำให้งบประมาณรั่วไหลออกไปเรื่อย ๆ เสียเงินโดยเปล่าประโยชน์',
|
||||
faqs: [
|
||||
{ question: 'ต้องมีข้อมูลอะไรบ้างก่อนเริ่ม?', answer: 'ถ้ามี Google Analytics, Ads dashboard หรือข้อมูลยอดขายอยู่แล้วจะดีมาก แต่ถ้ายังไม่มี เราจะช่วยตั้งระบบเก็บข้อมูลให้ตั้งแต่ต้น' },
|
||||
{ question: 'ใช้เวลากี่เดือนถึงเห็นผล?', answer: 'ปกติ 1-3 เดือนจะเริ่มเห็นแนวโน้มชัดเจน — ขึ้นอยู่กับปริมาณข้อมูลที่มีและความซับซ้อนของตลาด เราจะอัปเดต progress ให้ทุกเดือน' },
|
||||
{ question: 'ยิงโฆษณาอยู่แล้ว ทำไมต้องจ้างที่ปรึกษา?', answer: 'หลายครั้งปัญหาอยู่ที่การวัดผลหรือการตีความข้อมูล ไม่ใช่การยิงโฆษณาเอง เราช่วยหา insight ที่ทีมคุณอาจมองข้าม และการมองนอกกรอบก็จะช่วยให้เห็นโอกาสใหม่ ๆ หรือได้ทดสอบตลาดใหม่มากขึ้น' },
|
||||
{ question: 'ถ้างบน้อย ควรเริ่มจากตรงไหน?', answer: 'เราจะเริ่มจากดูข้อมูลสถิติ และกำหนดกลยุทธ์ที่ควรจะได้ผลมากที่สุด โดยที่ใช้งบประมาณต่ำที่สุด' },
|
||||
{ question: 'มีค่าใช้จ่ายขั้นต่ำไหม?', answer: 'มี — ค่าโฆษณาที่เราแนะนำจะมีค่าใช้จ่ายขั้นต่ำ เพราะจากประสบการณ์นั้น การจ่ายน้อยเกินไปจะไม่ครอบคลุมกลุ่มเป้าหมายทั้งวัน แต่มีบางกรณี ถ้ากลุ่มเป้าหมายนั้นเฉพาะเจาะจงมาก ค่าโฆษณาอาจจะต่ำกว่าค่าใช้จ่ายที่เราแนะนำก็ได้' },
|
||||
{ question: 'ค่าบริการนั้นรวมกับค่าโฆษณาไหม?', answer: 'ไม่รวม — ค่าบริการจะเป็นรายเดือนแยกต่างหากกับค่าโฆษณา โดยค่าโฆษณาเราจะแนะนำให้ลูกค้าจ่ายเองโดยตรง เพื่อความโปร่งใสในการใช้งบประมาณ' },
|
||||
{ question: 'วัดผลยังไง และจะรู้ได้ยังไงว่าได้ผล?', answer: 'การวัดผล เราจะเน้นการดูยอดขายเป็นหลัก (ถ้าลูกค้าให้ดู) ถ้าดูยอดขายไม่ได้ ก็จะดูยอดคลิก ยอดคนเห็นโฆษณารองลงมา สิ่งที่เราเจอคือลูกค้าหลายคนไม่ยอมแจ้งยอดขายกับเรา แต่เขาก็ใช้บริการเราเรื่อย ๆ และจะมาแจ้งเราอีกทีตอนยอดตก' },
|
||||
{ question: 'ต้องเซ็นสัญญานานไหม?', answer: 'ไม่ต้อง — เราไม่มีสัญญาผูกมัดรายปี เริ่มด้วย 1 เดือนก่อนก็ได้ ถ้าไม่โอเคก็หยุดได้เลย เราเชื่อว่าถ้าทำดี ลูกค้าจะอยู่ต่อเอง' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Automation Workflow',
|
||||
@@ -47,10 +96,17 @@ export const services = [
|
||||
headline: 'วางระบบงานให้มีความรวดเร็วและลดความผิดพลาด',
|
||||
copy: 'เหมาะกับธุรกิจที่ยังใช้ระบบงานที่เน้นแรงงานคนมาก ซึ่งช้าและมีโอกาสผิดพลาดสูง',
|
||||
detail: 'เริ่มจากดู workflow ปัจจุบันว่าอะไรซ้ำ ทำมือ หรือเสียเวลา แล้วเลือกว่าจะใช้ n8n ระบบเฉพาะทาง หรือ AI ช่วยในจุดไหน',
|
||||
painPoints: ['ทีมทำงานซ้ำ ๆ และเสียเวลากับขั้นตอนเดิม', 'ข้อมูลกระจัดกระจาย ต้องคอย copy หรือส่งต่อเอง', 'งานผิดพลาดจากการทำมือเกิดซ้ำ'],
|
||||
painPoints: ['พนักงานทำงานซ้ำ ๆ กับขั้นตอนเดิม เช่น การสร้างเอกสารซ้ำ ๆ โดยการไล่หาข้อมูล จากนั้นก็คัดลอกและวางแบบเดิม ๆ เป็นต้น', 'การไล่หาข้อมูลที่กระจัดกระจาย เช่น การถามหาข้อมูลสินค้าหรือโครงการ พนักงานต้องใช้เวลาหาข้อมูลนาน เพราะเก็บไว้หลายโฟลเดอร์ เป็นต้น', 'งานผิดพลาดจากการทำมือ เช่น การทำรายงานที่ต้องใช้ข้อมูลจากหลายแหล่ง ทำให้มีการคีย์ข้อมูลผิด เป็นต้น'],
|
||||
approach: ['งานที่มีการทำซ้ำ จะมีระบบงานมาแทนที่ทั้งหมด', 'เลือกระบบงานที่เหมาะสม กับความต้องการของลูกค้า และพฤติกรรมองค์กร', 'ระบบงานจะไม่เน้นการปรับพฤติกรรมการทำงาน แต่จะประสานหรือเป็นหนึ่งเดียวแทน'],
|
||||
deliverables: ['workflow map', 'ระบบ automation หรือ integration ตาม scope', 'คู่มือใช้งานและจุดตรวจสอบ'],
|
||||
deliverables: ['ความเร็วในการได้ผลลัพธ์มากขึ้น ลดเวลาการทำงาน', 'พนักงานสร้างผลงานได้มากขึ้น เพราะได้เวลาว่างคืนมามากขึ้น', 'ในระยะยาว ต้นทุนด้านพนักงานจะลดลง เพราะพนักงาน 1 คนจะทำงานได้มากขึ้น'],
|
||||
proof: 'เหมาะกับธุรกิจที่มีทีมทำงานซ้ำทุกวัน และอยากลดเวลาหรือความผิดพลาดก่อนขยายทีม',
|
||||
whyItMatters: 'การใช้แรงงานคนทำงานซ้ำ ๆ เดิม ๆ ทุกวัน ทั้ง ๆ ที่งานนั้นสามารถลดเวลาในการทำงานได้อย่างมหาศาล — ในระยะยาวทำให้ธุรกิจมีต้นทุนสูงขึ้น โดยเฉพาะต้นทุนค่าจ้างพนักงานต่อยอดขาย และเวลาที่พนักงานเสียไปกับงานซ้ำ ๆ ถ้าเอาคืนมาได้ พนักงานก็จะสามารถทำงานอื่นที่สร้างมูลค่าได้มากขึ้น',
|
||||
faqs: [
|
||||
{ question: 'ระบบ automation จะมาแทนที่คนใช่ไหม?', answer: 'ไม่ใช่ — เรา automate เฉพาะงานที่ซ้ำ ๆ และเสี่ยงผิดพลาด เพื่อให้ทีมคุณมีเวลาไปโฟกัสงานที่ใช้ความคิดสร้างสรรค์และการตัดสินใจมากขึ้น' },
|
||||
{ question: 'ถ้าการทำงานปัจจุบันยังไม่มีขั้นตอนการทำงานที่ชัดเจนยังไม่เป็นระบบ จะเริ่มยังไง?', answer: 'เราจะใช้วิธีคุยและสังเกตการทำงานจริง เพื่อช่วยวางระบบงานให้ และจะแทรกการใช้เทคโนโลยีให้พนักงานใช้งานด้วย' },
|
||||
{ question: 'ใช้เครื่องมืออะไร? แพงไหม?', answer: 'เราเลือกเครื่องมือให้เหมาะกับงาน — n8n, Make, Google Apps Script หรือ custom solution ถ้าเป็น open source แทบไม่มีค่าใช้จ่ายเพิ่ม' },
|
||||
{ question: 'แค่ทำระบบ automation จะสร้างประโยชน์ให้ธุรกิจยังไง?', answer: 'ถ้าลูกค้าคาดหวังผลลัพธ์ในระยะสั้น จะไม่เห็นผลประโยชน์ เพราะบริการนี้จะให้ผลประโยชน์ในระยะยาว — ยกตัวอย่างเช่น พนักงาน 1 คนเสียเวลาทำรายงานยอดขายวันละ 30 นาทีทุกวัน ทำให้มีการทำ OT เพราะทำงานเสร็จไม่ทัน แต่พอวางระบบแล้ว เวลาที่ใช้จะเหลือแค่ 3 นาที เวลาที่ได้คืนมาทำให้พนักงานไม่ต้องทำ OT ลดค่าใช้จ่ายของธุรกิจ และขวัญกำลังใจของพนักงานก็ดีขึ้น เพราะได้กลับบ้านตรงเวลา เป็นต้น' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'AI Consult',
|
||||
@@ -60,10 +116,17 @@ export const services = [
|
||||
headline: 'ระบบงานที่ผสาน AI เป็นส่วนหนึ่งในระบบ',
|
||||
copy: 'เหมาะกับธุรกิจที่อยากใช้ AI ให้เกิดประโยชน์สูงสุด และไม่ต้องการให้ความรู้อยู่กับพนักงานเท่านั้น',
|
||||
detail: 'เลือกโมเดลและวิธีใช้ให้เหมาะกับงานจริง โดยเฉพาะงานที่ต้องรักษาความรู้และความลับขององค์กร',
|
||||
painPoints: ['อยากใช้ AI แต่ยังไม่รู้ว่างานไหนคุ้มที่สุด', 'ทีมลองเครื่องมือหลายตัวแต่ยังไม่เชื่อมกับงานจริง', 'มีความรู้สำคัญอยู่กับคนหรือเอกสารกระจัดกระจาย'],
|
||||
approach: ['ความรู้ที่พนักงานมี จะถูกเก็บเป็นความรู้ขององค์กร', 'พนักงานจะใช้ AI เป็นส่วนหนึ่งในการทำงาน', 'ข้อมูลที่เป้นความลับจะมีระบบงานเฉพาะ'],
|
||||
deliverables: ['AI use case roadmap', 'prototype หรือ workflow ที่ใช้ได้จริง', 'แนวทางรักษาความรู้และข้อมูลขององค์กร'],
|
||||
painPoints: ['พนักงานออกทีไร มีปัญหาข้อมูลลูกค้าทุกที', 'พนักงานบิดเบือนความจริงในรายงาน', 'พนักงานทำงานช้า เพราะต้องนั่งหาข้อมูลใหม่ทุกครั้ง'],
|
||||
approach: ['วางระบบ AI ให้เป็นส่วนหนึ่งของการทำงาน', 'พนักงานจะไม่ต้องปรับตัวมาก และกระตุ้นให้ใช้งานระบบที่สร้างขึ้นจนเป็นนิสัย', 'ข้อมูลจะถูกเก็บอย่างเป็นความลับ และง่ายต่อการเข้าถึงและโยกย้าย'],
|
||||
deliverables: ['ความรู้ที่พนักงานมี จะถูกเก็บเป็นความรู้ขององค์กร', 'ระบบงานที่เพิ่มประสิทธิภาพและความเร็วในการทำงานให้พนักงาน', 'ระบบ AI ที่มีความสามารถในการพัฒนาตัวเอง ยิ่งพนักงานใช้งาน ยิ่งทำงานตอบโจทย์พนักงานแต่ละคนมากขึ้น', 'พนักงานจะบิดเบือนข้อมูลได้น้อยลง หรือไม่กล้าทำ เพราะจะสามารถสอบถามเพื่อยืนยันข้อมูลได้จาก AI โดยตรง'],
|
||||
proof: 'เหมาะกับองค์กรที่อยากใช้ AI เพื่อช่วยคนทำงาน ไม่ใช่แค่ซื้อเครื่องมือใหม่',
|
||||
whyItMatters: 'ความรู้และความลับทางธุรกิจอยู่ที่ตัวพนักงาน — พอลาออกก็หายไป เริ่มจากศูนย์ทุกครั้ง ตามคู่แข่งไม่ทัน หรืออาจจะเสียลูกค้าและโอกาสไปพร้อมกับพนักงานที่ลาออกไป',
|
||||
faqs: [
|
||||
{ question: 'AI จะมาแทนที่พนักงานไหม?', answer: 'ไม่ใช่ — AI จะเป็นเพียงเครื่องมือที่จะช่วยให้พนักงานทำงานได้เร็วขึ้น ผิดพลาดน้อยลง และค่อย ๆ เก็บความรู้และประสบการณ์จากพนักงานเข้าศูนย์ข้อมูล' },
|
||||
{ question: 'ข้อมูลบริษัทจะปลอดภัยไหม?', answer: 'ปลอดภัย — เพราะเราจะแนะนำให้ใช้ AI Provider ที่มีนโยบายไม่เก็บข้อมูล หรือถ้าข้อมูลมีความลับมาก ก็สามารถใช้ Local LLM ได้ (ซึ่งจะต้องลงทุนเครื่อง PC ประสิทธิภาพสูง) นอกจากนี้ข้อมูลที่เป็นองค์ความรู้ขององค์กร จะเก็บไว้ที่ server ของลูกค้า ซึ่งบุคคลภายนอกจะไม่สามารถเข้าไปดูได้' },
|
||||
{ question: 'ธุรกิจเล็ก ๆ ใช้ AI คุ้มไหม?', answer: 'คุ้ม — เพราะเราไม่ได้คิดค่าบริการแพง เมื่อเทียบกับความประหยัดและผลประโยชน์ที่ได้ในระยะยาว ถ้าลูกค้าไม่คิดจะใช้ Local LLM และใช้ AI Provider ที่ราคาไม่แพง ค่าใช้จ่ายจะไม่สูงเลย' },
|
||||
{ question: 'ต้องมีความรู้ AI มาก่อนไหม?', answer: 'ไม่ต้อง — เพราะเราจะออกแบบให้พนักงานใช้งาน AI ผ่านเครื่องมือที่ใช้กันประจำอยู่แล้ว เช่น LINE เป็นต้น พนักงานจะเหมือนกับมีผู้ช่วยส่วนตัวที่ทำงานทุกอย่างที่คอมพิวเตอร์ทำได้ มาช่วยทำงานแทน เช่น การสร้างเอกสารอย่างใบวางบิล คำสั่งซื้อ หรือเอกสารอื่น ๆ เป็นต้น ในมุมของเซลล์ยังจะสามารถเป็นโค้ช ช่วยแนะนำไอเดียการเข้าหาลูกค้าได้อีกด้วย ซึ่งจังหวะนี้คือจุดที่ AI จะได้ความรู้เชิงลึกของลูกค้าจากเซลล์' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@ import { process } from '../data/site.js';
|
||||
>
|
||||
<section class="page-hero scene scene-light hero-oversized" data-scene="light">
|
||||
<p class="eyebrow">เกี่ยวกับเรา</p>
|
||||
<h1>ที่ปรึกษาที่เริ่มจากคำถาม ไม่ใช่เริ่มจากขายแพ็กเกจ</h1>
|
||||
<h1>กำไรของคุณคือเป้าหมายของเรา</h1>
|
||||
<p class="hero-lead">
|
||||
MoreminiMore ทำงานกับ SME ที่อยากใช้เว็บ การตลาด ระบบอัตโนมัติ และ AI ให้คุ้มขึ้น โดยดูข้อมูลและบริบทของธุรกิจก่อนตัดสินใจลงมือ
|
||||
ทุกบริการของ MoreminiMore มีจุดมุ่งหมายคือ เพิ่มยอดขาย หรือ ลดต้นทุน เพื่อสุดท้ายให้ลูกค้ามีกำไรมากขึ้น โดยใช้ข้อมูลเป็นพื้นฐานในการวางกลยุทธ์ทั้งการตลาดและการทำงาน
|
||||
</p>
|
||||
</section>
|
||||
|
||||
@@ -21,10 +21,10 @@ import { process } from '../data/site.js';
|
||||
<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">ทำไมเราถึงมีอยู่</p>
|
||||
<h2>ธุรกิจไม่ควรเสียเงินกับสิ่งที่ยังไม่รู้ว่าคุ้มไหม</h2>
|
||||
<p class="eyebrow">ทำไมถึงมีเรา</p>
|
||||
<h2>ธุรกิจไม่ควรเสียต้นทุนกับการ "ตาม" คนอื่นจน "ลืม" ตัวเอง</h2>
|
||||
<p>
|
||||
เราเห็น SME หลายรายจ่ายเงินกับเว็บที่สวยแต่ไม่มีคนทัก โฆษณาที่มีคนคลิกแต่ไม่เกิดยอดขาย หรือเครื่องมือ AI ที่ดูน่าตื่นเต้นแต่ไม่เข้ากับงานจริง จึงเลือกทำงานแบบดูโจทย์ก่อน แล้วค่อยเสนอสิ่งที่ควรทำ
|
||||
เราเห็น SME หลายรายจ่ายเงินกับเว็บที่สวยแต่ไม่มีคนทัก โฆษณาที่มีคนคลิกแต่ไม่เกิดยอดขาย หรือเครื่องมือ AI ที่ดูน่าตื่นเต้นแต่ไม่เข้ากับงานจริง สุดท้ายคือเสียเงินเปล่าเพราะ "ตาม" สิ่งที่คนอื่นขาย โดย "ลืม" ว่าธุรกิจตัวเองต้องการอะไรกันแน่
|
||||
</p>
|
||||
</article>
|
||||
<article class="glass-panel liquid-glass liquidGlass-wrapper">
|
||||
@@ -40,15 +40,18 @@ import { process } from '../data/site.js';
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="page-section page-section-tight">
|
||||
<section class="process-section">
|
||||
<div class="section-heading">
|
||||
<p class="eyebrow">ขั้นตอน</p>
|
||||
<h2>วิธีทำงานที่ลดการเดา</h2>
|
||||
<p class="eyebrow">วิธีการทำงาน</p>
|
||||
<h2>กลยุทธ์และระบบงานของเรา สำหรับลูกค้าแต่ละรายจะไม่เหมือนกัน</h2>
|
||||
</div>
|
||||
<div class="process-grid">
|
||||
{process.map(([title, copy], index) => (
|
||||
<article>
|
||||
<span>{String(index + 1).padStart(2, '0')}</span>
|
||||
<article class="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 class="step-number">{String(index + 1).padStart(2, '0')}</span>
|
||||
<h3>{title}</h3>
|
||||
<p>{copy}</p>
|
||||
</article>
|
||||
@@ -56,99 +59,196 @@ import { process } from '../data/site.js';
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="page-section scene scene-dark tools-section" data-scene="dark">
|
||||
<div class="tools-layout">
|
||||
<div class="tools-copy">
|
||||
<p class="eyebrow">เครื่องมือ</p>
|
||||
<h2>เลือกเครื่องมือจากโจทย์ ไม่ใช่จากกระแส</h2>
|
||||
<p>
|
||||
เราใช้ stack หลายแบบ แต่หลักคิดมีข้อเดียว: เครื่องมือต้องช่วยเพิ่มยอดขาย ลดต้นทุน หรือทำให้ทีมตัดสินใจเร็วขึ้น ถ้าไม่ช่วย เราไม่ยัดใส่โปรเจกต์ให้ดูเท่
|
||||
</p>
|
||||
</div>
|
||||
<section class="tools-section-full">
|
||||
<div class="section-heading">
|
||||
<p class="eyebrow">เทคโนโลยีและแอป</p>
|
||||
<h2>เราเลือกเทคโนโลยีและแอปให้เหมาะสมกับงาน</h2>
|
||||
</div>
|
||||
|
||||
<div class="tools-stack" aria-label="เครื่องมือที่ MoreminiMore ใช้">
|
||||
<article class="tool-card tool-card-featured 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>01</span>
|
||||
<h3>Marketing Intelligence</h3>
|
||||
<p>ดูโฆษณาคู่แข่ง, keyword gap, trend ตลาด และสัญญาณที่บอกว่าควรเริ่มจากอะไร</p>
|
||||
</article>
|
||||
<div class="tools-grid">
|
||||
<article class="tool-card 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>01</span>
|
||||
<h3>Data Collection & Analytics</h3>
|
||||
<p>รวบรวมและวิเคราะห์ข้อมูลจากทุกช่องทาง — Google Analytics, Search Console, Meta Ads, LINE OA และอื่น ๆ เพื่อให้ทุกการตัดสินใจมีตัวเลขรองรับ ไม่ใช่แค่ความรู้สึก</p>
|
||||
</article>
|
||||
|
||||
<article class="tool-card 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>02</span>
|
||||
<h3>Build Stack</h3>
|
||||
<p>Astro, WordPress, Python, PHP, Node.js — เลือกตามงานจริง ไม่ล็อกลูกค้ากับของที่ดูแพงแต่ดูแลยาก</p>
|
||||
</article>
|
||||
<article class="tool-card 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>02</span>
|
||||
<h3>Development Stack</h3>
|
||||
<p>Astro, WordPress, Python, PHP, Node.js — เราเลือก stack จากโจทย์จริง ไม่ใช่จากเทรนด์ ทุกเทคโนโลยีต้องตอบโจทย์ธุรกิจคุณ</p>
|
||||
</article>
|
||||
|
||||
<article class="tool-card 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>03</span>
|
||||
<h3>Automation + AI</h3>
|
||||
<p>n8n, Make, OpenAI API, Meta API, Local LLM — ใช้เมื่อช่วยลดงานซ้ำหรือปิดช่องว่างข้อมูลได้จริง</p>
|
||||
</article>
|
||||
</div>
|
||||
<article class="tool-card 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>03</span>
|
||||
<h3>Automation & AI Integration</h3>
|
||||
<p>n8n, Make, OpenAI API, Local LLM — เชื่อมต่อระบบ ลดงานซ้ำ และใช้ AI ในจุดที่สร้างผลลัพธ์จริง ไม่ใช่แค่เพิ่มเครื่องมือ</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="final-cta">
|
||||
<div class="glass-panel liquid-glass liquidGlass-wrapper">
|
||||
<section class="page-section contact-layout">
|
||||
<div class="glass-panel liquid-glass liquidGlass-wrapper contact-hero">
|
||||
<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">คุยกับเรา</p>
|
||||
<h2>เล่าโจทย์ของธุรกิจคุณก่อน แล้วค่อยดูว่าควรเริ่มตรงไหน</h2>
|
||||
<button class="button button-primary" type="button" data-open-lead>ส่งโจทย์ให้เราดู</button>
|
||||
<p class="eyebrow">เริ่มต้นกับเรา</p>
|
||||
<h2>เลือกปัญหาที่ใกล้ที่สุด</h2>
|
||||
<p class="contact-hero-text">ส่งโจทย์ของคุณมาให้เราดู — ไม่ต้องเตรียม brief สมบูรณ์ แค่เล่าว่าตอนนี้ธุรกิจติดตรงไหน เราจะช่วยคุณต่อ</p>
|
||||
<button class="button button-primary" type="button" data-open-lead>เปิดฟอร์มส่งโจทย์</button>
|
||||
</div>
|
||||
|
||||
<div class="contact-info-grid">
|
||||
<a class="contact-info-card liquid-glass liquidGlass-wrapper" href="mailto:contact@moreminimore.com">
|
||||
<div class="liquidGlass-effect" aria-hidden="true"></div>
|
||||
<div class="liquidGlass-tint" aria-hidden="true"></div>
|
||||
<div class="liquidGlass-shine" aria-hidden="true"></div>
|
||||
<svg class="contact-icon" aria-hidden="true" viewBox="0 0 24 24" focusable="false">
|
||||
<path d="M22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6zm-2 0l-8 5-8-5h16zm0 12H4V8l8 5 8-5v10z" />
|
||||
</svg>
|
||||
<span>contact@moreminimore.com</span>
|
||||
</a>
|
||||
<a class="contact-info-card liquid-glass liquidGlass-wrapper" href="tel:+668****5945">
|
||||
<div class="liquidGlass-effect" aria-hidden="true"></div>
|
||||
<div class="liquidGlass-tint" aria-hidden="true"></div>
|
||||
<div class="liquidGlass-shine" aria-hidden="true"></div>
|
||||
<svg class="contact-icon" aria-hidden="true" viewBox="0 0 24 24" focusable="false">
|
||||
<path d="M6.6 10.8c1.4 2.8 3.8 5.1 6.6 6.6l2.2-2.2c.3-.3.8-.4 1.2-.3 1.3.4 2.6.6 4 .6.7 0 1.2.5 1.2 1.2v3.5c0 .7-.5 1.2-1.2 1.2C10.6 21.4 2.6 13.4 2.6 3.4c0-.7.5-1.2 1.2-1.2h3.5c.7 0 1.2.5 1.2 1.2 0 1.4.2 2.7.6 4 .1.4 0 .8-.3 1.2l-2.2 2.2Z" />
|
||||
</svg>
|
||||
<span>080-995-5945</span>
|
||||
</a>
|
||||
<a class="contact-info-card liquid-glass liquidGlass-wrapper" href="https://line.me/ti/p/@moreminimore" target="_blank" rel="noopener noreferrer">
|
||||
<div class="liquidGlass-effect" aria-hidden="true"></div>
|
||||
<div class="liquidGlass-tint" aria-hidden="true"></div>
|
||||
<div class="liquidGlass-shine" aria-hidden="true"></div>
|
||||
<img class="contact-icon" src="/images/social/line-icon.png" alt="" width="28" height="28" />
|
||||
<span>@moreminimore</span>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</PageShell>
|
||||
|
||||
<style>
|
||||
.tools-layout {
|
||||
.page-section::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page-section h2,
|
||||
.page-section h3 {
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.page-section p {
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.page-section .eyebrow {
|
||||
border-color: rgb(19 18 13 / .10);
|
||||
background: rgb(255 255 255 / .52);
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.contact-layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.contact-hero {
|
||||
text-align: center;
|
||||
padding: clamp(28px, 5vw, 48px);
|
||||
margin-bottom: clamp(24px, 4vw, 40px);
|
||||
}
|
||||
|
||||
.contact-hero h2 {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.contact-hero-text {
|
||||
max-width: 52ch;
|
||||
margin: 14px auto 20px;
|
||||
color: var(--muted);
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.65;
|
||||
}
|
||||
|
||||
.contact-info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr);
|
||||
gap: clamp(24px, 5vw, 64px);
|
||||
align-items: start;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.contact-info-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: clamp(20px, 3vw, 28px);
|
||||
border-radius: 22px;
|
||||
text-decoration: none;
|
||||
transition: transform .2s var(--ease), box-shadow .2s var(--ease);
|
||||
}
|
||||
|
||||
.contact-info-card:hover {
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
|
||||
.contact-icon {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.contact-info-card svg.contact-icon {
|
||||
fill: var(--ink);
|
||||
}
|
||||
|
||||
.contact-icon img {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.contact-info-card > span:last-child {
|
||||
color: var(--muted);
|
||||
font-size: 0.88rem;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
@media (max-width: 620px) {
|
||||
.contact-info-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.tools-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 18px;
|
||||
max-width: var(--container);
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.tools-copy {
|
||||
position: sticky;
|
||||
top: 120px;
|
||||
}
|
||||
|
||||
.tools-copy h2 {
|
||||
margin-top: 12px;
|
||||
max-width: 10ch;
|
||||
font-size: clamp(2.4rem, 5vw, 5.2rem);
|
||||
line-height: .92;
|
||||
}
|
||||
|
||||
.tools-copy p:last-child {
|
||||
margin-top: 18px;
|
||||
max-width: 34rem;
|
||||
color: rgb(255 255 255 / .72);
|
||||
font-size: clamp(1rem, .4vw + 1rem, 1.2rem);
|
||||
}
|
||||
|
||||
.tools-stack {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.tool-card {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding: clamp(22px, 4vw, 36px);
|
||||
padding: clamp(24px, 4vw, 38px);
|
||||
border: 1px solid rgb(255 255 255 / .24);
|
||||
border-radius: 28px;
|
||||
transition: border-color .25s var(--ease), transform .2s var(--ease);
|
||||
}
|
||||
|
||||
.tool-card:hover {
|
||||
border-color: var(--yellow);
|
||||
}
|
||||
|
||||
.tool-card > *:not(.liquidGlass-effect, .liquidGlass-tint, .liquidGlass-shine) {
|
||||
@@ -159,44 +259,72 @@ import { process } from '../data/site.js';
|
||||
.tool-card span {
|
||||
display: inline-flex;
|
||||
margin-bottom: 18px;
|
||||
border: 1px solid rgb(255 255 255 / .22);
|
||||
border-radius: 999px;
|
||||
padding: 6px 10px;
|
||||
color: rgb(255 255 255 / .62);
|
||||
padding: 6px 12px;
|
||||
background: var(--yellow);
|
||||
color: var(--ink);
|
||||
font-size: 12px;
|
||||
font-weight: 900;
|
||||
letter-spacing: .08em;
|
||||
}
|
||||
|
||||
.tool-card h3 {
|
||||
margin-bottom: 12px;
|
||||
font-size: clamp(1.55rem, 2vw, 2.45rem);
|
||||
margin-bottom: 14px;
|
||||
color: white;
|
||||
font-size: clamp(1.35rem, 1.8vw, 1.9rem);
|
||||
font-weight: 800;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.tool-card p {
|
||||
max-width: 42rem;
|
||||
color: rgb(255 255 255 / .72);
|
||||
font-size: 0.92rem;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
/* Full-width filter background */
|
||||
.tools-section-full {
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
padding: clamp(54px, 8vw, 104px) 0;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.tools-section-full::before {
|
||||
position: absolute;
|
||||
inset: 0 calc(50% - 50vw);
|
||||
z-index: -1;
|
||||
pointer-events: none;
|
||||
content: "";
|
||||
background: rgb(0 0 0 / .14);
|
||||
backdrop-filter: invert(1);
|
||||
-webkit-backdrop-filter: invert(1);
|
||||
}
|
||||
|
||||
.tools-section-full .section-heading {
|
||||
width: var(--container);
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.tools-section-full .section-heading h2 {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.tools-section-full .section-heading .eyebrow {
|
||||
border-color: var(--dark-line);
|
||||
background: rgb(255 255 255 / .10);
|
||||
color: rgb(255 255 255 / .72);
|
||||
}
|
||||
|
||||
.tool-card-featured {
|
||||
min-height: 260px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
background: linear-gradient(135deg, rgb(254 212 0 / .16), rgb(212 85 58 / .12));
|
||||
@media (max-width: 920px) {
|
||||
.tools-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.tools-layout {
|
||||
@media (max-width: 620px) {
|
||||
.tools-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.tools-copy {
|
||||
position: static;
|
||||
}
|
||||
|
||||
.tools-copy h2 {
|
||||
max-width: 12ch;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
---
|
||||
import PageShell from '../components/PageShell.astro';
|
||||
|
||||
import { getCollection } from 'astro:content';
|
||||
|
||||
const posts = (await getCollection('blog', ({ data }) => !data.draft)).sort(
|
||||
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf(),
|
||||
);
|
||||
|
||||
// Collect all unique categories
|
||||
const allCategories = [...new Set(posts.map((p) => p.data.category))].sort();
|
||||
---
|
||||
|
||||
<PageShell
|
||||
@@ -14,25 +16,189 @@ const posts = (await getCollection('blog', ({ data }) => !data.draft)).sort(
|
||||
>
|
||||
<section class="page-hero scene scene-light hero-oversized" data-scene="light">
|
||||
<p class="eyebrow">บทความ</p>
|
||||
<h1>บทความสำหรับธุรกิจที่อยากตัดสินใจจากข้อมูล</h1>
|
||||
<h1>ความรู้ด้าน AI และ Online Marketing</h1>
|
||||
<p class="hero-lead">
|
||||
รวมมุมมองเรื่องเว็บ การตลาด ระบบอัตโนมัติ และ AI แบบที่เน้นใช้งานจริงในธุรกิจ ไม่ใช่แค่ตามกระแส
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="page-section">
|
||||
<div class="blog-grid">
|
||||
{posts.map((post) => (
|
||||
<article class="blog-card 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 class="eyebrow">{post.data.category}</span>
|
||||
<h2>{post.data.title}</h2>
|
||||
<p>{post.data.description}</p>
|
||||
<a class="text-link" href={`/blog/${post.id}/`}>อ่านบทความ</a>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
<section class="page-section blog-section">
|
||||
<!-- Category filters -->
|
||||
<div class="blog-tags" id="blog-tags">
|
||||
<button class="blog-tag active" data-cat="all">ทั้งหมด</button>
|
||||
{allCategories.map((cat) => (
|
||||
<button class="blog-tag" data-cat={cat}>{cat}</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div class="blog-grid" id="blog-grid">
|
||||
{posts.map((post) => {
|
||||
const fmt = new Intl.DateTimeFormat('th-TH', { day: '2-digit', month: 'short', year: '2-digit' }).format(post.data.pubDate);
|
||||
const imgId = post.id === 'ai-for-sme-start-with-pain' ? 'ai' : post.id === 'marketing-automation-reduce-work' ? 'automation' : post.id === 'sme-website-next-action' ? 'website' : 'marketing';
|
||||
return (
|
||||
<a class="blog-card liquid-glass liquidGlass-wrapper" href={`/blog/${post.id}/`} data-cat={post.data.category}>
|
||||
<div class="liquidGlass-effect" aria-hidden="true"></div>
|
||||
<div class="liquidGlass-tint" aria-hidden="true"></div>
|
||||
<div class="liquidGlass-shine" aria-hidden="true"></div>
|
||||
<img class="blog-card-img" src={`/images/blog-${imgId}.jpg`} alt={post.data.title} loading="lazy" />
|
||||
<div class="blog-meta">
|
||||
<span class="eyebrow">{post.data.category}</span>
|
||||
<span class="blog-date eyebrow">{fmt}</span>
|
||||
</div>
|
||||
<h3>{post.data.title}</h3>
|
||||
<p>{post.data.description}</p>
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<p class="blog-empty" id="blog-empty" hidden>ไม่พบบทความที่ตรงกับหมวดหมู่นี้</p>
|
||||
</section>
|
||||
</PageShell>
|
||||
|
||||
<style>
|
||||
.blog-section::before { display: none; }
|
||||
|
||||
/* Category filters */
|
||||
.blog-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-bottom: clamp(20px, 3vw, 36px);
|
||||
}
|
||||
.blog-tag {
|
||||
padding: 6px 14px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid var(--line);
|
||||
background: rgb(255 255 255 / .40);
|
||||
color: var(--muted);
|
||||
font-size: 0.82rem;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
transition: all .2s var(--ease);
|
||||
}
|
||||
.blog-tag:hover,
|
||||
.blog-tag.active {
|
||||
background: var(--yellow);
|
||||
color: var(--ink);
|
||||
border-color: var(--yellow);
|
||||
}
|
||||
|
||||
/* Grid — 3 columns */
|
||||
.blog-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; }
|
||||
|
||||
/* Card */
|
||||
.blog-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
text-decoration: none;
|
||||
padding: clamp(14px, 2vw, 22px);
|
||||
border-radius: 20px;
|
||||
}
|
||||
.blog-card-img {
|
||||
width: 100%;
|
||||
aspect-ratio: 16 / 9;
|
||||
object-fit: cover;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
/* Meta row — category + date side by side */
|
||||
.blog-meta {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.blog-meta .eyebrow {
|
||||
background: var(--yellow);
|
||||
color: var(--ink);
|
||||
border-color: transparent;
|
||||
font-size: 0.75rem;
|
||||
padding: 3px 10px;
|
||||
}
|
||||
.blog-meta .blog-date.eyebrow {
|
||||
background: #ffffff85;
|
||||
color: var(--ink);
|
||||
border-color: rgb(19 18 13 / .14);
|
||||
opacity: 1;
|
||||
}
|
||||
.blog-date {
|
||||
color: var(--ink);
|
||||
font-size: 0.78rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.blog-card h3 {
|
||||
color: var(--ink);
|
||||
font-size: 1.1rem;
|
||||
font-weight: 800;
|
||||
line-height: 1.35;
|
||||
margin: 0 0 6px;
|
||||
}
|
||||
.blog-card p {
|
||||
color: var(--muted);
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.55;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.blog-empty {
|
||||
text-align: center;
|
||||
color: var(--muted);
|
||||
font-size: 1.1rem;
|
||||
padding: clamp(40px, 6vw, 80px) 0;
|
||||
}
|
||||
|
||||
@media (max-width: 820px) {
|
||||
.blog-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
}
|
||||
@media (max-width: 540px) {
|
||||
.blog-grid { grid-template-columns: 1fr; }
|
||||
.blog-card {
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
.blog-meta {
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
margin-inline: auto;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.blog-card h3,
|
||||
.blog-card p {
|
||||
margin-inline: auto;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
const tagsEl = document.getElementById('blog-tags');
|
||||
const grid = document.getElementById('blog-grid');
|
||||
const empty = document.getElementById('blog-empty');
|
||||
const cards = grid?.querySelectorAll('.blog-card');
|
||||
const tagBtns = tagsEl?.querySelectorAll('.blog-tag');
|
||||
|
||||
if (tagBtns && cards) {
|
||||
tagBtns.forEach((btn) => {
|
||||
btn.addEventListener('click', () => {
|
||||
const cat = btn.dataset.cat;
|
||||
tagBtns.forEach((b) => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
let visible = 0;
|
||||
cards.forEach((card) => {
|
||||
if (cat === 'all' || card.dataset.cat === cat) {
|
||||
card.style.display = '';
|
||||
visible++;
|
||||
} else {
|
||||
card.style.display = 'none';
|
||||
}
|
||||
});
|
||||
empty.hidden = visible > 0;
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -33,21 +33,34 @@ const formattedDate = new Intl.DateTimeFormat('th-TH', {
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="blog-feature-image">
|
||||
{['ai-for-sme-start-with-pain', 'marketing-automation-reduce-work', 'sme-website-next-action'].includes(post.id) ? (
|
||||
<img src={`/images/blog-${post.id === 'ai-for-sme-start-with-pain' ? 'ai' : post.id === 'marketing-automation-reduce-work' ? 'automation' : 'website'}.jpg`} alt={post.data.title} />
|
||||
) : (
|
||||
<img src="/images/blog-marketing.jpg" alt={post.data.title} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div class="blog-article-shell">
|
||||
<div class="blog-prose">
|
||||
<Content />
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<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">ขั้นตอนถัดไป</p>
|
||||
<h2>อ่านแล้วเจอโจทย์คล้ายกัน ส่งปัญหามาให้เราช่วยดูก่อนได้</h2>
|
||||
<button class="button button-primary" type="button" data-open-lead>ส่งโจทย์ให้เราดู</button>
|
||||
</div>
|
||||
</section>
|
||||
</PageShell>
|
||||
|
||||
<style>
|
||||
.blog-article-hero { padding-bottom: clamp(36px, 5vw, 64px); }
|
||||
|
||||
.blog-feature-image {
|
||||
max-width: var(--container);
|
||||
margin: 2rem auto 1rem;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.blog-feature-image img {
|
||||
width: 100%;
|
||||
border-radius: 20px;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
---
|
||||
import PageShell from '../components/PageShell.astro';
|
||||
import { problems } from '../data/site.js';
|
||||
---
|
||||
|
||||
<PageShell
|
||||
title="ติดต่อ | MoreminiMore"
|
||||
description="ติดต่อ MoreminiMore เพื่อส่งโจทย์เว็บไซต์ การตลาด ระบบอัตโนมัติ หรือ AI ให้เราช่วยดูว่าควรเริ่มตรงไหน"
|
||||
>
|
||||
<section class="page-hero scene scene-light hero-oversized" data-scene="light">
|
||||
<p class="eyebrow">ติดต่อ</p>
|
||||
<h1>ส่งโจทย์ให้เราดู แล้วค่อยตัดสินใจว่าจะทำอะไร</h1>
|
||||
<p class="hero-lead">
|
||||
ไม่ต้องเตรียม brief สมบูรณ์ แค่เล่าว่าตอนนี้ธุรกิจติดตรงไหน เราจะช่วยดูว่าควรถามอะไรต่อและควรเริ่มจากจุดไหน
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="page-section contact-layout">
|
||||
<div class="glass-panel liquid-glass liquidGlass-wrapper contact-card">
|
||||
<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">เริ่มต้นที่นี่</p>
|
||||
<h2>เลือกปัญหาที่ใกล้ที่สุด</h2>
|
||||
<div class="contact-problem-list">
|
||||
{problems.map(([, label]) => <span>{label}</span>)}
|
||||
</div>
|
||||
<button class="button button-primary" type="button" data-open-lead>เปิดฟอร์มส่งโจทย์</button>
|
||||
</div>
|
||||
|
||||
<aside class="contact-info">
|
||||
<p class="eyebrow">ข้อมูลติดต่อ</p>
|
||||
<h2>ช่องทางติดต่อ</h2>
|
||||
<dl>
|
||||
<div>
|
||||
<dt>Email</dt>
|
||||
<dd><a href="mailto:contact@moreminimore.com">contact@moreminimore.com</a></dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Phone</dt>
|
||||
<dd><a href="tel:+66809955945">080-995-5945</a></dd>
|
||||
</div>
|
||||
</dl>
|
||||
<p>
|
||||
ถ้าโจทย์ยังไม่ชัด ให้ส่งเป็นภาษาธรรมดาได้เลย เช่น เว็บมีคนเข้าแต่ไม่ค่อยมีคนทัก หรือยิงแอดแล้วไม่แน่ใจว่างบหายไปตรงไหน
|
||||
</p>
|
||||
</aside>
|
||||
</section>
|
||||
</PageShell>
|
||||
@@ -95,6 +95,20 @@ import { portfolio } from '../data/site.js';
|
||||
}
|
||||
|
||||
@media (max-width: 920px) {
|
||||
.portfolio-page .section-heading {
|
||||
grid-template-columns: 1fr;
|
||||
justify-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.section-heading .portfolio-design-note {
|
||||
grid-column: 1 / -1;
|
||||
width: 100%;
|
||||
max-width: 58ch;
|
||||
margin-inline: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.portfolio-page .portfolio-card,
|
||||
.portfolio-page .portfolio-card.featured {
|
||||
grid-column: span 6;
|
||||
@@ -102,9 +116,48 @@ import { portfolio } from '../data/site.js';
|
||||
}
|
||||
|
||||
@media (max-width: 620px) {
|
||||
.page-hero.hero-oversized {
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.page-hero.hero-oversized h1,
|
||||
.page-hero.hero-oversized .hero-lead {
|
||||
margin-inline: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.page-hero.hero-oversized h1 {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.page-hero.hero-oversized .hero-lead {
|
||||
max-width: 34ch;
|
||||
}
|
||||
|
||||
.portfolio-page .section-heading h2 {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.section-heading .portfolio-design-note {
|
||||
max-width: 34ch;
|
||||
}
|
||||
|
||||
.portfolio-page .portfolio-card,
|
||||
.portfolio-page .portfolio-card.featured {
|
||||
grid-column: span 12;
|
||||
border-radius: 22px;
|
||||
}
|
||||
|
||||
.portfolio-page .portfolio-card img {
|
||||
aspect-ratio: 16 / 9;
|
||||
object-position: top center;
|
||||
}
|
||||
|
||||
.portfolio-page .portfolio-card div {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
import PageShell from '../../components/PageShell.astro';
|
||||
import { services, process } from '../../data/site.js';
|
||||
import { services, portfolio } from '../../data/site.js';
|
||||
|
||||
export function getStaticPaths() {
|
||||
return services.map((service) => ({
|
||||
@@ -11,86 +11,291 @@ export function getStaticPaths() {
|
||||
|
||||
const { service } = Astro.props;
|
||||
const relatedServices = services.filter((item) => item.slug !== service.slug);
|
||||
const cases = portfolio.filter((p) => p.tag.includes(service.name));
|
||||
const isWD = service.slug === 'website-development';
|
||||
const isMC = service.slug === 'marketing-consult';
|
||||
const isAuto = service.slug === 'automation-workflow';
|
||||
const isAI = service.slug === 'ai-consult';
|
||||
const approachCols = service.approach.length === 4 ? '2' : '3';
|
||||
const datarootCase = cases.find((p) => p.name === 'Dataroot');
|
||||
---
|
||||
|
||||
<PageShell
|
||||
title={`${service.name} | MoreminiMore`}
|
||||
description={`${service.name} จาก MoreminiMore: ${service.copy}`}
|
||||
>
|
||||
<section class="page-hero service-page-hero scene scene-light" data-scene="light">
|
||||
<div class="page-hero-grid">
|
||||
<div>
|
||||
<p class="eyebrow">{service.badge}</p>
|
||||
<h1>{service.headline}</h1>
|
||||
</div>
|
||||
<div class="service-hero-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>
|
||||
<span>{service.name}</span>
|
||||
<p>{service.copy}</p>
|
||||
<button class="button button-primary" type="button" data-open-lead>ส่งโจทย์บริการนี้</button>
|
||||
</div>
|
||||
<!-- 1. Hero -->
|
||||
<section class="page-hero scene scene-light hero-oversized" data-scene="light">
|
||||
<p class="eyebrow">{service.badge}</p>
|
||||
<h1>{service.headline}</h1>
|
||||
<p class="hero-lead">{service.copy}</p>
|
||||
</section>
|
||||
|
||||
<!-- 2. Pain Points -->
|
||||
<section class="page-section-light">
|
||||
<div class="section-heading">
|
||||
<p class="eyebrow">คุณกำลังเจอแบบนี้อยู่หรือเปล่า?</p>
|
||||
<h2>ปัญหาเหล่านี้คือสิ่งที่เราเจอบ่อยที่สุด</h2>
|
||||
</div>
|
||||
<div class="service-pain-grid">
|
||||
{service.painPoints.map((item, i) => (
|
||||
<div class="service-pain-card 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 class="service-pain-num">{String(i + 1).padStart(2, '0')}</span>
|
||||
<p>{item}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="page-section service-story-section scene scene-light" data-scene="light">
|
||||
<div class="section-heading">
|
||||
<p class="eyebrow">วินิจฉัยก่อน</p>
|
||||
<h2>เริ่มจากดูว่าโจทย์นี้ควรแก้ตรงไหนก่อน</h2>
|
||||
</div>
|
||||
<div class="service-story-grid">
|
||||
<article>
|
||||
<h3>ปัญหาที่มักเจอ</h3>
|
||||
<ul>
|
||||
{service.painPoints.map((item) => <li>{item}</li>)}
|
||||
</ul>
|
||||
</article>
|
||||
<article>
|
||||
<h3>วิธีที่เราเข้าไปช่วย</h3>
|
||||
<ul>
|
||||
{service.approach.map((item) => <li>{item}</li>)}
|
||||
</ul>
|
||||
</article>
|
||||
<article>
|
||||
<h3>สิ่งที่ได้จากงานนี้</h3>
|
||||
<ul>
|
||||
{service.deliverables.map((item) => <li>{item}</li>)}
|
||||
</ul>
|
||||
</article>
|
||||
<!-- 3. Why It Matters (dark) -->
|
||||
<section class="page-section scene-dark why-section" data-scene="dark">
|
||||
<div class="why-layout">
|
||||
<p class="eyebrow">ทำไมต้องแก้ตอนนี้</p>
|
||||
{typeof service.whyItMatters === 'object' ? (
|
||||
<>
|
||||
<h2>{service.whyItMatters.heading}</h2>
|
||||
<div class="why-cards-grid">
|
||||
{service.whyItMatters.cards.map((card) => (
|
||||
<div class="why-card 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>
|
||||
<strong>{card.label}</strong>
|
||||
<p>{card.desc}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<h2>ถ้าไม่แก้ — จะเกิดอะไรขึ้น?</h2>
|
||||
<p class="why-text">{service.whyItMatters}</p>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="case-section service-proof-section scene scene-dark" data-scene="dark">
|
||||
<!-- 4. Our Approach -->
|
||||
<section class="page-section-light">
|
||||
<div class="section-heading">
|
||||
<p class="eyebrow">สิ่งที่สำคัญ</p>
|
||||
<h2>{service.objective}</h2>
|
||||
<p class="eyebrow">เราแตกต่างยังไง</p>
|
||||
<h2>วิธีที่เราเข้าไปช่วย — ไม่เหมือนที่อื่น</h2>
|
||||
</div>
|
||||
<div class="service-proof-grid">
|
||||
<article class="case-story 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>
|
||||
<span>{service.name}</span>
|
||||
<h3>{service.proof}</h3>
|
||||
<p>{service.detail}</p>
|
||||
</article>
|
||||
<div class="process-grid">
|
||||
{process.map(([title, copy], index) => (
|
||||
<article>
|
||||
<span>{String(index + 1).padStart(2, '0')}</span>
|
||||
<h3>{title}</h3>
|
||||
<p>{copy}</p>
|
||||
</article>
|
||||
{isMC || isAuto || isAI ? (
|
||||
<div class="service-timeline">
|
||||
{service.approach.map((item, i) => (
|
||||
<div class="timeline-item">
|
||||
<span class="timeline-dot">{String(i + 1).padStart(2, '0')}</span>
|
||||
<div class="timeline-card 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>{item}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div class={`service-approach-grid cols-${approachCols}`}>
|
||||
{service.approach.map((item, i) => (
|
||||
<div class="service-approach-card 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 class="service-approach-num">{String(i + 1).padStart(2, '0')}</span>
|
||||
<p>{item}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
<!-- 5. What You Get -->
|
||||
<section class="page-section-light">
|
||||
<div class="section-heading">
|
||||
<p class="eyebrow">สิ่งที่คุณจะได้รับ</p>
|
||||
<h2>หลังทำงานกับเรา — คุณจะได้อะไร?</h2>
|
||||
</div>
|
||||
{isWD || isMC || isAuto || isAI ? (
|
||||
<div class="service-deliver-list">
|
||||
{service.deliverables.map((item, i) => (
|
||||
<div class="service-deliver-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 class="service-deliver-check" aria-hidden="true">✓</span>
|
||||
<p>{item}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div class="service-deliver-grid">
|
||||
{service.deliverables.map((item, i) => (
|
||||
<div class="service-deliver-card 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 class="service-deliver-num">{String(i + 1).padStart(2, '0')}</span>
|
||||
<p>{item}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
<!-- 6. Case Study (dark) -->
|
||||
{isAuto || isAI ? null : isMC ? (
|
||||
<section class="case-section scene scene-dark" data-scene="dark">
|
||||
<div class="section-heading">
|
||||
<p class="eyebrow">กรณีศึกษา</p>
|
||||
<div>
|
||||
<h2>Dataroot</h2>
|
||||
<p>บริษัทให้บริการ ERP Software และการปรับแต่ง ERP Software สำหรับองค์กรขนาดใหญ่</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="case-grid">
|
||||
<article class="case-story 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="case-story-title">เราทำอะไรบ้าง กับลูกค้าเจ้านี้</p>
|
||||
<div class="story-step">
|
||||
<span>01</span>
|
||||
<h3>ปัญหา</h3>
|
||||
<p>ยิงโฆษณาและทำการตลาดอยู่แล้ว แต่ต้องดูมีการใช้งบประมาณสูงมาก โดยลูกค้าที่ได้มาไม่คุ้มค่ากับงบประมาณที่จ่ายไป</p>
|
||||
</div>
|
||||
<div class="story-step">
|
||||
<span>02</span>
|
||||
<h3>สิ่งที่พบ</h3>
|
||||
<p>ตั้งค่าโฆษณากว้างมากเกินไป ทำให้เสียงบประมาณไปกับกลุ่มคนที่ไม่ใช่เป้าหมาย</p>
|
||||
</div>
|
||||
<div class="story-step">
|
||||
<span>03</span>
|
||||
<h3>สิ่งที่ปรับ</h3>
|
||||
<p>ปรับการตั้งค่าโดยโฟกัสกลุ่มเป้าหมาย เพื่อให้โฆษณาไปแสดงเฉพาะกลุ่มคนที่น่าจะเป็นลูกค้า</p>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<div class="case-proof">
|
||||
{datarootCase && <img src={datarootCase.image} alt="Dataroot website screenshot" loading="lazy" />}
|
||||
<div class="metric-card">
|
||||
<strong>+373%</strong>
|
||||
<span>impression</span>
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
<strong>+114.2%</strong>
|
||||
<span>click</span>
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
<strong>−28.3%</strong>
|
||||
<span>ad spend</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
) : (
|
||||
<section class="service-case-section" data-scene="dark">
|
||||
<div class="section-heading">
|
||||
<p class="eyebrow">เราเคยทำมาแล้ว</p>
|
||||
<h2>นี่คือผลลัพธ์จากลูกค้าจริง</h2>
|
||||
</div>
|
||||
|
||||
{cases.length > 0 ? (
|
||||
<div class="portfolio-grid service-case-grid">
|
||||
{cases.map((item) => (
|
||||
<a class="portfolio-card featured liquid-glass liquidGlass-wrapper" href={item.href} target="_blank" rel="noopener noreferrer">
|
||||
<div class="liquidGlass-effect" aria-hidden="true"></div>
|
||||
<div class="liquidGlass-tint" aria-hidden="true"></div>
|
||||
<div class="liquidGlass-shine" aria-hidden="true"></div>
|
||||
<img src={item.image} alt={`${item.name} website screenshot`} loading="lazy" />
|
||||
<div>
|
||||
<span>{item.tag}</span>
|
||||
<h3>{item.name}</h3>
|
||||
<p>{item.description}</p>
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p class="service-no-case">บริการนี้เป็นบริการใหม่ เรากำลังรวบรวมผลงานตัวอย่าง — ส่งโจทย์ของคุณมาเป็นเคสแรกกับเรา</p>
|
||||
)}
|
||||
|
||||
<button class="button button-primary service-case-cta" type="button" data-open-lead>ส่งโจทย์ให้เราดู</button>
|
||||
</section>
|
||||
)}
|
||||
|
||||
<!-- 7. Packages (website-dev only) -->
|
||||
{isWD && service.packages && (
|
||||
<section class="page-section-light">
|
||||
<div class="section-heading">
|
||||
<p class="eyebrow">รูปแบบเว็บไซต์</p>
|
||||
<h2>เราให้คุณเลือกระบบที่เหมาะกับธุรกิจ</h2>
|
||||
</div>
|
||||
<div class="service-pkg-grid">
|
||||
{service.packages.map((pkg) => (
|
||||
<div class="service-pkg-card 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>
|
||||
<div class="service-pkg-header">
|
||||
<img class="service-pkg-logo" src={`/images/${pkg.icon}-logo.svg`} alt={pkg.name} width="48" height="48" />
|
||||
<div>
|
||||
<h3>{pkg.name}</h3>
|
||||
<p class="service-pkg-suit">{pkg.suit}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="service-pkg-body">
|
||||
<ul class="service-pkg-features">
|
||||
{pkg.features.map((f) => <li>{f}</li>)}
|
||||
</ul>
|
||||
<div class="service-pkg-pricing">
|
||||
<div class="service-pkg-price-row">
|
||||
<span>เว็บไซต์</span>
|
||||
<strong>เริ่มต้น {pkg.price} บาท</strong>
|
||||
</div>
|
||||
<div class="service-pkg-price-row">
|
||||
<span>Hosting</span>
|
||||
<strong>{pkg.hosting === '0' ? 'เริ่มต้น 10,000 บาท/ปี (ฟรีปีแรก)' : `${pkg.hosting} บาท/ปี`}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{service.packageNote && (
|
||||
<p class="service-pkg-note">📝 {service.packageNote}</p>
|
||||
)}
|
||||
</section>
|
||||
)}
|
||||
|
||||
<!-- 8. FAQ -->
|
||||
<section class="page-section-light">
|
||||
<div class="section-heading">
|
||||
<p class="eyebrow">คำถามที่พบบ่อย</p>
|
||||
<h2>ทุกคำถามที่คุณอาจสงสัย — ตอบตรงนี้</h2>
|
||||
</div>
|
||||
<div class="service-faq-grid">
|
||||
{service.faqs.map((item) => (
|
||||
<div class="service-faq-card 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>
|
||||
<h3>{item.question}</h3>
|
||||
<p>{item.answer}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="page-section page-section-tight scene scene-light" data-scene="light">
|
||||
<!-- 9. Related -->
|
||||
<section class="page-section-light page-section-light-tight">
|
||||
<div class="section-heading">
|
||||
<p class="eyebrow">บริการอื่น ๆ</p>
|
||||
<h2>บางโจทย์อาจต้องเริ่มจากบริการอื่นก่อน</h2>
|
||||
<p class="eyebrow">บริการอื่นที่เกี่ยวข้อง</p>
|
||||
<h2>บางทีปัญหาเริ่มจากจุดอื่น — ลองดูบริการเหล่านี้</h2>
|
||||
</div>
|
||||
<div class="related-service-grid">
|
||||
{relatedServices.map((item) => (
|
||||
@@ -106,14 +311,177 @@ const relatedServices = services.filter((item) => item.slug !== service.slug);
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<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">ขั้นตอนถัดไป</p>
|
||||
<h2>เล่าโจทย์ของคุณก่อน แล้วเราช่วยดูว่าบริการนี้ใช่จุดเริ่มต้นไหม</h2>
|
||||
<button class="button button-primary" type="button" data-open-lead>ส่งโจทย์ให้เราดู</button>
|
||||
</div>
|
||||
</section>
|
||||
</PageShell>
|
||||
|
||||
<style>
|
||||
/* ── Light Section (no filter) ── */
|
||||
.page-section-light { position: relative; padding: clamp(54px, 8vw, 104px) 0; width: var(--container); margin-inline: auto; }
|
||||
.page-section-light-tight { padding: clamp(40px, 7vw, 88px) 0; }
|
||||
.page-section-light .section-heading h2 { color: var(--ink); }
|
||||
.page-section-light .eyebrow { border-color: rgb(19 18 13 / .10); background: rgb(255 255 255 / .52); color: var(--muted); }
|
||||
|
||||
/* ── Pain Points ── */
|
||||
.service-pain-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; }
|
||||
.service-pain-card { display: flex; flex-direction: column; gap: 16px; padding: clamp(22px, 3vw, 32px); border-radius: 22px; transition: transform .2s var(--ease), box-shadow .2s var(--ease); }
|
||||
.service-pain-card:hover { transform: scale(1.03); }
|
||||
.service-pain-num { width: 52px; height: 52px; display: grid; place-items: center; border-radius: 16px; background: var(--yellow); color: var(--ink); font-size: 1.25rem; font-weight: 900; flex: 0 0 auto; }
|
||||
.service-pain-card p { color: var(--ink); font-size: 1.05rem; font-weight: 700; line-height: 1.45; }
|
||||
|
||||
/* ── Why It Matters ── */
|
||||
.why-section { position: relative; isolation: isolate; color: white; }
|
||||
.why-section::before { position: absolute; inset: 0 calc(50% - 50vw); z-index: -1; content: ""; background: rgb(0 0 0 / .22); backdrop-filter: invert(1); -webkit-backdrop-filter: invert(1); }
|
||||
.why-layout { width: var(--container); margin-inline: auto; position: relative; z-index: 1; padding: clamp(40px, 7vw, 80px) 0; }
|
||||
.why-layout h2 { margin-top: 12px; color: white; font-size: clamp(2.4rem, 4vw, 4rem); }
|
||||
.why-text { margin-top: clamp(16px, 3vw, 28px); color: rgb(255 255 255 / .82); font-size: clamp(1.1rem, 1.5vw, 1.35rem); font-weight: 600; line-height: 1.7; max-width: 48ch; }
|
||||
|
||||
/* Why Cards (website-dev) */
|
||||
.why-cards-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; margin-top: clamp(20px, 3vw, 36px); }
|
||||
.why-card { padding: clamp(22px, 3vw, 32px); border-radius: 22px; border: 1px solid transparent; transition: border-color .25s var(--ease); }
|
||||
.why-card:hover { border-color: var(--yellow); }
|
||||
.why-card strong { display: block; margin-bottom: 10px; color: var(--yellow); font-size: 1.1rem; font-weight: 800; letter-spacing: .02em; }
|
||||
.why-card p { color: rgb(255 255 255 / .78); font-size: 0.95rem; line-height: 1.65; }
|
||||
|
||||
/* ── Approach Grid ── */
|
||||
.service-approach-grid { display: grid; gap: 18px; }
|
||||
.service-approach-grid.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
||||
.service-approach-grid.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
.service-approach-grid.cols-mc { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
.service-approach-grid.cols-mc .service-approach-card:last-child { grid-column: 1 / -1; max-width: 480px; justify-self: center; }
|
||||
.service-approach-card { display: flex; flex-direction: column; gap: 16px; padding: clamp(22px, 3vw, 32px); border-radius: 22px; transition: transform .2s var(--ease); }
|
||||
.service-approach-card:hover { transform: scale(1.03); }
|
||||
.service-approach-num { width: 52px; height: 52px; display: grid; place-items: center; border-radius: 16px; background: var(--yellow); color: var(--ink); font-size: 1.25rem; font-weight: 900; flex: 0 0 auto; }
|
||||
.service-approach-card p { color: var(--ink); font-size: 1.05rem; font-weight: 700; line-height: 1.45; }
|
||||
|
||||
/* Approach Timeline (marketing-consult) */
|
||||
.service-timeline {
|
||||
position: relative;
|
||||
padding-left: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.timeline-item {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: 52px 1fr;
|
||||
gap: clamp(20px, 3vw, 32px);
|
||||
padding-bottom: clamp(24px, 4vw, 40px);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.timeline-item:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
/* vertical line */
|
||||
.timeline-item::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 25px;
|
||||
top: 52px;
|
||||
bottom: 0;
|
||||
width: 2px;
|
||||
background: linear-gradient(to bottom, var(--yellow), rgb(19 18 13 / .10));
|
||||
}
|
||||
|
||||
.timeline-item:last-child::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.timeline-dot {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: 50%;
|
||||
background: var(--yellow);
|
||||
color: var(--ink);
|
||||
font-size: 1.25rem;
|
||||
font-weight: 900;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0 0 0 6px rgb(255 255 255 / .52), 0 4px 16px rgb(254 212 0 / .28);
|
||||
}
|
||||
|
||||
.timeline-card {
|
||||
padding: clamp(18px, 3vw, 28px);
|
||||
border-radius: 22px;
|
||||
transition: transform .2s var(--ease);
|
||||
}
|
||||
|
||||
.timeline-card:hover {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
.timeline-card p {
|
||||
color: var(--ink);
|
||||
font-size: 1.08rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
/* ── Deliverables ── */
|
||||
.service-deliver-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; }
|
||||
.service-deliver-card { display: flex; flex-direction: column; gap: 16px; padding: clamp(22px, 3vw, 32px); border-radius: 22px; transition: transform .2s var(--ease); }
|
||||
.service-deliver-card:hover { transform: scale(1.03); }
|
||||
.service-deliver-num { width: 52px; height: 52px; display: grid; place-items: center; border-radius: 16px; background: var(--yellow); color: var(--ink); font-size: 1.25rem; font-weight: 900; flex: 0 0 auto; }
|
||||
.service-deliver-card p { color: var(--ink); font-size: 1.05rem; font-weight: 700; line-height: 1.45; }
|
||||
|
||||
/* Deliverables List (website-dev) */
|
||||
.service-deliver-list { display: flex; flex-direction: column; gap: 14px; }
|
||||
.service-deliver-item { display: flex; align-items: center; gap: 16px; padding: clamp(18px, 3vw, 28px); border-radius: 22px; transition: transform .2s var(--ease); }
|
||||
.service-deliver-item:hover { transform: scale(1.03); }
|
||||
.service-deliver-check { display: grid; place-items: center; width: 36px; height: 36px; border-radius: 12px; background: var(--yellow); color: var(--ink); font-size: 1.1rem; font-weight: 900; flex: 0 0 auto; }
|
||||
.service-deliver-item p { color: var(--ink); font-size: 1.08rem; font-weight: 700; line-height: 1.5; }
|
||||
|
||||
/* ── Case Study ── */
|
||||
.service-case-section { position: relative; isolation: isolate; padding: clamp(54px, 8vw, 104px) 0; color: white; }
|
||||
.service-case-section::before { position: absolute; inset: 0 calc(50% - 50vw); z-index: -1; content: ""; background: rgb(0 0 0 / .18); backdrop-filter: invert(1); -webkit-backdrop-filter: invert(1); }
|
||||
.service-case-section .section-heading { width: var(--container); margin-inline: auto; }
|
||||
.service-case-section .section-heading h2 { color: white; }
|
||||
.service-case-section .eyebrow { border-color: var(--dark-line); background: rgb(255 255 255 / .10); color: rgb(255 255 255 / .72); }
|
||||
.service-case-grid { max-width: var(--container); margin-inline: auto; grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
.service-case-grid .portfolio-card { grid-column: span 1; }
|
||||
.service-case-grid .portfolio-card img { aspect-ratio: 16 / 10; }
|
||||
.service-no-case { width: var(--container); margin: 0 auto; color: rgb(255 255 255 / .72); font-size: 1.05rem; text-align: center; padding: clamp(32px, 6vw, 64px) 0; }
|
||||
.service-case-cta { display: block; margin: clamp(20px, 3vw, 32px) auto 0; width: fit-content; }
|
||||
|
||||
/* ── Packages (website-dev) ── */
|
||||
.service-pkg-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
|
||||
.service-pkg-card { display: flex; flex-direction: column; padding: clamp(28px, 4vw, 40px); border-radius: 28px; text-align: left; transition: background .8s var(--ease), transform .7s var(--ease); }
|
||||
.service-pkg-card:hover { background: linear-gradient(135deg, #fed400, #ffffff52); transform: scale(1.01); }
|
||||
.service-pkg-header { display: flex; align-items: center; gap: 16px; margin-bottom: 20px; }
|
||||
.service-pkg-logo { width: 48px; height: 48px; flex: 0 0 auto; border-radius: 12px; }
|
||||
.service-pkg-header h3 { color: var(--ink); font-size: 1.35rem; font-weight: 800; margin: 0 0 4px; }
|
||||
.service-pkg-suit { color: var(--muted); font-size: 0.88rem; font-weight: 600; line-height: 1.55; }
|
||||
.service-pkg-body { display: flex; flex-direction: column; gap: 18px; flex: 1; }
|
||||
.service-pkg-features { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; }
|
||||
.service-pkg-features li { position: relative; padding-left: 22px; color: var(--ink); font-size: 0.92rem; line-height: 1.6; }
|
||||
.service-pkg-features li::before { position: absolute; left: 0; top: .15em; content: '→ '; color: var(--ink); font-weight: 700; font-size: 0.85rem; }
|
||||
.service-pkg-pricing { display: flex; flex-direction: column; gap: 8px; padding-top: 16px; border-top: 1px solid rgb(19 18 13 / .10); }
|
||||
.service-pkg-price-row { display: flex; justify-content: space-between; align-items: baseline; }
|
||||
.service-pkg-price-row span { color: var(--muted); font-size: 0.85rem; }
|
||||
.service-pkg-price-row strong { color: var(--ink); font-size: 1rem; font-weight: 800; }
|
||||
.service-pkg-note { max-width: var(--container); margin: clamp(16px, 3vw, 28px) auto 0; color: var(--muted); font-size: 0.88rem; line-height: 1.6; text-align: center; }
|
||||
|
||||
/* ── FAQ ── */
|
||||
.service-faq-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
|
||||
.service-faq-card { padding: clamp(22px, 3vw, 32px); border-radius: 22px; transition: transform .2s var(--ease); }
|
||||
.service-faq-card:hover { transform: scale(1.03); }
|
||||
.service-faq-card h3 { color: var(--ink); font-size: 1.2rem; font-weight: 800; margin-bottom: 10px; }
|
||||
.service-faq-card p { color: var(--muted); line-height: 1.65; }
|
||||
|
||||
/* ── Related Services ── */
|
||||
.related-service-card { transition: background .8s var(--ease), transform .7s var(--ease); }
|
||||
.related-service-card:hover { background: linear-gradient(135deg, #fed400, #ffffff52); transform: scale(1.01); }
|
||||
|
||||
/* ── Responsive ── */
|
||||
@media (max-width: 920px) {
|
||||
.service-pain-grid, .service-approach-grid, .service-deliver-grid, .why-cards-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
}
|
||||
@media (max-width: 620px) {
|
||||
.service-pain-grid, .service-approach-grid, .service-deliver-grid, .service-faq-grid, .service-case-grid, .service-pkg-grid, .related-service-grid, .why-cards-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -41,19 +41,31 @@ function closePanel() {
|
||||
panel?.setAttribute('aria-hidden', 'true');
|
||||
}
|
||||
|
||||
function closeNav() {
|
||||
body.classList.remove('nav-open');
|
||||
nav?.classList.remove('is-open');
|
||||
serviceWrap?.classList.remove('is-open');
|
||||
navToggle?.setAttribute('aria-expanded', 'false');
|
||||
serviceToggle?.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
|
||||
openButtons.forEach((button) => button.addEventListener('click', openPanel));
|
||||
closeButtons.forEach((button) => button.addEventListener('click', closePanel));
|
||||
backdrop?.addEventListener('click', closePanel);
|
||||
backdrop?.addEventListener('click', () => {
|
||||
closePanel();
|
||||
closeNav();
|
||||
});
|
||||
|
||||
window.addEventListener('keydown', (event) => {
|
||||
if (event.key === 'Escape') {
|
||||
closePanel();
|
||||
serviceWrap?.classList.remove('is-open');
|
||||
closeNav();
|
||||
}
|
||||
});
|
||||
|
||||
navToggle?.addEventListener('click', () => {
|
||||
const isOpen = nav?.classList.toggle('is-open');
|
||||
body.classList.toggle('nav-open', Boolean(isOpen));
|
||||
navToggle.setAttribute('aria-expanded', String(Boolean(isOpen)));
|
||||
});
|
||||
|
||||
@@ -65,8 +77,7 @@ serviceToggle?.addEventListener('click', () => {
|
||||
navMenu?.addEventListener('click', (event) => {
|
||||
const target = event.target;
|
||||
if (target instanceof HTMLAnchorElement) {
|
||||
nav?.classList.remove('is-open');
|
||||
navToggle?.setAttribute('aria-expanded', 'false');
|
||||
closeNav();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -164,19 +175,24 @@ form?.addEventListener('submit', async (event) => {
|
||||
setStatus('กำลังส่งโจทย์...', '');
|
||||
|
||||
try {
|
||||
await fetch(endpoint, {
|
||||
const response = await fetch(endpoint, {
|
||||
method: 'POST',
|
||||
mode: 'no-cors',
|
||||
headers: {
|
||||
'Content-Type': 'text/plain;charset=utf-8',
|
||||
},
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const body = await response.json().catch(() => ({}));
|
||||
throw new Error(body.error || `Server error (${response.status})`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
if (!result.ok) throw new Error(result.error || 'Unknown error');
|
||||
|
||||
form.reset();
|
||||
setStatus(`ได้รับโจทย์แล้ว ${diagnosis} เราจะติดต่อกลับทางเบอร์หรืออีเมลที่ให้ไว้`, 'success');
|
||||
} catch (error) {
|
||||
setStatus('ส่งไม่สำเร็จ กรุณาลองใหม่อีกครั้ง', 'error');
|
||||
setStatus(error instanceof Error ? error.message : 'ส่งไม่สำเร็จ กรุณาลองใหม่อีกครั้ง', 'error');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -349,6 +349,10 @@ box-shadow: inset 1px 1px 0 rgb(255 255 255 / .72);
|
||||
isolation: auto;
|
||||
}
|
||||
|
||||
.services-section.scene {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.hero {
|
||||
min-height: 100svh;
|
||||
padding: 150px 0 88px;
|
||||
@@ -534,6 +538,11 @@ gap: 18px;
|
||||
padding: clamp(22px, 4vw, 34px);
|
||||
border: 1px solid rgb(255 255 255 / .56);
|
||||
border-radius: 26px;
|
||||
transition: transform .2s var(--ease);
|
||||
}
|
||||
|
||||
.blog-card:hover {
|
||||
transform: scale(1.03);
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
@@ -743,6 +752,12 @@ border: 1px solid var(--line);
|
||||
border-radius: 24px;
|
||||
background: rgb(255 255 255 / .24);
|
||||
padding: clamp(20px, 3vw, 28px);
|
||||
transition: background .8s var(--ease), transform .7s var(--ease);
|
||||
}
|
||||
|
||||
.related-service-card:hover {
|
||||
background: linear-gradient(135deg, #fed400, #ffffff52);
|
||||
transform: scale(1.01);
|
||||
}
|
||||
|
||||
.service-story-grid ul {
|
||||
@@ -1054,6 +1069,11 @@ border: 0;
|
||||
border-radius: var(--radius);
|
||||
background: transparent;
|
||||
box-shadow: var(--shadow);
|
||||
transition: transform .2s var(--ease);
|
||||
}
|
||||
|
||||
.glass-panel:hover {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
.glass-filter {
|
||||
@@ -1730,6 +1750,11 @@ linear-gradient(150deg, rgb(255 255 255 / .06), rgb(254 212 0 / .08));
|
||||
border-radius: 24px;
|
||||
background: rgb(255 255 255 / .06);
|
||||
box-shadow: 0 24px 70px rgb(0 0 0 / .26);
|
||||
transition: transform .2s var(--ease);
|
||||
}
|
||||
|
||||
.portfolio-card:hover {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
.portfolio-card.featured {
|
||||
@@ -1884,13 +1909,23 @@ color: rgb(255 255 255 / .72);
|
||||
.panel-backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 100;
|
||||
z-index: 80;
|
||||
background: rgb(255 255 255 / .74);
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity .24s var(--ease);
|
||||
}
|
||||
|
||||
body.nav-open .panel-backdrop,
|
||||
body.panel-open .panel-backdrop {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
body.panel-open .panel-backdrop {
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.lead-panel {
|
||||
position: fixed;
|
||||
inset: 12px 12px 12px auto;
|
||||
@@ -2043,12 +2078,40 @@ a:focus-visible {
|
||||
left: -9999px;
|
||||
}
|
||||
|
||||
@media (max-width: 1100px) and (min-width: 921px) {
|
||||
.hero-grid {
|
||||
grid-template-columns: 1fr;
|
||||
min-height: auto;
|
||||
padding-top: 28px;
|
||||
}
|
||||
|
||||
.hero-copy {
|
||||
max-width: 820px;
|
||||
}
|
||||
|
||||
.hero-neural {
|
||||
max-width: min(100%, 520px);
|
||||
height: 440px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 920px) {
|
||||
body.nav-open {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.site-nav {
|
||||
grid-template-columns: 1fr auto;
|
||||
border-radius: 26px;
|
||||
}
|
||||
|
||||
.site-nav.is-open {
|
||||
max-height: calc(100svh - 28px);
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.nav-toggle {
|
||||
display: inline-flex;
|
||||
min-height: 40px;
|
||||
@@ -2069,8 +2132,14 @@ transition: background-color .24s var(--ease), border-color .24s var(--ease), co
|
||||
.site-nav.is-open .nav-menu {
|
||||
grid-column: 1 / -1;
|
||||
display: grid;
|
||||
min-height: 0;
|
||||
justify-content: stretch;
|
||||
padding: 8px;
|
||||
gap: 6px;
|
||||
padding: 10px;
|
||||
border: 1px solid rgb(255 255 255 / .62);
|
||||
border-radius: 22px;
|
||||
background: rgb(255 255 255 / .74);
|
||||
box-shadow: inset 1px 1px 0 rgb(255 255 255 / .82);
|
||||
}
|
||||
|
||||
.site-nav.is-open .nav-cta {
|
||||
@@ -2105,23 +2174,102 @@ width: 100%;
|
||||
|
||||
.nav-service.is-open .service-mega {
|
||||
display: grid;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.hero-grid,
|
||||
.page-hero-grid,
|
||||
.problem-strip,
|
||||
.section-heading,
|
||||
.case-grid,
|
||||
.service-detail-grid,
|
||||
.about-grid,
|
||||
.contact-layout,
|
||||
.faq-list,
|
||||
.blog-grid,
|
||||
.service-story-grid,
|
||||
.service-proof-grid,
|
||||
.related-service-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.service-mega a {
|
||||
min-width: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.service-mega strong,
|
||||
.service-mega span {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.page-hero.hero-oversized {
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.page-hero.hero-oversized h1,
|
||||
.page-hero.hero-oversized .hero-lead {
|
||||
margin-inline: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hero-grid,
|
||||
.page-hero-grid,
|
||||
.problem-strip,
|
||||
.section-heading,
|
||||
.case-grid,
|
||||
.service-detail-grid,
|
||||
.about-grid,
|
||||
.contact-layout,
|
||||
.faq-list,
|
||||
.blog-grid,
|
||||
.service-story-grid,
|
||||
.service-proof-grid,
|
||||
.related-service-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.hero-copy,
|
||||
.problem-strip,
|
||||
.problem-strip-head,
|
||||
.section-heading,
|
||||
.case-story,
|
||||
.service-card,
|
||||
.process-grid article,
|
||||
.service-hero-panel,
|
||||
.about-grid .glass-panel,
|
||||
.contact-info,
|
||||
.final-cta .glass-panel,
|
||||
.portfolio-card div {
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hero-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.section-heading,
|
||||
.problem-strip,
|
||||
.hero-copy {
|
||||
justify-items: center;
|
||||
}
|
||||
|
||||
.hero h1 span,
|
||||
.page-hero h1 span,
|
||||
.problem-strip h2 span,
|
||||
.section-heading h2 span,
|
||||
.final-cta h2 span {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.hero h1,
|
||||
.hero-lead,
|
||||
.section-heading h2,
|
||||
.section-heading p,
|
||||
.problem-strip h2,
|
||||
.problem-strip p,
|
||||
.case-story-title,
|
||||
.story-step p,
|
||||
.service-card > p,
|
||||
.process-grid p {
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.hero-actions,
|
||||
.detail-actions {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.section-link {
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.hero {
|
||||
padding-top: 128px;
|
||||
@@ -2178,6 +2326,17 @@ grid-template-columns: auto auto;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.site-nav.liquidGlass-wrapper {
|
||||
transform: translateY(var(--nav-y));
|
||||
}
|
||||
|
||||
body.nav-open .site-nav {
|
||||
--nav-border: rgb(255 255 255 / .72);
|
||||
--nav-shadow: 0 28px 80px rgb(31 28 17 / .20), inset 1px 1px 0 rgb(255 255 255 / .86);
|
||||
--nav-tint: rgb(255 255 255 / .38);
|
||||
border-radius: 26px;
|
||||
}
|
||||
|
||||
.brand img {
|
||||
width: 142px;
|
||||
}
|
||||
@@ -2265,6 +2424,18 @@ font-size: clamp(2rem, 7vw, 2.5rem);
|
||||
max-width: 11ch;
|
||||
}
|
||||
|
||||
.page-hero.hero-oversized h1 {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.page-hero.hero-oversized .hero-lead {
|
||||
max-width: 34ch;
|
||||
}
|
||||
|
||||
.section-heading h2 {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.service-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 14px;
|
||||
@@ -2273,16 +2444,85 @@ max-width: 11ch;
|
||||
.process-grid,
|
||||
.service-proof-grid .process-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 68px;
|
||||
}
|
||||
|
||||
#process {
|
||||
padding-bottom: clamp(92px, 20vw, 128px);
|
||||
}
|
||||
|
||||
.problem-sign-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.hero-copy,
|
||||
.problem-strip,
|
||||
.problem-strip-head,
|
||||
.section-heading,
|
||||
.case-story,
|
||||
.service-card,
|
||||
.process-grid article,
|
||||
.why-section,
|
||||
.blog-card,
|
||||
.blog-card .eyebrow,
|
||||
.final-cta .glass-panel,
|
||||
.portfolio-card div {
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.why-section .eyebrow,
|
||||
.why-section h2,
|
||||
.why-section p,
|
||||
.blog-card .eyebrow {
|
||||
margin-inline: auto;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.final-cta .glass-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.final-cta h2,
|
||||
.final-cta .eyebrow {
|
||||
margin-inline: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hero-actions,
|
||||
.detail-actions {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.service-card ul {
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
margin-inline: auto;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.process-grid article {
|
||||
min-height: auto;
|
||||
}
|
||||
|
||||
.process-grid article::after {
|
||||
top: auto;
|
||||
right: 50%;
|
||||
bottom: -34px;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
display: grid;
|
||||
transform: translate(50%, 50%);
|
||||
content: "↓";
|
||||
}
|
||||
|
||||
.process-grid article:last-child::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.process-grid .step-number {
|
||||
width: 58px;
|
||||
height: 58px;
|
||||
@@ -2294,14 +2534,49 @@ border-radius: 18px;
|
||||
grid-column: span 12;
|
||||
}
|
||||
|
||||
.case-proof,
|
||||
.case-proof {
|
||||
min-height: auto;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.case-proof img {
|
||||
min-height: 360px;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
min-height: 0;
|
||||
aspect-ratio: 16 / 10.5;
|
||||
object-fit: contain;
|
||||
background: rgb(13 21 17 / .42);
|
||||
}
|
||||
|
||||
.metric-card {
|
||||
position: static;
|
||||
margin-top: 10px;
|
||||
position: absolute;
|
||||
min-width: 96px;
|
||||
margin-top: 0;
|
||||
padding: 9px 10px;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.metric-card strong {
|
||||
font-size: clamp(1.15rem, 6vw, 1.55rem);
|
||||
}
|
||||
|
||||
.metric-card span {
|
||||
font-size: 0.72rem;
|
||||
}
|
||||
|
||||
.metric-card:nth-of-type(1) {
|
||||
left: 12px;
|
||||
bottom: 12px;
|
||||
}
|
||||
|
||||
.metric-card:nth-of-type(2) {
|
||||
right: 12px;
|
||||
top: 12px;
|
||||
}
|
||||
|
||||
.metric-card:nth-of-type(3) {
|
||||
right: 18px;
|
||||
bottom: 12px;
|
||||
}
|
||||
|
||||
.lead-panel {
|
||||
|
||||