Compare commits

12 Commits

Author SHA1 Message Date
Kunthawat Greethong
54c9b381b9 feat: publish 14 blog articles from vault research
- 14 new Thai-language blog posts covering AI, SEO, B2B, and Tools
- 66 images (featured + inline) for all articles
- Categories: AI & Marketing, SEO, B2B, Tools
- Sources: arXiv papers, Search Engine Journal, Marketing AI Institute, HubSpot, Neil Patel
- All articles GEO-optimized with TL;DR, FAQ, and structured data
- Social posts (FB, X, IG) created in vault for future publishing

Articles:
1. Fintech มองไม่เห็นโดย AI Agents
2. AI Brand Reputation — 167K Citations
3. AI Recommendation Multi-Industry Map
4. Google ตอบ SEO สำหรับ AI Agents
5. Google Open Knowledge Format (OKF)
6. OPID — AI Agent ฝึกตัวเองได้
7. Two Things B2B Marketer ควรทำกับ AI
8. B2B Marketers Future of Work
9. AI Visibility ≠ SEO — Operational Alignment
10. Brand Reputation Precedes You With AI
11. Broken Form Cost Agency Leads
12. ChatGPT Opens Ads for All
13. OpenKnowledge AI-First Obsidian
14. Profound vs Bluefish AEO
2026-06-30 22:51:34 +07:00
Kunthawat Greethong
c004ee6504 Add SEO+GEO foundation + blog auto JSON-LD + robots fix 2026-06-30 22:16:47 +07:00
Kunthawat Greethong
479ed4722e Improve mobile responsive layout and site content 2026-06-30 21:02:47 +07:00
Kunthawat Greethong
bb1b1ba568 feat: oversized H1 hero for all inner pages + portfolio refinements
- Add hero-oversized class (Option B) to global.css
- Apply oversized H1 to: about, services, blog, contact, faq, privacy, terms
- Portfolio page: oversized hero, new text, portfolio-design-note in section-heading
- Clean up duplicate styles from portfolio.astro scoped block
2026-06-28 17:52:56 +07:00
Kunthawat Greethong
9ebbc91e5b feat: major content & layout overhaul across all sections
- Problem strip: 4 sign cards with closing statement
- Dataroot section: rebranded as case study with new content
- Services: 2×2 content-rich cards with bullet lists, updated copy
- Process: moved above portfolio, new strategy-focused copy
- Portfolio: 9 items with correct tags, uniform cards, light theme
- SEO: OG tags, canonical, favicons, robots.txt, sitemap, 404
- Backdrop: lighter white for lead panel readability
- Footer, LegalPages component, various text refinements
- Fix CSS syntax error in neural hero hover state
2026-06-28 16:52:44 +07:00
Kunthawat Greethong
f114a34a62 Magnetic Field hero, Thai eyebrows, black text-stroke, service pages fixes
- Hero: Magnetic Field design (ripple rings, field curves, attract animations)
- H1: เปลี่ยนเป็น 'เป้าหมายของเราคือการเพิ่มกำไรให้ลูกค้า', กำไร เน้นขอบดำ
- Site: ทุก eyebrow แปลเป็นไทย
- Buttons: text สีดำทุกหน้าแม้ใน dark section
- Yellow text: เพิ่ม -webkit-text-stroke ขอบดำทุก element
- Service pages: light/light/dark pattern, process-grid แถวเดียว
- Logo: อัพเดทใหม่
- Demos: เพิ่ม 5 hero design concepts (orbital, energy flow, holographic, constellation, magnetic)
2026-06-26 11:15:58 +07:00
Kunthawat Greethong
689a8924e6 fix: Business Knowledge card visibility, spread neural cards, adjust layout
- Add position:absolute to neural-node.liquid-glass override to fix
  3D positioning (liquid-glass was overriding to position:relative)
- Spread outer cards further apart for better visual separation
- Increase container size to 600x520px to accommodate spread
- Enlarge neural cards (220px width, 130px min-height)
- Update float animations to match new positions
2026-06-24 14:20:57 +07:00
Kunthawat Greethong
2a3062357f fix: hero neural UX improvements
1. Mouse move listener now on document (not just hero section)
2. Removed hover effect on outer cards, kept only for center กำไร card
3. Bigger text: card-tag 20px, card-desc 16px
4. Hero overflow visible on desktop (cards can extend left)
5. Hero overflow clip on mobile (normal containment)
2026-06-24 09:14:55 +07:00
Kunthawat Greethong
1d893e1bcb fix: remove duplicate CSS causing style conflicts
- Removed old translateZ() CSS that was overriding new translate3d() styles
- This was causing nodes to not display in correct 3D positions
2026-06-24 09:02:19 +07:00
Kunthawat Greethong
61c2bd6924 feat: neural network hero with true 3D and dynamic lines
- True 3D positioning with translate3d(x, y, z) for each node
- Larger cards (200px width) with proper spacing
- Canvas-based dynamic connection lines
- Lines connect at card borders (edge-to-edge)
- Straight solid lines (3px, yellow, 50% opacity)
- Mouse parallax with smooth easing
- 3D perspective changes card sizes dynamically
- Mobile responsive: flat column layout
- Device orientation support for touch devices
2026-06-24 08:58:32 +07:00
Kunthawat Greethong
fdb03f6117 feat: neural network hero with 3D parallax
- Replace profit cluster with neural network visualization
- 4 liquid-glass nodes: กำไร (center), Marketing, AI, Business Knowledge
- 3D perspective with CSS preserve-3d
- Mouse parallax: scene rotates ±15deg following cursor
- Unequal distances: nodes at z: -100, -150, -200
- Floating animations for each outer node
- SVG dashed connector lines with pulse animation
- Device orientation support for mobile
- Responsive: flat column layout on mobile (≤620px)
- Smooth easing with requestAnimationFrame
2026-06-24 08:45:49 +07:00
Kunthawat Greethong
0f244424c0 feat: hero profit cluster, dark text fix, footer, privacy/terms pages
- Replace hero right panel with liquid-glass profit cluster (กำไร + Marketing/AI/Business Knowledge)
- Fix dark-on-dark text visibility in all inverted sections (scene-dark, page-section)
- Add Footer component with liquid-glass design, contact info, legal links
- Add privacy and terms placeholder pages
- Update PageShell to include Footer on all pages
2026-06-24 08:24:49 +07:00
140 changed files with 11805 additions and 1242 deletions

View File

@@ -1,21 +1,22 @@
# Plan Review Log: MoreminiMore Homepage Rebuild # Plan Review Log: Footer Component + Remove Yellow Lines from Process Section
Act 1 (grill) complete — plan locked with the user. MAX_ROUNDS=5.
Act 1 grill complete — plan locked with user. ## Round 1 — Codex
พบ 10 issues (3 critical, 3 significant, 4 minor):
1. 🔴 PageShell layout ignored — ควรแก้ผ่าน PageShell
2. 🔴 Privacy/Terms pages ไม่มี — dead links
3. 🔴 Liquid glass markup pattern ไม่ระบุ
4. 🟡 service-proof-grid yellow accent missed
5. 🟡 Mobile layout spec ambiguous
6. 🟡 Step-flow visual cue removed without alternative
7. 🟡 Missing semantic `<footer>` element
8. 🟠 LINE URL unspecified
9. 🟠 Logo dimensions omitted
10. 🟠 z-index risk unresolved
MAX_ROUNDS=5 ### Claude's response
แก้ทั้ง 10 ข้อใน PLAN.md revision
## Act 1 Summary ## Round 2 — Codex
All 10 findings addressed. Minor note: footer ควรวางระหว่าง `</main>` กับ floating-cta (ไม่ใช่ inside `<main>`).
- User clarified credibility priority: SME understanding > measurable business value > modern UX/coding impression. VERDICT: APPROVED (2 rounds)
- User clarified homepage must be company-site quality, not a one-page landing page.
- User clarified visual direction: subtle macOS-inspired liquid glass, hybrid light/dark rhythm, abstract business-map parallax, restrained motion.
- User clarified implementation preference: Astro static + vanilla JS first, Google Apps Script for low-volume lead handling.
- User clarified CTA wording: use "ปรึกษาฟรี" only, not "ปรึกษาฟรี 30 นาที".
- User clarified Dealplustech must be included in portfolio using a homepage screenshot.
- User requested a copy-ready Google Apps Script file plus detailed setup instructions.
## Act 2 Status
Not started.
No implementation has been done from this plan yet.

