Compare commits
12 Commits
f827afb33f
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54c9b381b9 | ||
|
|
c004ee6504 | ||
|
|
479ed4722e | ||
|
|
bb1b1ba568 | ||
|
|
9ebbc91e5b | ||
|
|
f114a34a62 | ||
|
|
689a8924e6 | ||
|
|
2a3062357f | ||
|
|
1d893e1bcb | ||
|
|
61c2bd6924 | ||
|
|
fdb03f6117 | ||
|
|
0f244424c0 |
@@ -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
@@ -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.
|
|
||||||
|
|||||||
@@ -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
@@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
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 |
182
public/demos/a-orbital.html
Normal 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>
|
||||||
180
public/demos/b-energyflow.html
Normal 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>
|
||||||
179
public/demos/c-holographic.html
Normal 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>
|
||||||
208
public/demos/d-constellation.html
Normal 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>
|
||||||
197
public/demos/e-magnetic.html
Normal 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
@@ -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
|
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 |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 965 KiB |
|
After Width: | Height: | Size: 832 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 992 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 911 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 745 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 996 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 693 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 670 KiB |
|
After Width: | Height: | Size: 768 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 815 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1016 KiB |
|
After Width: | Height: | Size: 887 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 899 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 731 KiB |
|
After Width: | Height: | Size: 1011 KiB |
|
After Width: | Height: | Size: 980 KiB |
|
After Width: | Height: | Size: 600 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 796 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 866 KiB |
|
After Width: | Height: | Size: 918 KiB |
|
After Width: | Height: | Size: 289 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 956 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
BIN
public/images/portfolio/leudjorakhe.png
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 |