418
PLAN.md
View File

@@ -1,351 +1,71 @@
# Plan: MoreminiMore Homepage Rebuild # Plan: Footer Component + Remove Yellow Lines from Process Section
_Locked via grill — by Claude + Kunthawat — Revised Round 1_
_Locked via grill — by Codex + Kunthawat_
## Goal ## Goal
สร้าง Footer component ใหม่ด้วย liquid glass style และลบเส้นสีเหลืองออกจาก How we work section
Rebuild the MoreminiMore company website from a clean slate, starting with the homepage only. The homepage must make SME owners feel that MoreminiMore is a friendly growth partner who understands real business problems, uses real data before recommending work, and can deliver modern, trustworthy websites and systems. The visual experience should feel modern and a little wow through restrained liquid-glass UI, layered parallax, and polished UX, but never become an effect demo or a tech showcase.
## Approach
## Core Positioning ### 1. ลบเส้นสีเหลืองจาก Process Section (`src/styles/global.css`)
- ลบ `.process-grid::before` (เส้นแนวนอนสีเหลือง) → `display: none`
Priority of trust: - ลบ `.process-grid article::after` (วงกลม ">" สีเหลืองระหว่าง step) → `display: none`
- `.process-grid .step-number`: เปลี่ยน `background: var(--yellow)``background: rgb(255 255 255 / .5)` + ลบ yellow box-shadow
1. MoreminiMore understands SME businesses and their real problems. - `.service-proof-grid .process-grid .step-number`: override สีเหลืองเหมือนกัน (scope เพิ่ม)
2. MoreminiMore can help clients choose work that is more efficient, worthwhile, and suitable for their business. - **หมายเหตุ:** step numbers (01, 02, 03, 04) ยังคงแสดง sequential flow อยู่แล้ว ไม่ต้องเพิ่ม connector แทน
3. MoreminiMore writes modern code in the UX sense: smooth, beautiful, easy to use, and subtly impressive.
### 2. สร้าง Footer Component (`src/components/Footer.astro`)
Target customer priority: - ใช้ `<footer>` semantic element
- ใช้ liquid glass style (ต้องมี 3 child divs):
1. Businesses that already have a website, ads, or tools, but feel the result is not worth the money or effort. ```html
2. Businesses that do not yet have a good website or system and want to start correctly. <footer class="site-footer liquid-glass liquidGlass-wrapper">
3. Businesses growing into AI/automation/workflow needs. <div class="liquidGlass-effect" aria-hidden="true"></div>
<div class="liquidGlass-tint" aria-hidden="true"></div>
Brand role: <div class="liquidGlass-shine" aria-hidden="true"></div>
<!-- content -->
1. Growth partner for SMEs. </footer>
2. Business diagnosis partner. ```
3. Team that can implement real working solutions. - `position: relative; z-index: auto` (ไม่ทับ lead-panel z-index: 110)
Tone: ### 3. เนื้อหา Footer
**ซ้าย:**
- Friendly-first. - โลโก้: `/images/logos/logo-long-black.png` (width="205" height="36")
- Thai-first copy. - คำอธิบาย: "ที่ปรึกษาเว็บไซต์ การตลาด และ AI สำหรับ SME"
- English only for service names and necessary terms.
- No consultant-speak, no overly technical language, no fake metrics. **กลาง:**
- ลิงก์: หน้าแรก / บริการ / ผลงาน / บล็อก / ติดต่อ / นโยบายความเป็นส่วนตัว / เงื่อนไขการใช้งาน
## Homepage Strategy
**ขวา:**
Hero strategy: - LINE: @moreminimore (link: https://line.me/ti/p/@moreminimore)
- Email: contact@moreminimore.com
- Belief-led headline.
- Pain-led subheadline. **ล่าง:**
- Promise-led CTA/context. - Copyright: © {new Date().getFullYear()} MoreminiMore
Current hero copy direction: ### 4. Responsive
- Desktop (>768px): 3 columns (grid-template-columns: 1fr 1fr 1fr)
> ธุรกิจไม่ควรเสียเงินกับสิ่งที่ยังไม่รู้ว่าคุ้มไหม - Mobile (≤768px): vertical stack (flex-direction: column) — เรียง: โลโก้ → ลิงก์ → ติดต่อ → copyright
>
> เราช่วย SME ดูข้อมูลจริงก่อนตัดสินใจทำเว็บ การตลาด AI หรือระบบอัตโนมัติ เพื่อเลือกสิ่งที่ควรทำ อย่างมีประสิทธิภาพ และเหมาะสมกับลูกค้า ### 5. Integration Strategy
- **PageShell pages** (about, services, blog, blog/[slug], contact, faq, portfolio, services/[slug]):
The final copy can be polished, especially the phrase "เหมาะสมกับลูกค้า", but the idea should stay intact. เพิ่ม `<Footer />` import + render ใน `src/components/PageShell.astro` ก่อน `</main>` หรือก่อน `</body>`
- **index.astro** (standalone, ไม่ใช้ PageShell):
Primary conversion priority: เพิ่ม `<Footer />` import + render ก่อน `</body>` โดยตรง
1. ส่งโจทย์ธุรกิจให้เราดูก่อน ### 6. สร้าง Placeholder Pages
2. ดูเคส/ผลงานก่อน แล้วค่อยติดต่อ - สร้าง `src/pages/privacy.astro` (placeholder — "นโยบายความเป็นส่วนตัว กำลังอัพเดท")
3. ปรึกษาฟรี - สร้าง `src/pages/terms.astro` (placeholder — "เงื่อนไขการใช้งาน กำลังอัพเดท")
- ใช้ PageShell layout เหมือนหน้าอื่น
Do not use "30 นาที" in CTA copy. Use "ปรึกษาฟรี" only.
## Key decisions & tradeoffs
Homepage v1 must not include a blog section. Blog content can stay preserved for later, but the homepage should focus on trust, diagnosis, proof, service clarity, portfolio quality, and conversion. - ใช้ liquid glass style เดียวกับ navbar เพื่อความ cohesive
- ลบเส้นเหลืองทั้งหมด — step numbers ยังบ่งบอกลำดับอยู่
## Homepage Sections - ใช้ dynamic year (`new Date().getFullYear()`) ใน copyright (Astro SSG → build-time inlined)
- Footer ใน PageShell = แก้จุดเดียว ครอบคลุม 8 หน้า
Recommended homepage order: - z-index: auto (ไม่ทับ lead-panel)
1. Hero ## Risks / open questions
- Belief-led headline. - Privacy/Terms pages เป็น placeholder — ต้องเพิ่ม content ทีหลัง
- Friendly explanation. - Logo อาจต้องเปลี่ยนเป็นสีขาวเมื่ออยู่บนพื้นเข้ม (invert)
- CTA to open problem form.
- Light abstract business-map background with subtle liquid glass. ## Out of scope
- ไม่แก้ไขหน้า Privacy/Terms content จริง
2. Problem framing - ไม่เพิ่ม social media icons (Facebook/X/LinkedIn)
- Explain that customers do not need to know which service they need.
- MoreminiMore will map the problem to the suitable service.
- CTA opens the same slide-over form.
3. Dataroot diagnosis story
- Dark diagnosis stage.
- Split case layout.
- Left side: narrative diagnosis.
- Right side: metric cards and relevant visual/screenshot.
- Use only real Dataroot metrics:
- +373% impression
- +114.2% click
- -28.3% ad spend
4. Outcome-first service cards
- Service name is still visible in English.
- Card headline should sell the outcome/problem solved, not the service label first.
- Desktop hover reveals "เหมาะกับปัญหาแบบไหน".
- Mobile shows essential information directly.
5. Portfolio preview
- Dark gallery stage.
- Featured + grid layout.
- Featured 1 should be Jet Industries for credibility.
- Featured 2 should be selected from the most visually strong portfolio screenshot after inspecting assets.
- Dataroot does not need to be the main portfolio feature because it has the diagnosis story.
- Portfolio role is mainly visual website quality, because most clients are website clients.
6. Mini process
- Short 4-step process:
1. เข้าใจธุรกิจ
2. ดูข้อมูล
3. เลือกทางที่คุ้ม
4. ลงมือและวัดผล
7. Final CTA
- Friendly, low-friction.
- Reopen form panel.
- Reinforce "ส่งโจทย์ให้เราดูก่อน".
## Problem Form
The primary CTA opens a form, not a separate contact page.
Placement and behavior:
- Desktop: glass slide-over panel from the right.
- Mobile: bottom sheet.
- Floating/sticky CTA appears after the hero, not immediately on first paint.
- Navigation also has a CTA.
Problem chips:
1. เว็บมีอยู่แล้ว แต่ไม่ค่อยมีลูกค้าทัก
2. ยิงแอดอยู่ แต่ยอดขายไม่คุ้ม
3. มีคนทักมา แต่ไม่ใช่ลูกค้าที่ใช่
4. ทีมงานทำงานเดิม ๆ แต่ทำงานช้า หรือผิดพลาดบ่อย
5. อยากใช้ AI แต่ไม่รู้เริ่มตรงไหน
6. ยังไม่แน่ใจว่าควรแก้อะไรก่อน
Textarea:
- Must include a very short example because customers are assumed to be lazy and may not want to type.
- Example direction:
- "ยิงแอดอยู่ แต่ยอดขายไม่คุ้ม อยากรู้ว่าควรแก้อะไรก่อน"
- "มีเว็บแล้ว แต่ลูกค้าไม่ค่อยทัก อยากรู้ว่าควรแก้เว็บหรือยิงแอดก่อน"
Contact fields:
- Name.
- Phone.
- Email.
- Phone or email must be provided, but both are not required.
- Labels must be explicit because non-technical customers may be confused by a single generic "contact channel" field.
Submission backend:
- Use Google Apps Script first because lead volume is expected to be low.
- Send notification email to Gmail/Google Workspace.
- Ideally also store leads in Google Sheet.
- Sender should be MoreminiMore-owned; customer contact should be used as reply-to where possible.
- Keep message clean to reduce spam risk.
- Provide the Google Apps Script as a copy-ready file because the user has not done this setup before.
- Current script artifact: `google-apps-script/lead-form.gs`.
- Current setup guide: `google-apps-script/SETUP.md`.
Post-submit UX:
- Stay in the panel.
- Show success message plus light diagnosis preview.
- Do not pretend to generate a complete diagnosis.
- Example direction: "จากปัญหาที่เลือก เราน่าจะเริ่มจากการดูเว็บ/แอด/ขั้นตอนทำงานก่อน แล้วจะติดต่อกลับทางเบอร์หรืออีเมลที่ให้ไว้"
## Navigation
This is a company website, not a one-page landing page.
Navigation should include:
- หน้าแรก
- บริการ
- ผลงาน
- เกี่ยวกับ
- FAQ and/or บทความ
- ติดต่อ / ส่งโจทย์ให้เราดู
Services submenu:
- Compact mega menu.
- Use English service names:
- Website Development
- Marketing Consult
- Automation Workflow
- AI Consult
- Include a short Thai explanation under each service name.
- Desktop supports hover, click, and keyboard.
- Mobile uses an accordion/list.
Nav visual behavior:
- Hybrid glass sticky nav.
- On hero: transparent/light glass.
- After scroll: compact stronger glass/solid for readability.
## Visual System
Overall mode:
- Hybrid light/dark.
- Light glass for friendly SME trust.
- Dark/premium stages for Dataroot diagnosis and portfolio.
Section atmosphere:
- Light hero.
- Dark Dataroot diagnosis.
- Light service/process/form context.
- Dark portfolio gallery.
Brand assets:
- Use existing logo.
- Use `#fed400` as accent only, not as a full-page wash.
- Use red `#d4553a` sparingly if useful.
- Avoid recreating the old yellow-heavy design.
Liquid glass:
- Subtle macOS-inspired.
- Use in key moments only:
- Navigation.
- CTA/form slide-over.
- Hero card/form/selected elements.
- Dataroot diagnosis cards.
- Possibly light service cards, but not every surface.
- Must preserve readability before effect.
Background and parallax:
- Main background concept: abstract business map.
- Use lines, nodes, soft grids, flow paths, and layered decision-map visuals.
- Hero should not rely on stock imagery.
- Portfolio sections can use real portfolio screenshots as the main visual material.
Motion:
- Desktop:
- Hero mouse parallax should be noticeable enough to feel dimensional.
- Scroll-driven scene changes are allowed.
- Use exactly 3 main background scenes:
1. Hero / light business map.
2. Dataroot / dark diagnosis stage.
3. Portfolio / dark gallery stage.
- Mobile:
- No mouse interaction.
- Use scroll parallax/reveal only.
- Keep performance conservative.
## Portfolio Rules
Portfolio role:
- Show website visual quality and execution.
- Most clients are website clients, not consulting clients.
- Consulting-heavy proof is mainly Dataroot.
- Dealplustech must be included in the website portfolio.
- URL: `https://www.dealplustech.co.th`
- Capture a homepage screenshot and use it as a portfolio image, matching the treatment of other portfolio clients.
- Dealplustech is both website work and consulting-adjacent, but should still appear as a website portfolio item.
Client context:
- Largest client: Jet Industries.
- Second largest: Dataroot.
- Most other clients are smaller.
Sorting priority:
1. Visual quality / modern feel.
2. Professional credibility.
3. SME relatability.
Featured portfolio:
- Featured 1: Jet Industries.
- Featured 2: choose visually strongest work after inspecting assets.
- Other projects in grid.
## Technical Approach
Stack:
- Astro static, rebuilt from scratch.
- Vanilla JS first.
- CSS first for liquid glass and layout.
- Use small vanilla scripts for:
- Mouse parallax.
- Scroll scene transitions.
- Slide-over/bottom sheet form.
- Form validation and submission.
- Do not use React by default.
- Add React only if a specific interaction becomes too complex for readable vanilla JS.
Implementation scope:
- Homepage-first.
- Do not build full route details in v1.
- Navigation may reference future routes, but implementation focus is homepage.
- Preserve extracted inputs in `redesign-input/`.
- Old code remains archived in `_archive/pre-redesign-2026-06-21/`.
Suggested initial implementation files after plan approval:
1. Recreate minimal Astro project files at root:
- `package.json`
- `astro.config.mjs`
- `tsconfig.json`
- `src/pages/index.astro`
- `src/styles/global.css`
- `src/scripts/home.js`
2. Copy required assets from `redesign-input/assets/` into `public/`.
3. Build homepage components either inline first or split only when repeated:
- Navigation
- Hero
- Problem CTA panel
- Dataroot case
- Service cards
- Portfolio preview
- Process
- Footer
4. Add Google Apps Script endpoint configuration as an environment/runtime variable if possible.
## Key Decisions & Tradeoffs
- Problem-first homepage, but service cards still exist because this is a company website.
- Friendly-first copy, but visual system must remain premium enough for Jet/Dataroot credibility.
- Use English service names in nav for professionalism, but Thai copy everywhere else for clarity.
- Use Google Apps Script before heavier transactional email infrastructure because lead volume is expected to be low.
- Use Astro static + vanilla JS to keep the site light and maintainable.
- Use effects only in high-impact places to avoid repeating the previous failure mode of design overwhelming the business message.
## Risks / Open Questions
- The exact visual quality of portfolio assets must be inspected before choosing Featured 2.
- Dealplustech needs a homepage screenshot before implementation can finalize portfolio assets.
- Google Apps Script deliverability depends on the Google account/domain setup. SPF/DKIM/DMARC should be checked before production.
- Navigation points to company-site routes, but homepage is the first implementation scope. Decide whether future routes should be placeholders, omitted, or added later.
- Need final decision on exact final hero copy during implementation polish.
## Out Of Scope For Homepage V1
- Full services pages.
- Full portfolio detail pages.
- Blog section on homepage.
- Full blog redesign.
- Heavy WebGL/canvas animation.
- Full React app or SPA rewrite.
- Invented metrics or testimonials.
- Reusing old design or old code structure as the main foundation.

View File

@@ -2,6 +2,7 @@
import { defineConfig } from 'astro/config'; import { defineConfig } from 'astro/config';
export default defineConfig({ export default defineConfig({
site: 'https://moreminimore.com',
output: 'static', output: 'static',
image: { layout: 'constrained', responsiveStyles: true }, image: { layout: 'constrained', responsiveStyles: true },
devToolbar: { enabled: false }, devToolbar: { enabled: false },

4435
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -10,9 +10,14 @@
"dev": "astro dev", "dev": "astro dev",
"build": "astro build", "build": "astro build",
"preview": "astro preview", "preview": "astro preview",
"start": "node server.js",
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "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"
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
public/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

182
public/demos/a-orbital.html Normal file
View File

@@ -0,0 +1,182 @@
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>A: Orbital — ระบบดาวเคราะห์</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'Kanit', system-ui, sans-serif;
background: #0a0f1a;
color: #fff;
display: flex; align-items: center; justify-content: center;
min-height: 100vh; overflow: hidden;
}
@import url('https://fonts.googleapis.com/css2?family=Kanit:wght@400;600;800;900&display=swap');
.demo { position: relative; width: 650px; height: 580px; }
/* Canvas for orbital rings */
canvas#orbitalCanvas {
position: absolute; inset: 0; pointer-events: none; z-index: 1;
}
.scene {
position: relative; width: 100%; height: 100%;
transform-style: preserve-3d;
transition: transform 0.2s ease-out;
}
.node {
position: absolute; border-radius: 50%;
display: flex; flex-direction: column;
align-items: center; justify-content: center;
text-align: center; backface-visibility: hidden;
}
/* Center Sun */
.sun {
left: 50%; top: 50%;
transform: translate(-50%, -50%);
width: 170px; height: 170px;
background: radial-gradient(circle at 40% 35%, #fff7cc, #fed400 40%, #d4a000 100%);
box-shadow: 0 0 60px rgba(254,212,0,0.6), 0 0 120px rgba(254,212,0,0.3), 0 0 200px rgba(254,180,0,0.15);
z-index: 10; animation: sunPulse 3s ease-in-out infinite;
}
@keyframes sunPulse {
0%, 100% { box-shadow: 0 0 60px rgba(254,212,0,0.6), 0 0 120px rgba(254,212,0,0.3), 0 0 200px rgba(254,180,0,0.15); }
50% { box-shadow: 0 0 80px rgba(254,212,0,0.8), 0 0 150px rgba(254,212,0,0.4), 0 0 230px rgba(254,180,0,0.2); }
}
.sun .label { font-size: 2.8rem; font-weight: 900; color: #3a2e00; }
.sun .sub { font-size: 0.75rem; color: #6b5500; margin-top: 4px; font-weight: 600; }
/* Orbiting planets */
.planet {
width: 110px; height: 110px;
background: rgba(255,255,255,0.06);
backdrop-filter: blur(10px);
border: 1.5px solid rgba(255,255,255,0.2);
box-shadow: 0 8px 32px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.15);
left: 50%; top: 50%;
animation: orbit var(--orbit-dur) linear infinite;
z-index: 5;
}
.planet:nth-child(2) { --orbit-dur: 12s; --radius: 230px; --angle: 0deg; --z: -40px; }
.planet:nth-child(3) { --orbit-dur: 15s; --radius: 280px; --angle: 120deg; --z: -70px; }
.planet:nth-child(4) { --orbit-dur: 18s; --radius: 330px; --angle: 240deg; --z: -100px; }
@keyframes orbit {
0% { transform: translate(-50%, -50%) rotate(0deg) translateX(var(--radius)) rotate(0deg); }
100% { transform: translate(-50%, -50%) rotate(360deg) translateX(var(--radius)) rotate(-360deg); }
}
.planet .tag { font-size: 1rem; font-weight: 800; color: #fff; text-transform: uppercase; }
.planet .desc { font-size: 0.7rem; color: rgba(255,255,255,0.6); margin-top: 4px; }
/* Connecting lines (drawn on canvas) */
.title {
position: fixed; top: 24px; left: 50%; transform: translateX(-50%);
font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.2em;
color: rgba(255,255,255,0.4); z-index: 100;
}
</style>
</head>
<body>
<span class="title">A. Orbital — ระบบดาวเคราะห์โคจร</span>
<div class="demo">
<canvas id="orbitalCanvas"></canvas>
<div class="scene" id="scene">
<div class="node sun" data-node="center">
<span class="label">กำไร</span>
<span class="sub">เป้าหมายของทุกธุรกิจ</span>
</div>
<div class="node planet" data-node="mkt">
<span class="tag">Marketing</span>
<span class="desc">เพิ่มรายได้</span>
</div>
<div class="node planet" data-node="ai">
<span class="tag">AI</span>
<span class="desc">ลดต้นทุนและเวลา</span>
</div>
<div class="node planet" data-node="biz">
<span class="tag">Business<br>Knowledge</span>
<span class="desc">ลดความเสี่ยง</span>
</div>
</div>
</div>
<script>
const canvas = document.getElementById('orbitalCanvas');
const ctx = canvas.getContext('2d');
const scene = document.getElementById('scene');
function resize() {
const rect = canvas.parentElement.getBoundingClientRect();
canvas.width = rect.width;
canvas.height = rect.height;
}
resize();
window.addEventListener('resize', resize);
function draw() {
const rect = canvas.parentElement.getBoundingClientRect();
ctx.clearRect(0, 0, canvas.width, canvas.height);
const sun = document.querySelector('[data-node="center"]');
const planets = document.querySelectorAll('.planet');
if (!sun) return;
const sunRect = sun.getBoundingClientRect();
const sx = sunRect.left + sunRect.width/2 - rect.left;
const sy = sunRect.top + sunRect.height/2 - rect.top;
// Draw orbital rings
const sr = 85; // sun radius
const radii = [230, 280, 330];
radii.forEach((r, i) => {
ctx.beginPath();
ctx.ellipse(sx, sy, r, r * 0.45, 0, 0, Math.PI * 2);
ctx.strokeStyle = `rgba(254,212,0,${0.15 - i * 0.03})`;
ctx.lineWidth = 1;
ctx.setLineDash([8, 14]);
ctx.stroke();
ctx.setLineDash([]);
});
// Draw connection lines
planets.forEach(p => {
const pRect = p.getBoundingClientRect();
const px = pRect.left + pRect.width/2 - rect.left;
const py = pRect.top + pRect.height/2 - rect.top;
const dx = px - sx, dy = py - sy;
const dist = Math.sqrt(dx*dx + dy*dy);
const r = 85;
ctx.beginPath();
ctx.moveTo(sx + (dx/dist)*r, sy + (dy/dist)*r);
ctx.lineTo(px - (dx/dist)*55, py - (dy/dist)*55);
const grad = ctx.createLinearGradient(sx, sy, px, py);
grad.addColorStop(0, 'rgba(254,212,0,0.7)');
grad.addColorStop(1, 'rgba(254,212,0,0.15)');
ctx.strokeStyle = grad;
ctx.lineWidth = 1.5;
ctx.stroke();
});
requestAnimationFrame(draw);
}
// Mouse parallax
document.addEventListener('mousemove', e => {
const x = (e.clientX / window.innerWidth - 0.5) * 8;
const y = (e.clientY / window.innerHeight - 0.5) * -8;
scene.style.transform = `rotateX(${y}deg) rotateY(${x}deg)`;
});
draw();
</script>
</body>
</html>

View File

@@ -0,0 +1,180 @@
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>B: Energy Flow — กระแสพลังงาน</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Kanit:wght@400;600;800;900&display=swap');
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'Kanit', system-ui, sans-serif;
background: #080d14;
color: #fff; overflow: hidden;
display: flex; align-items: center; justify-content: center; min-height: 100vh;
}
.demo { position: relative; width: 650px; height: 580px; }
canvas#flowCanvas { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.scene {
position: relative; width: 100%; height: 100%;
transform-style: preserve-3d;
transition: transform 0.3s ease-out;
}
.node {
position: absolute;
display: flex; flex-direction: column;
align-items: center; justify-content: center; text-align: center;
}
/* Core */
.core {
left: 50%; top: 50%;
transform: translate(-50%, -50%);
width: 160px; height: 160px; border-radius: 50%;
background: radial-gradient(circle at 35% 30%, #2a1a00, #100800);
border: 2px solid rgba(254,212,0,0.8);
box-shadow: 0 0 40px rgba(254,212,0,0.3), 0 0 80px rgba(254,180,0,0.1), inset 0 0 40px rgba(254,212,0,0.08);
z-index: 10;
animation: coreBeat 2s ease-in-out infinite;
}
@keyframes coreBeat {
0%, 100% { box-shadow: 0 0 40px rgba(254,212,0,0.3), 0 0 80px rgba(254,180,0,0.1), inset 0 0 40px rgba(254,212,0,0.08); }
50% { box-shadow: 0 0 60px rgba(254,212,0,0.5), 0 0 100px rgba(254,180,0,0.2), inset 0 0 50px rgba(254,212,0,0.12); }
}
.core .label { font-size: 2.6rem; font-weight: 900; color: #fed400; }
.core .sub { font-size: 0.7rem; color: rgba(254,212,0,0.5); margin-top: 4px; font-weight: 600; }
/* Satellites */
.satellite {
border-radius: 50%;
background: rgba(255,255,255,0.04);
backdrop-filter: blur(8px);
border: 1px solid rgba(254,212,0,0.25);
width: 120px; height: 120px;
z-index: 5;
left: 50%; top: 50%;
}
.satellite:nth-child(2) { transform: translate(-50%, -50%) translateY(-230px); animation: float1 4s ease-in-out infinite; }
.satellite:nth-child(3) { transform: translate(-50%, -50%) translateX(220px) translateY(10px); animation: float2 4.5s ease-in-out infinite; }
.satellite:nth-child(4) { transform: translate(-50%, -50%) translateX(-160px) translateY(190px); animation: float3 5s ease-in-out infinite; }
@keyframes float1 { 0%,100%{ transform: translate(-50%,-50%) translateY(-230px); } 50%{ transform: translate(-50%,-50%) translateY(-245px); } }
@keyframes float2 { 0%,100%{ transform: translate(-50%,-50%) translateX(220px) translateY(10px); } 50%{ transform: translate(-50%,-50%) translateX(235px) translateY(0px); } }
@keyframes float3 { 0%,100%{ transform: translate(-50%,-50%) translateX(-160px) translateY(190px); } 50%{ transform: translate(-50%,-50%) translateX(-175px) translateY(205px); } }
.satellite .tag { font-size: 0.9rem; font-weight: 800; color: #fff; }
.satellite .desc { font-size: 0.65rem; color: rgba(255,255,255,0.5); margin-top: 3px; }
.title {
position: fixed; top: 24px; left: 50%; transform: translateX(-50%);
font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.2em;
color: rgba(255,255,255,0.4); z-index: 100;
}
</style>
</head>
<body>
<span class="title">B. Energy Flow — กระแสพลังงาน พร้อม particles</span>
<div class="demo">
<canvas id="flowCanvas"></canvas>
<div class="scene" id="scene">
<div class="node core" data-node="center">
<span class="label">กำไร</span>
<span class="sub">เป้าหมายของทุกธุรกิจ</span>
</div>
<div class="node satellite" data-node="mkt">
<span class="tag">Marketing</span>
<span class="desc">เพิ่มรายได้</span>
</div>
<div class="node satellite" data-node="ai">
<span class="tag">AI</span>
<span class="desc">ลดต้นทุนและเวลา</span>
</div>
<div class="node satellite" data-node="biz">
<span class="tag">Business<br>Knowledge</span>
<span class="desc">ลดความเสี่ยง</span>
</div>
</div>
</div>
<script>
const canvas = document.getElementById('flowCanvas');
const ctx = canvas.getContext('2d');
const scene = document.getElementById('scene');
function resize() {
const rect = canvas.parentElement.getBoundingClientRect();
canvas.width = rect.width;
canvas.height = rect.height;
}
resize();
window.addEventListener('resize', resize);
// Particle system per connection
const connections = [];
let t = 0;
function draw() {
t++;
const rect = canvas.parentElement.getBoundingClientRect();
ctx.clearRect(0, 0, canvas.width, canvas.height);
const sun = document.querySelector('[data-node="center"]');
const sats = document.querySelectorAll('.satellite');
if (!sun) { requestAnimationFrame(draw); return; }
const sr = sun.getBoundingClientRect();
const sx = sr.left + sr.width/2 - rect.left;
const sy = sr.top + sr.height/2 - rect.top;
sats.forEach((sat, i) => {
const pr = sat.getBoundingClientRect();
const px = pr.left + pr.width/2 - rect.left;
const py = pr.top + pr.height/2 - rect.top;
const dx = px - sx, dy = py - sy;
const dist = Math.sqrt(dx*dx + dy*dy);
// Draw stream line
ctx.beginPath();
ctx.moveTo(sx + (dx/dist)*80, sy + (dy/dist)*80);
ctx.lineTo(px - (dx/dist)*60, py - (dy/dist)*60);
const grad = ctx.createLinearGradient(sx, sy, px, py);
grad.addColorStop(0, 'rgba(254,212,0,0.6)');
grad.addColorStop(0.5, 'rgba(254,212,0,0.3)');
grad.addColorStop(1, 'rgba(254,212,0,0.1)');
ctx.strokeStyle = grad;
ctx.lineWidth = 2;
ctx.stroke();
// Animated particles along the line
const count = 12;
for (let j = 0; j < count; j++) {
const phase = (t * 0.03 + j / count + i * 0.33) % 1;
const pp = phase < 0.5 ? phase * 2 : 2 - phase * 2;
const x = sx + (dx/dist)*80 + dx * (1 - 80/dist - 60/dist) * phase;
const y = sy + (dy/dist)*80 + dy * (1 - 80/dist - 60/dist) * phase;
ctx.beginPath();
ctx.arc(x, y, 2.5, 0, Math.PI*2);
ctx.fillStyle = `rgba(254,230,100,${0.8 * pp})`;
ctx.fill();
// Glow
ctx.beginPath();
ctx.arc(x, y, 5, 0, Math.PI*2);
ctx.fillStyle = `rgba(254,212,0,${0.25 * pp})`;
ctx.fill();
}
});
requestAnimationFrame(draw);
}
document.addEventListener('mousemove', e => {
const x = (e.clientX / window.innerWidth - 0.5) * 6;
const y = (e.clientY / window.innerHeight - 0.5) * -6;
scene.style.transform = `rotateX(${y}deg) rotateY(${x}deg)`;
});
draw();
</script>
</body>
</html>

View File

@@ -0,0 +1,179 @@
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>C: Holographic 3D — Hologram Sci-Fi</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Kanit:wght@400;600;800;900&display=swap');
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'Kanit', system-ui, sans-serif;
background: #020810;
color: #fff; overflow: hidden;
display: flex; align-items: center; justify-content: center; min-height: 100vh;
}
.demo { position: relative; width: 700px; height: 600px; }
canvas#holoCanvas { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.scene {
position: relative; width: 100%; height: 100%;
transform-style: preserve-3d; perspective: 1200px;
transition: transform 0.2s ease-out;
}
.node {
position: absolute;
display: flex; flex-direction: column;
align-items: center; justify-content: center; text-align: center;
border-radius: 50%;
}
/* Center hologram */
.holo-core {
left: 50%; top: 50%;
transform: translate(-50%, -50%);
width: 170px; height: 170px;
background: radial-gradient(circle at 40% 35%, rgba(0,255,255,0.15), rgba(0,200,255,0.05));
border: 2px solid rgba(0,255,255,0.5);
box-shadow: 0 0 50px rgba(0,255,255,0.2), 0 0 100px rgba(0,200,255,0.08), inset 0 0 30px rgba(0,255,255,0.05);
z-index: 10;
animation: holoPulse 2.5s ease-in-out infinite;
}
@keyframes holoPulse {
0%, 100% { border-color: rgba(0,255,255,0.5); box-shadow: 0 0 50px rgba(0,255,255,0.2), 0 0 100px rgba(0,200,255,0.08); }
50% { border-color: rgba(0,255,255,0.8); box-shadow: 0 0 70px rgba(0,255,255,0.35), 0 0 120px rgba(0,200,255,0.15); }
}
.holo-core .label { font-size: 2.8rem; font-weight: 900; color: #0ff; text-shadow: 0 0 20px rgba(0,255,255,0.5); }
.holo-core .sub { font-size: 0.7rem; color: rgba(0,255,255,0.5); margin-top: 4px; font-weight: 600; }
/* Scanline effect */
.holo-core::after {
content: ''; position: absolute; inset: 0; border-radius: 50%;
background: repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0,255,255,0.03) 2px, rgba(0,255,255,0.03) 4px);
pointer-events: none; z-index: 1;
}
/* Satellites - holographic */
.holo-sat {
width: 115px; height: 115px;
background: rgba(0,255,255,0.04);
border: 1.5px solid rgba(0,255,255,0.35);
box-shadow: 0 0 25px rgba(0,255,255,0.1), inset 0 0 20px rgba(0,255,255,0.04);
z-index: 5;
left: 50%; top: 50%;
}
.holo-sat::after {
content: ''; position: absolute; inset: 0; border-radius: 50%;
background: repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0,255,255,0.02) 2px, rgba(0,255,255,0.02) 4px);
pointer-events: none;
}
.holo-sat:nth-child(2) { transform: translate(-50%,-50%) translate3d(-220px,-140px,-80px); animation: hfloat1 5s ease-in-out infinite; }
.holo-sat:nth-child(3) { transform: translate(-50%,-50%) translate3d(180px,-20px,-30px); animation: hfloat2 6s ease-in-out infinite; }
.holo-sat:nth-child(4) { transform: translate(-50%,-50%) translate3d(-100px,210px,-100px); animation: hfloat3 5.5s ease-in-out infinite; }
@keyframes hfloat1 { 0%,100%{transform:translate(-50%,-50%) translate3d(-220px,-140px,-80px)} 50%{transform:translate(-50%,-50%) translate3d(-230px,-155px,-100px)} }
@keyframes hfloat2 { 0%,100%{transform:translate(-50%,-50%) translate3d(180px,-20px,-30px)} 50%{transform:translate(-50%,-50%) translate3d(195px,-35px,-55px)} }
@keyframes hfloat3 { 0%,100%{transform:translate(-50%,-50%) translate3d(-100px,210px,-100px)} 50%{transform:translate(-50%,-50%) translate3d(-115px,225px,-130px)} }
.holo-sat .tag { font-size: 0.9rem; font-weight: 800; color: #0ff; text-shadow: 0 0 10px rgba(0,255,255,0.4); }
.holo-sat .desc { font-size: 0.65rem; color: rgba(0,255,255,0.5); margin-top: 3px; }
.title {
position: fixed; top: 24px; left: 50%; transform: translateX(-50%);
font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.2em;
color: rgba(0,255,255,0.4); z-index: 100;
}
</style>
</head>
<body>
<span class="title">C. Holographic 3D — Hologram Sci-Fi</span>
<div class="demo">
<canvas id="holoCanvas"></canvas>
<div class="scene" id="scene">
<div class="node holo-core" data-node="center">
<span class="label">กำไร</span>
<span class="sub">เป้าหมายของทุกธุรกิจ</span>
</div>
<div class="node holo-sat" data-node="mkt">
<span class="tag">Marketing</span>
<span class="desc">เพิ่มรายได้</span>
</div>
<div class="node holo-sat" data-node="ai">
<span class="tag">AI</span>
<span class="desc">ลดต้นทุนและเวลา</span>
</div>
<div class="node holo-sat" data-node="biz">
<span class="tag">Business<br>Knowledge</span>
<span class="desc">ลดความเสี่ยง</span>
</div>
</div>
</div>
<script>
const canvas = document.getElementById('holoCanvas');
const ctx = canvas.getContext('2d');
const scene = document.getElementById('scene');
function resize() {
const rect = canvas.parentElement.getBoundingClientRect();
canvas.width = rect.width;
canvas.height = rect.height;
}
resize(); window.addEventListener('resize', resize);
let t = 0;
function draw() {
t++;
const rect = canvas.parentElement.getBoundingClientRect();
ctx.clearRect(0, 0, canvas.width, canvas.height);
const center = document.querySelector('[data-node="center"]');
const sats = document.querySelectorAll('.holo-sat');
if (!center) { requestAnimationFrame(draw); return; }
const cr = center.getBoundingClientRect();
const cx = cr.left + cr.width/2 - rect.left;
const cy = cr.top + cr.height/2 - rect.top;
sats.forEach((sat, i) => {
const pr = sat.getBoundingClientRect();
const px = pr.left + pr.width/2 - rect.left;
const py = pr.top + pr.height/2 - rect.top;
const dx = px - cx, dy = py - cy;
const dist = Math.sqrt(dx*dx + dy*dy);
// Hologram beam line (dotted)
ctx.beginPath();
ctx.setLineDash([4, 8]);
ctx.lineDashOffset = -t * 2;
ctx.moveTo(cx + (dx/dist)*85, cy + (dy/dist)*85);
ctx.lineTo(px - (dx/dist)*58, py - (dy/dist)*58);
ctx.strokeStyle = 'rgba(0,255,255,0.3)';
ctx.lineWidth = 1.5;
ctx.stroke();
ctx.setLineDash([]);
// Glow nodes at intervals
for (let j = 0; j < 5; j++) {
const phase = ((t * 0.02 + j/5 + i*0.33) % 1);
const x = cx + (dx/dist)*85 + dx * (1 - 85/dist - 58/dist) * phase;
const y = cy + (dy/dist)*85 + dy * (1 - 85/dist - 58/dist) * phase;
const alpha = Math.sin(phase * Math.PI);
ctx.beginPath();
ctx.arc(x, y, 2, 0, Math.PI*2);
ctx.fillStyle = `rgba(0,255,255,${0.6 * alpha})`;
ctx.fill();
}
});
requestAnimationFrame(draw);
}
document.addEventListener('mousemove', e => {
scene.style.transform = `rotateX(${(e.clientY/window.innerHeight-0.5)*-8}deg) rotateY(${(e.clientX/window.innerWidth-0.5)*8}deg)`;
});
draw();
</script>
</body>
</html>

View File

@@ -0,0 +1,208 @@
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>D: Constellation — แผนที่ดาว</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Kanit:wght@400;600;800;900&display=swap');
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'Kanit', system-ui, sans-serif;
background: radial-gradient(ellipse at center, #0d1520 0%, #040810 100%);
color: #fff; overflow: hidden;
display: flex; align-items: center; justify-content: center; min-height: 100vh;
}
/* Starfield background */
.stars {
position: fixed; inset: 0; z-index: 0; pointer-events: none;
}
.demo { position: relative; width: 700px; height: 600px; z-index: 1; }
canvas#constCanvas { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.scene {
position: relative; width: 100%; height: 100%;
transform-style: preserve-3d;
transition: transform 0.3s ease-out;
}
.node {
position: absolute;
display: flex; flex-direction: column;
align-items: center; justify-content: center; text-align: center;
}
/* Polaris - main star */
.star-main {
left: 50%; top: 50%;
transform: translate(-50%, -50%);
width: 150px; height: 150px; border-radius: 50%;
background: radial-gradient(circle at 38% 35%, rgba(255,255,255,0.25), rgba(254,212,0,0.15) 50%, transparent 100%);
z-index: 10;
}
.star-main .glow {
position: absolute; inset: -30px; border-radius: 50%;
background: radial-gradient(circle, rgba(254,212,0,0.08), transparent 70%);
animation: starGlow 3s ease-in-out infinite;
}
@keyframes starGlow {
0%, 100% { transform: scale(1); opacity: 0.5; }
50% { transform: scale(1.15); opacity: 0.8; }
}
.star-main .label { font-size: 2.6rem; font-weight: 900; color: #fed400; text-shadow: 0 0 30px rgba(254,212,0,0.6); position: relative; z-index: 1; }
.star-main .sub { font-size: 0.7rem; color: rgba(254,212,0,0.5); margin-top: 4px; font-weight: 600; position: relative; z-index: 1; }
/* Constellation stars */
.c-star {
width: 70px; height: 70px; border-radius: 50%;
background: radial-gradient(circle at 40% 35%, rgba(255,255,255,0.15), transparent);
z-index: 5;
left: 50%; top: 50%;
}
/* Star twinkle */
.c-star::before {
content: ''; position: absolute; inset: -15px; border-radius: 50%;
background: radial-gradient(circle, rgba(254,240,200,0.1), transparent 70%);
animation: twinkle 4s ease-in-out infinite;
}
@keyframes twinkle {
0%, 100% { opacity: 0.3; transform: scale(0.8); }
50% { opacity: 0.7; transform: scale(1.15); }
}
.c-star:nth-child(2)::before { animation-delay: 0s; }
.c-star:nth-child(3)::before { animation-delay: 1.2s; }
.c-star:nth-child(4)::before { animation-delay: 2.5s; }
/* Star points (4-point cross) */
.c-star::after {
content: ''; position: absolute; inset: -8px; border-radius: 50%;
box-shadow:
0 -25px 0 -8px rgba(254,240,200,0.3),
0 25px 0 -8px rgba(254,240,200,0.3),
-25px 0 0 -8px rgba(254,240,200,0.3),
25px 0 0 -8px rgba(254,240,200,0.3);
animation: starRotate 10s linear infinite;
}
@keyframes starRotate { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
.c-star:nth-child(2) { transform: translate(-50%,-50%) translate3d(-220px,-160px,-60px); }
.c-star:nth-child(3) { transform: translate(-50%,-50%) translate3d(190px,-30px,-30px); }
.c-star:nth-child(4) { transform: translate(-50%,-50%) translate3d(-120px,200px,-70px); }
.c-star .tag { font-size: 0.8rem; font-weight: 800; color: #fff; position: relative; z-index: 1; text-shadow: 0 0 15px rgba(255,255,255,0.4); }
.c-star .desc { font-size: 0.6rem; color: rgba(255,255,255,0.5); margin-top: 2px; position: relative; z-index: 1; }
.title {
position: fixed; top: 24px; left: 50%; transform: translateX(-50%);
font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.2em;
color: rgba(255,255,255,0.4); z-index: 100;
}
</style>
</head>
<body>
<span class="title">D. Constellation — แผนที่ดาว</span>
<!-- Starfield -->
<svg class="stars" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="s"><stop offset="0%" stop-color="#fff" stop-opacity="0.8"/><stop offset="100%" stop-color="#fff" stop-opacity="0"/></radialGradient>
</defs>
<circle cx="8%" cy="12%" r="1.5" fill="#fff" opacity="0.6"/><circle cx="15%" cy="8%" r="1" fill="#fff" opacity="0.3"/>
<circle cx="22%" cy="18%" r="0.8" fill="#fff" opacity="0.5"/><circle cx="78%" cy="10%" r="1.2" fill="#fff" opacity="0.4"/>
<circle cx="85%" cy="22%" r="1" fill="#fff" opacity="0.3"/><circle cx="92%" cy="8%" r="0.6" fill="#fff" opacity="0.7"/>
<circle cx="6%" cy="85%" r="1" fill="#fff" opacity="0.4"/><circle cx="14%" cy="92%" r="0.8" fill="#fff" opacity="0.5"/>
<circle cx="88%" cy="88%" r="1.3" fill="#fff" opacity="0.35"/><circle cx="95%" cy="78%" r="0.7" fill="#fff" opacity="0.6"/>
<circle cx="42%" cy="5%" r="0.9" fill="#fff" opacity="0.45"/><circle cx="55%" cy="3%" r="0.5" fill="#fff" opacity="0.55"/>
<circle cx="65%" cy="92%" r="1.1" fill="#fff" opacity="0.3"/><circle cx="35%" cy="95%" r="0.7" fill="#fff" opacity="0.5"/>
</svg>
<div class="demo">
<canvas id="constCanvas"></canvas>
<div class="scene" id="scene">
<div class="node star-main" data-node="center">
<div class="glow"></div>
<span class="label">กำไร</span>
<span class="sub">เป้าหมายของทุกธุรกิจ</span>
</div>
<div class="node c-star" data-node="mkt">
<span class="tag">Marketing</span>
<span class="desc">เพิ่มรายได้</span>
</div>
<div class="node c-star" data-node="ai">
<span class="tag">AI</span>
<span class="desc">ลดต้นทุน</span>
</div>
<div class="node c-star" data-node="biz">
<span class="tag">Business Knowledge</span>
<span class="desc">ลดความเสี่ยง</span>
</div>
</div>
</div>
<script>
const canvas = document.getElementById('constCanvas');
const ctx = canvas.getContext('2d');
const scene = document.getElementById('scene');
function resize() {
const rect = canvas.parentElement.getBoundingClientRect();
canvas.width = rect.width;
canvas.height = rect.height;
}
resize(); window.addEventListener('resize', resize);
function draw() {
const rect = canvas.parentElement.getBoundingClientRect();
ctx.clearRect(0, 0, canvas.width, canvas.height);
const center = document.querySelector('[data-node="center"]');
const stars = document.querySelectorAll('.c-star');
if (!center) { requestAnimationFrame(draw); return; }
const cr = center.getBoundingClientRect();
const cx = cr.left + cr.width/2 - rect.left;
const cy = cr.top + cr.height/2 - rect.top;
// Draw constellation lines (thin, elegant)
stars.forEach((star, i) => {
const pr = star.getBoundingClientRect();
const px = pr.left + pr.width/2 - rect.left;
const py = pr.top + pr.height/2 - rect.top;
const dx = px - cx, dy = py - cy;
const dist = Math.sqrt(dx*dx + dy*dy);
// Constellation line
ctx.beginPath();
ctx.moveTo(cx + (dx/dist)*75, cy + (dy/dist)*75);
ctx.lineTo(px - (dx/dist)*35, py - (dy/dist)*35);
ctx.strokeStyle = 'rgba(254,240,200,0.25)';
ctx.lineWidth = 1;
ctx.setLineDash([2, 6]);
ctx.stroke();
ctx.setLineDash([]);
// Tiny connecting stars along line
for (let j = 0; j < 3; j++) {
const p = 0.25 + j * 0.25;
const sx = cx + (dx/dist)*75 + dx * (1 - 75/dist - 35/dist) * p;
const sy = cy + (dy/dist)*75 + dy * (1 - 75/dist - 35/dist) * p;
ctx.beginPath();
ctx.arc(sx, sy, 1.2, 0, Math.PI*2);
ctx.fillStyle = 'rgba(255,255,255,0.3)';
ctx.fill();
}
});
requestAnimationFrame(draw);
}
document.addEventListener('mousemove', e => {
scene.style.transform = `rotateX(${(e.clientY/window.innerHeight-0.5)*-5}deg) rotateY(${(e.clientX/window.innerWidth-0.5)*5}deg)`;
});
draw();
</script>
</body>
</html>

View File

@@ -0,0 +1,197 @@
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>E: Magnetic Field — สนามแม่เหล็ก</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Kanit:wght@400;600;800;900&display=swap');
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'Kanit', system-ui, sans-serif;
background: #060a12;
color: #fff; overflow: hidden;
display: flex; align-items: center; justify-content: center; min-height: 100vh;
}
.demo { position: relative; width: 700px; height: 600px; }
canvas#magCanvas { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.scene {
position: relative; width: 100%; height: 100%;
transform-style: preserve-3d;
transition: transform 0.3s ease-out;
}
.node {
position: absolute;
display: flex; flex-direction: column;
align-items: center; justify-content: center; text-align: center;
border-radius: 50%;
}
/* Magnet core */
.magnet {
left: 50%; top: 50%;
transform: translate(-50%, -50%);
width: 170px; height: 170px;
background: radial-gradient(circle at 40% 35%, #3a2000, #0d0500);
border: 3px solid #fed400;
box-shadow: 0 0 0 12px rgba(254,212,0,0.1), 0 0 60px rgba(254,212,0,0.3), 0 0 140px rgba(254,180,0,0.1);
z-index: 10;
animation: magnetPulse 2s ease-in-out infinite;
}
@keyframes magnetPulse {
0%, 100% { box-shadow: 0 0 0 12px rgba(254,212,0,0.1), 0 0 60px rgba(254,212,0,0.3), 0 0 140px rgba(254,180,0,0.1); }
50% { box-shadow: 0 0 0 18px rgba(254,212,0,0.15), 0 0 80px rgba(254,212,0,0.4), 0 0 160px rgba(254,180,0,0.15); }
}
.magnet .label { font-size: 2.6rem; font-weight: 900; color: #fed400; }
.magnet .sub { font-size: 0.7rem; color: rgba(254,212,0,0.5); margin-top: 4px; font-weight: 600; }
/* Attracted nodes */
.attract {
width: 105px; height: 105px;
background: rgba(254,212,0,0.04);
border: 1.5px solid rgba(254,212,0,0.3);
box-shadow: 0 0 20px rgba(254,212,0,0.08);
z-index: 5;
left: 50%; top: 50%;
animation: attract 3s ease-in-out infinite alternate;
}
.attract:nth-child(2) {
transform: translate(-50%,-50%) translate3d(-200px,-150px,-60px);
animation-name: attract1;
}
.attract:nth-child(3) {
transform: translate(-50%,-50%) translate3d(170px,-20px,-25px);
animation-name: attract2;
}
.attract:nth-child(4) {
transform: translate(-50%,-50%) translate3d(-100px,190px,-70px);
animation-name: attract3;
}
@keyframes attract1 {
0% { transform: translate(-50%,-50%) translate3d(-220px,-160px,-80px); }
100% { transform: translate(-50%,-50%) translate3d(-185px,-140px,-50px); }
}
@keyframes attract2 {
0% { transform: translate(-50%,-50%) translate3d(185px,-25px,-35px); }
100% { transform: translate(-50%,-50%) translate3d(155px,-15px,-20px); }
}
@keyframes attract3 {
0% { transform: translate(-50%,-50%) translate3d(-120px,210px,-90px); }
100% { transform: translate(-50%,-50%) translate3d(-90px,180px,-60px); }
}
.attract .tag { font-size: 0.9rem; font-weight: 800; color: #fff; }
.attract .desc { font-size: 0.65rem; color: rgba(255,255,255,0.5); margin-top: 3px; }
.title {
position: fixed; top: 24px; left: 50%; transform: translateX(-50%);
font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.2em;
color: rgba(255,255,255,0.4); z-index: 100;
}
</style>
</head>
<body>
<span class="title">E. Magnetic Field — สนามแม่เหล็กดึงดูด</span>
<div class="demo">
<canvas id="magCanvas"></canvas>
<div class="scene" id="scene">
<div class="node magnet" data-node="center">
<span class="label">กำไร</span>
<span class="sub">เป้าหมายของทุกธุรกิจ</span>
</div>
<div class="node attract" data-node="mkt">
<span class="tag">Marketing</span>
<span class="desc">เพิ่มรายได้</span>
</div>
<div class="node attract" data-node="ai">
<span class="tag">AI</span>
<span class="desc">ลดต้นทุนและเวลา</span>
</div>
<div class="node attract" data-node="biz">
<span class="tag">Business<br>Knowledge</span>
<span class="desc">ลดความเสี่ยง</span>
</div>
</div>
</div>
<script>
const canvas = document.getElementById('magCanvas');
const ctx = canvas.getContext('2d');
const scene = document.getElementById('scene');
function resize() {
const rect = canvas.parentElement.getBoundingClientRect();
canvas.width = rect.width;
canvas.height = rect.height;
}
resize(); window.addEventListener('resize', resize);
let t = 0;
function draw() {
t++;
const rect = canvas.parentElement.getBoundingClientRect();
ctx.clearRect(0, 0, canvas.width, canvas.height);
const center = document.querySelector('[data-node="center"]');
const nodes = document.querySelectorAll('.attract');
if (!center) { requestAnimationFrame(draw); return; }
const cr = center.getBoundingClientRect();
const cx = cr.left + cr.width/2 - rect.left;
const cy = cr.top + cr.height/2 - rect.top;
// Magnetic field lines (ripple waves)
for (let r = 0; r < 4; r++) {
const radius = 95 + r * 30 + (t * 0.02) % 30;
const alpha = Math.max(0, 0.25 - r * 0.06 - ((t * 0.02) % 30) / 120);
ctx.beginPath();
ctx.arc(cx, cy, radius, 0, Math.PI*2);
ctx.strokeStyle = `rgba(254,212,0,${alpha})`;
ctx.lineWidth = 1;
ctx.stroke();
}
// Connection lines with magnetic field arcs
nodes.forEach((node, i) => {
const pr = node.getBoundingClientRect();
const px = pr.left + pr.width/2 - rect.left;
const py = pr.top + pr.height/2 - rect.top;
const dx = px - cx, dy = py - cy;
const dist = Math.sqrt(dx*dx + dy*dy);
// Main connection
ctx.beginPath();
ctx.moveTo(cx + (dx/dist)*85, cy + (dy/dist)*85);
ctx.lineTo(px - (dx/dist)*53, py - (dy/dist)*53);
ctx.strokeStyle = `rgba(254,212,0,0.4)`;
ctx.lineWidth = 2;
ctx.stroke();
// Field curve arcs on both sides
for (let side = -1; side <= 1; side += 2) {
const offset = side * 15;
const midX = cx + dx * 0.5 + (-dy/dist) * offset;
const midY = cy + dy * 0.5 + (dx/dist) * offset;
ctx.beginPath();
ctx.moveTo(cx + (dx/dist)*85, cy + (dy/dist)*85);
ctx.quadraticCurveTo(midX, midY, px - (dx/dist)*53, py - (dy/dist)*53);
ctx.strokeStyle = `rgba(254,212,0,0.1)`;
ctx.lineWidth = 1;
ctx.stroke();
}
});
requestAnimationFrame(draw);
}
document.addEventListener('mousemove', e => {
scene.style.transform = `rotateX(${(e.clientY/window.innerHeight-0.5)*-6}deg) rotateY(${(e.clientX/window.innerWidth-0.5)*6}deg)`;
});
draw();
</script>
</body>
</html>

75
public/demos/index.html Normal file
View File

@@ -0,0 +1,75 @@
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hero Design Demos</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Kanit:wght@400;600;800;900&display=swap');
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'Kanit', system-ui, sans-serif;
background: #0d1117;
color: #fff;
min-height: 100vh;
padding: 48px 24px;
}
h1 { font-size: 2rem; text-align: center; margin-bottom: 8px; }
h1 span { color: #fed400; }
.sub { text-align: center; color: rgba(255,255,255,0.5); margin-bottom: 40px; font-size: 1rem; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 20px; max-width: 1000px; margin: 0 auto; }
.card {
background: rgba(255,255,255,0.04);
border: 1px solid rgba(255,255,255,0.1);
border-radius: 16px;
padding: 32px 24px;
text-decoration: none;
color: #fff;
transition: all 0.3s ease;
display: flex; flex-direction: column; gap: 12px;
}
.card:hover { background: rgba(254,212,0,0.06); border-color: rgba(254,212,0,0.3); transform: translateY(-2px); }
.card .emoji { font-size: 3rem; }
.card .name { font-size: 1.3rem; font-weight: 800; }
.card .name span { color: #fed400; }
.card .desc { font-size: 0.82rem; color: rgba(255,255,255,0.5); line-height: 1.5; }
.card .tag { display: inline-block; font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.15em; color: rgba(254,212,0,0.6); border: 1px solid rgba(254,212,0,0.2); border-radius: 20px; padding: 4px 10px; width: fit-content; }
</style>
</head>
<body>
<h1>Hero Section — <span>5 Design Demos</span></h1>
<p class="sub">เลือกดูแต่ละแนวคิดเพื่อเปรียบเทียบ</p>
<div class="grid">
<a href="a-orbital.html" class="card">
<div class="emoji">🌌</div>
<div class="name">A. <span>Orbital</span></div>
<div class="tag">ระบบดาวเคราะห์โคจร</div>
<div class="desc">กำไรเป็นดวงอาทิตย์เรืองแสง 3 ป้ายโคจรรอบด้วยวงแหวน orbital พร้อมหมุนอัตโนมัติ</div>
</a>
<a href="b-energyflow.html" class="card">
<div class="emoji"></div>
<div class="name">B. <span>Energy Flow</span></div>
<div class="tag">กระแสพลังงาน</div>
<div class="desc">Particle วิ่งตามเส้นเชื่อมสีทอง เหมือนพลังงาน/ข้อมูลไหลเข้าสู่กำไร ดูมีชีวิตชีวา</div>
</a>
<a href="c-holographic.html" class="card">
<div class="emoji">🌀</div>
<div class="name">C. <span>Holographic 3D</span></div>
<div class="tag">Hologram Sci-Fi</div>
<div class="desc">โทน Cyan เรืองแสง พร้อม scanline และ beam เชื่อมต่อ ดูล้ำสมัย ดูแพง</div>
</a>
<a href="d-constellation.html" class="card">
<div class="emoji"></div>
<div class="name">D. <span>Constellation</span></div>
<div class="tag">แผนที่ดาว</div>
<div class="desc">โหนดเป็นดาวระยิบระยับ เส้นเชื่อมแบบกลุ่มดาว พื้นหลังมีดาวกระจาย ดูลึกลับสง่า</div>
</a>
<a href="e-magnetic.html" class="card">
<div class="emoji">🧲</div>
<div class="name">E. <span>Magnetic Field</span></div>
<div class="tag">สนามแม่เหล็ก</div>
<div class="desc">กำไรเป็นแม่เหล็กทรงพลัง มี ripple wave + field curve สื่อถึงการดึงดูดทุกอย่างสู่กำไร</div>
</a>
</div>
</body>
</html>

BIN
public/favicon-16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
public/favicon-180x180.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
public/favicon-32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
public/favicon-48x48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
public/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View 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

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View 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

View 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 965 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 832 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 992 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 745 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 996 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 815 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1016 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 887 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 899 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 731 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1011 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 980 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 796 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 918 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View 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

Some files were not shown because too many files have changed in this diff Show More