Compare commits

...

10 Commits

Author SHA1 Message Date
이희원 5f8e271b22 fix: 일부코드정리 2026-06-25 12:02:29 +09:00
이희원 6b77a42527 fix: 일부수정 2026-06-24 17:43:28 +09:00
이희원 fbd1a77754 fix: new version 작업 2026-06-24 17:15:42 +09:00
이희원 1415e935e7 fix: 디자인변경 초반작업 2026-06-24 14:28:57 +09:00
이희원 577bce2583 feat: concurrency 설정으로 중복 배포 방지
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 04:37:28 +09:00
이희원 1131c287f5 fix: initIntroAnimation을 DOM ready 이후 실행
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 04:36:09 +09:00
이희원 dd15c77479 fix: blob 초기 상태를 CSS에서 숨김 처리 (GSAP 로드 전 깜빡임 방지)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 04:35:11 +09:00
이희원 84bdb5de9f fix: base 경로를 './'로 통일 (서버 루트 배포)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 04:32:12 +09:00
이희원 c451d47568 fix: SSH 키 base64 디코딩 방식으로 변경
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 04:25:10 +09:00
이희원 a088ca9e1f fix: SSH 키를 env 변수로 전달하여 YAML 들여쓰기 오염 방지
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 04:23:10 +09:00
62 changed files with 899 additions and 1055 deletions

View File

@ -5,6 +5,10 @@ on:
branches:
- main
concurrency:
group: deploy
cancel-in-progress: true
jobs:
deploy:
runs-on: ubuntu-latest
@ -24,21 +28,15 @@ jobs:
- name: Build
run: npm run build
- name: Debug SSH key
run: |
echo "=== key line count ==="
echo "${{ secrets.SSH_PRIVATE_KEY }}" | wc -l
echo "=== first line ==="
echo "${{ secrets.SSH_PRIVATE_KEY }}" | head -1
echo "=== last line ==="
echo "${{ secrets.SSH_PRIVATE_KEY }}" | tail -1
- name: Deploy via SCP
env:
SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
SSH_HOST: ${{ secrets.SSH_HOST }}
SSH_PORT: ${{ secrets.SSH_PORT }}
run: |
mkdir -p ~/.ssh
printf '%s' "${{ secrets.SSH_PRIVATE_KEY }}" | tr -d '\r' > ~/.ssh/deploy_key
echo "$SSH_KEY" | base64 -d > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
echo "=== key validation ==="
ssh-keygen -l -f ~/.ssh/deploy_key || echo "KEY INVALID"
ssh-keyscan -p ${{ secrets.SSH_PORT }} -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts
scp -P ${{ secrets.SSH_PORT }} -i ~/.ssh/deploy_key -o IdentitiesOnly=yes -r dist/* root@${{ secrets.SSH_HOST }}:/var/www/proto.bodalab.diffthink.kr/
ssh-keyscan -p "$SSH_PORT" -H "$SSH_HOST" >> ~/.ssh/known_hosts
scp -P "$SSH_PORT" -i ~/.ssh/deploy_key -o IdentitiesOnly=yes -r dist/* root@"$SSH_HOST":/var/www/proto.bodalab.diffthink.kr/

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ node_modules/
dist/
.DS_Store
*.local
.mcp.json

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 MiB

After

Width:  |  Height:  |  Size: 49 MiB

133
doc/미완료.md Normal file
View File

@ -0,0 +1,133 @@
# 디자인 링크
https://www.figma.com/design/MnwN1Uzg5F6ks9Clr1brLW/%EB%94%94%EC%9E%90%EC%9D%B80624?m=auto&t=Y5wF3r0wUkUFeBIV-6
# 섹션별 링크
## PC
01_HOME:
https://www.figma.com/design/MnwN1Uzg5F6ks9Clr1brLW/%EB%94%94%EC%9E%90%EC%9D%B80624?node-id=2247-2094&t=XSGOQmdNzIB99Zh5-4
02_ABOUT:
https://www.figma.com/design/MnwN1Uzg5F6ks9Clr1brLW/%EB%94%94%EC%9E%90%EC%9D%B80624?node-id=2247-2230&t=XSGOQmdNzIB99Zh5-4
03_HISTORY:
https://www.figma.com/design/MnwN1Uzg5F6ks9Clr1brLW/%EB%94%94%EC%9E%90%EC%9D%B80624?node-id=2247-2121&t=XSGOQmdNzIB99Zh5-4
04_VISION:
https://www.figma.com/design/MnwN1Uzg5F6ks9Clr1brLW/%EB%94%94%EC%9E%90%EC%9D%B80624?node-id=2247-2183&t=XSGOQmdNzIB99Zh5-4
05_PROJECT:
https://www.figma.com/design/MnwN1Uzg5F6ks9Clr1brLW/%EB%94%94%EC%9E%90%EC%9D%B80624?node-id=2247-2202&t=XSGOQmdNzIB99Zh5-4
06_Expertise:
https://www.figma.com/design/MnwN1Uzg5F6ks9Clr1brLW/%EB%94%94%EC%9E%90%EC%9D%B80624?node-id=2247-2253&t=XSGOQmdNzIB99Zh5-4
## Mobile
01_HOME:
https://www.figma.com/design/MnwN1Uzg5F6ks9Clr1brLW/%EB%94%94%EC%9E%90%EC%9D%B80624?node-id=2319-2232&t=XSGOQmdNzIB99Zh5-4
02_ABOUT:
https://www.figma.com/design/MnwN1Uzg5F6ks9Clr1brLW/%EB%94%94%EC%9E%90%EC%9D%B80624?node-id=2319-2288&t=XSGOQmdNzIB99Zh5-4
03_HISTORY:
https://www.figma.com/design/MnwN1Uzg5F6ks9Clr1brLW/%EB%94%94%EC%9E%90%EC%9D%B80624?node-id=2319-2433&t=XSGOQmdNzIB99Zh5-4
04_VISION:
https://www.figma.com/design/MnwN1Uzg5F6ks9Clr1brLW/%EB%94%94%EC%9E%90%EC%9D%B80624?node-id=2319-4183&t=XSGOQmdNzIB99Zh5-4
05_PROJECT:
https://www.figma.com/design/MnwN1Uzg5F6ks9Clr1brLW/%EB%94%94%EC%9E%90%EC%9D%B80624?node-id=2319-4231&t=XSGOQmdNzIB99Zh5-4
06_Expertise:
https://www.figma.com/design/MnwN1Uzg5F6ks9Clr1brLW/%EB%94%94%EC%9E%90%EC%9D%B80624?node-id=2319-5082&t=XSGOQmdNzIB99Zh5-4
---
# 전체검수 결과 (2026-06-25)
이전 세션(어제) 작업물을 전체 점검함. 6개 섹션 모두 마크업/스타일/JS 반영되어 있고 `npm run build` 통과 확인.
발견해서 바로 고친 것:
- **포맷 불일치** — "포맷 완료"로 기록돼 있었지만 실제로는 7개 파일이 Prettier 규칙(CRLF 줄바꿈)을 안 지키고 있었음. `npm run format`으로 재정리.
- **PROJECT 카드 날짜 표시** — Figma 새 디자인엔 날짜가 없는데 `project__date`(예: "2023.12")가 마크업/CSS에 남아있던 걸 발견. 사용자 확인 후 전부 제거(`project__meta` 래퍼도 함께 정리, `_project.scss``.project__meta`/`.project__date` 규칙 삭제).
- **안 쓰는 파일 정리**`history-2.jpg`, `history-3.jpg`(미참조), `pnpm-lock.yaml`, `pnpm-workspace.yaml`(npm 단일 워크플로우와 혼용되던 흔적, CI는 `npm ci`만 사용) 삭제. 사용자 확인 후 진행.
검수 후에도 남아있는 미해결 항목은 아래 그대로.
---
# 미완료 / 확인 필요 항목 (위에서부터 확인)
추측해서 임의로 채운 값이 아니라, 실제로 막힌 지점만 기록한다. 아래 항목들은 자산(이미지/폰트) 전달이나 사용자 결정이 필요해서 남아있다.
## PROJECT
- **이미지 9~13번 누락** — 9(프로스펙스)·10(중소기업창업)·11(롯데 GA2ck)·12(국민은행)·13(코나아이 PC) 카드는 Figma 새 디자인엔 실제 목업 이미지가 있는데, figma-mcp로는 이미지 export가 안 돼서 빈 박스(`project__thumbEmpty`)로 남아있음. **사용자가 Figma에서 직접 5개 이미지를 export 해서 `src/images/project-9.jpg` ~ `project-13.jpg`로 전달해야 적용 가능.**
## GNB (모바일 드로어)
- **폰트 확인 필요** — 모바일 메뉴 항목 폰트가 처음엔 Figma 렌더에서 업라이트(정체) 세리프로 보인다고 판단해서 프로젝트에 있는 `DM Serif Display Italic`(이탤릭)으로 대체 적용했었음. 그런데 다시 렌더(`2319:5998`)를 보니 오히려 **민무늬 산세리프**(획 두께 균일, O/A가 기하학적 원형)처럼 보여서 기존 판단이 맞는지 의문이 생김. 사용자에게 (1) 지금처럼 이탤릭 세리프 유지 (2) 산세리프(SUIT 등)로 변경 (3) 별도 업라이트 세리프 폰트 파일 구해서 교체, 셋 중 결정 필요.
## HISTORY
- 좌측 세로 사진(나선형 건축물 텍스처)은 에셋 추출이 안 돼서 기존 `images/history-1.jpg`를 임시로 대체 사용 중. 실제 Figma 이미지로 교체 필요.
- 2024/2023/2022/2021년 그룹은 Figma 렌더에서 아코디언이 collapsed 상태로 보여서 항목이 1개씩만 보인다(2024: 우리은행 로보어드바이저 구축, 2023: 신한은행 슈퍼SOL 운영 계약, 2022: 한화금융 서비스앱 플러스 리뉴얼 2차 계약, 2021: 롯데 렌터카 차세대 구축 계약). 펼쳤을 때 추가 항목이 더 있는지 정적 렌더로는 확인이 안 돼서 일단 보이는 1개씩만 반영함. 펼침 상태의 전체 목록 확인 필요.
- HISTORY 섹션의 모바일 레이아웃은 별도 figma 크롭을 못 받아서, 좌측 사진을 숨기고 타임라인만 세로로 쌓는 형태로 추정 구현함. 실제 모바일 디자인 확인 필요.
## VISION
- 배경의 별빛/우주 텍스처 이미지는 ABOUT US와 마찬가지로 에셋 추출이 안 돼서 단색 `$color-bg`로 대체함.
- **인용구 폰트 결정 필요** — 인용구("Flawless execution...") 텍스트의 Figma 렌더 폰트가 라운드체 산세리프로 보이는데, 프로젝트에 등록된 폰트(SUIT, DM Serif Display Italic) 중 일치하는 게 없음. 일단 SUIT로 대체했음. (1) 지금처럼 SUIT 유지 (2) 라운드체 산세리프 폰트 파일을 구해서 교체, 둘 중 결정 필요.
---
# 완료된 항목 (참고용, 더 손댈 필요 없음)
## HOME
- **배경 패턴** — 동심원 패턴이 아니라 Unsplash 무료 사진(`A star trail over a body of water`, 작가 Reign Abarintos, id `-cKXtsJWU-I`)으로 확인됨. 순수 CSS로는 재현 불가 판단(불규칙한 별빛 줄무늬·노이즈가 있는 실제 사진). 사용자가 Figma에서 export해서 `src/images/bg_home.png`로 전달 → 적용 완료(2026-06-24). 자리채움으로 쓰던 GSAP blob 애니메이션(컬러 블러 도형)은 Figma에 없는 요소라 사용자 확인받고 완전히 제거(`.intro__blobs`/`.blob*` 마크업·SCSS·JS), `.intro__bg`(배경 이미지, opacity 0.2, GSAP 0→0.2 페이드인)로 교체. 텍스트 순차 등장 애니메이션은 유지.
## PROJECT
- 카드 레이아웃을 고정 `aspect-ratio: 16/10` 크롭 방식에서 이미지 원본 비율 그대로 쌓는 매스너리 방식으로 변경(`_projects.scss`).
- 11번째 카드 내용을 "한화 GAsk 구축 프로젝트(한화)" → "롯데 GA2ck 구축 프로젝트 (롯데 렌터카)(롯데)"로 수정 — 사용자 확인받고 반영함. 날짜(`2021.11`)는 기존 값 유지, 재확인 안 함.
## CONTACT/FOOTER
- 문서 상단 "06_Expertise" 링크(PC `2247:2253` / 모바일 `2319:5082`)가 실제로는 CONTACT/FOOTER 디자인이었음(라벨 오기로 추정). 기존에 중복으로 남아있던 옛 `<section id="expertise">`(4개 서비스 목록, 이미 ABOUT 섹션에 이전되어 있던 내용)는 삭제.
- CONTACT를 "WELCOME BODA LAB" 헤딩 + 설명 + Head Office(Address/e-mail/tel 3필드, fax·지도 삭제) + Contact Us 폼(2단: 입력 4개 스택 + 우측 문의내용, placeholder에 `*`, 체크박스 문구를 "[필수] 개인정보 수집 및 이용 동의"로) + Recruitment 태그 구조로 교체. 아코디언 라벨 "프로젝트 문의"→"Contact Us", "채용"→"Recruitment". Head Office 정보도 새 값으로 교체: Address "서울시 강서구 마곡중앙로 161-8, 두산더랜드파크 C동 618호" / e-mail `koji@bodalab.co.kr` / tel `010-4169-4728`.
- **색상 1차 작업 누락 → 재수정함**: 처음엔 다른 섹션과 동일하게 다크 테마(검은 배경/흰 텍스트)로 만들었는데, 사용자가 Figma와 다르다고 지적함. 다시 렌더 확인해보니 이 섹션(CONTACT)만 Figma에서 **흰 배경 + 검은 텍스트**(라이트 테마)로 되어 있었음 — 다른 섹션과 의도적으로 색 반전된 구간. `_contact.scss` 전체를 라이트 테마로 재작업: 배경 `$color-white`, 텍스트 `$color-dark` 계열, 강조색(Address/e-mail/tel 라벨, SEND 버튼, 체크박스 체크 상태, Recruitment 태그 hover)은 `$color-cyan`→`$color-blue`(`#7796ff`)로 교체. 아코디언 화살표 아이콘(`icon-chevron.svg`)은 흰색 stroke라 흰 배경에서 안 보이므로 `filter: invert(1)`로 우회. `.footer``.contact` 안에 있어서 같은 배경을 쓰게 되므로 footer 텍스트 색도 함께 라이트 테마로 변경(footer 전용 Figma 노드는 없어서 추정 적용).
- footer 연락처가 옛 값(`bodalab@bodalab.com`, `010-1234-5678`)으로 Head Office의 새 연락처와 다른 문제 — **사용자가 현행 유지로 결정함(2026-06-24)**. footer 전용 Figma 노드가 없어서 더 손대지 않음.
- `npm run build` 통과, playwright로 PC(1440px)/모바일(390px) 스크린샷 확인하여 Figma 렌더와 색상·레이아웃 일치 확인함.
## GNB
- **점검 완료(2026-06-24)** — playwright로 769px~1440px 전 구간 데스크톱 nav 줄바꿈/overflow 없음 확인, 스크롤에 따른 `isActive` 전환(섹션 진입 시 해당 메뉴로 자동 전환) 정상 동작 확인, 모바일 풀스크린 드로어도 정상.
- 모바일 드로어 메뉴 라벨 "PROJECTS"(복수형)가 데스크톱 nav·PROJECT 섹션 타이틀("PROJECT", 단수형)과 다른 것처럼 보였으나, Figma 모바일 드로어 렌더(`2319:5998`)에도 "PROJECTS"로 되어 있어서 **현행 유지**(불일치 아니라 Figma 의도).
## 최종 정리
- ~~파일명 정리~~**완료(2026-06-24)**. `_projects.scss``_project.scss`로 리네임, `index.scss``@use "page/projects"``@use "page/project"`로 수정. 빌드 재확인 통과.
- ~~안 쓰는 이미지 정리~~**완료(2026-06-24)**. `about-hand.jpg`(7.4MB), `vision-1/2/3.jpg`, `map.svg` 전부 코드 내 참조 없음을 grep으로 재확인 후 삭제함. `history-1.jpg`는 재사용 중이라 유지.
- ~~`npm run format`~~**완료(2026-06-24)**. `introAnimation.js` 포맷팅 외 변경 없음. `npm run build`도 재확인 통과.
---
# 참고: Figma 노드 ID 모음 (file_key: `MnwN1Uzg5F6ks9Clr1brLW`)
- PC 전체 페이지(컴포지트, 모든 섹션 한눈에 보임): `2247:2093`
- 01_HOME (PC): `2247:2094`
- 02_ABOUT US (PC, EXPERTISE 포함): `2247:2230`
- 03_HISTORY (PC): `2247:2121`
- VISION PC: `2247:2183` / VISION 모바일: `2319:4183`
- PROJECT PC: `2247:2202` / PROJECT 모바일: `2319:4231` — 렌더 확인 완료, 반영 완료(이미지 9~13 제외)
- CONTACT/FOOTER (문서 상단 "06_Expertise" 링크가 실제 이 내용임) PC: `2247:2253` / 모바일: `2319:5082` — 렌더 확인·반영 완료(footer 영역 제외)
- 모바일 전체 페이지(컴포지트): `2319:5243`
- 모바일 GNB 드로어(열린 상태): `2319:5998`
# 참고: Figma MCP 연결 관련 메모 (재현/트러블슈팅용)
- **환경이 Windows(`d:/repository/boda-lab`)에서 이 Mac(`/Users/heemac/repository/project-bodalab`)으로 바뀜.** Windows 때 설정(`.mcp.json`에 nvm4w 절대경로 `npx.cmd` 지정)은 이 머신에 적용 안 됨 — npx/node 자체가 새로 깔린 환경이라 처음엔 figma-mcp가 전혀 연결 안 되어 있었음.
- 이 Mac에서는 프로젝트 루트 `.mcp.json`(git에는 `.gitignore`로 추적 제외됨)에 `{ "mcpServers": { "figma": { "command": "npx", "args": ["-y", "figma-mcp"], "env": { "FIGMA_API_KEY": "..." } } } }` 형태로 새로 등록함. macOS는 nvm 심볼릭링크 문제가 없어서 `command: "npx"`만으로 동작함(절대경로 불필요).
- **`.mcp.json`은 세션 시작 시점에 로드된다.** 파일을 새로 만들거나 고쳐도 같은 대화 세션에는 바로 안 먹히고, Claude Code를 재시작(새 세션)해야 도구가 인식됨.
- 도구: `mcp__figma__add_figma_file(url)` — 파일 전체를 JSON으로 덤프하는데, 파일이 커서 약 25k 토큰 근처(`01_HOME`~`03_HISTORY` 중반)에서 항상 잘림. `node-id` 쿼리 파라미터를 URL에 넣어도 무시되고 항상 전체 문서 기준으로 덤프됨 — 범위 제한 불가.
- 도구: `mcp__figma__view_node(file_key, node_id)` — 특정 노드를 PNG로 렌더해서 보여줌(파일로 저장은 안 됨, 대화창에만 표시). 섹션별 정밀 확인에 주력 도구로 사용 중. 429(Rate Limit)가 났던 적이 있었으나 환경이 바뀐 뒤로는 재현 안 됨.
- 이미지 에셋(사진/목업) 자체는 이 MCP로 export/저장이 안 됨 — 필요한 이미지는 Figma에서 사용자가 직접 Export 해서 `src/images/`에 넣어줘야 함.
# 참고: 공통 / 도구 제약
- `add_figma_file`이 파일 전체를 한 번에 JSON 덤프하는 방식이라 토큰 한도에 걸려 `01_HOME` ~ `03_HISTORY` 중반 이후 노드는 JSON으로 못 받았다. `view_node(file_key, node_id)`로 노드 ID를 알 때만 PNG 렌더로 확인 가능. VISION/PROJECT/CONTACT 등 이후 섹션은 작업 시점에 사용자에게 "Copy link to selection" 링크를 요청해서 진행한다.
- `view_node`는 이미지를 대화창에 렌더만 해줄 뿐, 파일로 저장(export)하는 기능이 없다. 따라서 Figma 안의 사진/목업 이미지 에셋(배경 텍스처, 프로젝트 카드 스크린샷 등)은 이 MCP로 직접 추출이 불가능하다. 실제 자산은 Figma에서 직접 "Export" 해서 `src/images/`에 받아와야 한다.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 639 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 385 KiB

View File

@ -18,10 +18,12 @@
</a>
<nav class="gnb__nav">
<ul class="gnb__navList">
<li class="gnb__navItem"><a class="gnb__navLink" href="#intro">HOME</a></li>
<li class="gnb__navItem"><a class="gnb__navLink" href="#about">ABOUT</a></li>
<li class="gnb__navItem"><a class="gnb__navLink" href="#project">PROJECTS</a></li>
<li class="gnb__navItem"><a class="gnb__navLink" href="#contact">CONTACT</a></li>
<li class="gnb__navItem"><a class="gnb__navLink isActive" href="#intro">HOME</a></li>
<li class="gnb__navItem"><a class="gnb__navLink" href="#about">ABOUT US</a></li>
<li class="gnb__navItem"><a class="gnb__navLink" href="#history">HISTORY</a></li>
<li class="gnb__navItem"><a class="gnb__navLink" href="#vision">VISION</a></li>
<li class="gnb__navItem"><a class="gnb__navLink" href="#project">PROJECT</a></li>
<li class="gnb__navItem"><a class="gnb__navLink" href="#contact">CONTACT US</a></li>
</ul>
</nav>
<button class="gnb__hamburger" aria-label="메뉴 열기" aria-expanded="false">
@ -32,11 +34,17 @@
</div>
<!-- 모바일 메뉴 -->
<nav class="gnb__mobileNav">
<button class="gnb__mobileNavClose" aria-label="메뉴 닫기">
<span class="gnb__mobileNavCloseLine"></span>
<span class="gnb__mobileNavCloseLine"></span>
</button>
<ul class="gnb__mobileNavList">
<li class="gnb__mobileNavItem"><a class="gnb__mobileNavLink" href="#intro">HOME</a></li>
<li class="gnb__mobileNavItem"><a class="gnb__mobileNavLink" href="#about">ABOUT</a></li>
<li class="gnb__mobileNavItem"><a class="gnb__mobileNavLink isActive" href="#intro">HOME</a></li>
<li class="gnb__mobileNavItem"><a class="gnb__mobileNavLink" href="#about">ABOUT US</a></li>
<li class="gnb__mobileNavItem"><a class="gnb__mobileNavLink" href="#history">HISTORY</a></li>
<li class="gnb__mobileNavItem"><a class="gnb__mobileNavLink" href="#vision">VISION</a></li>
<li class="gnb__mobileNavItem"><a class="gnb__mobileNavLink" href="#project">PROJECTS</a></li>
<li class="gnb__mobileNavItem"><a class="gnb__mobileNavLink" href="#contact">CONTACT</a></li>
<li class="gnb__mobileNavItem"><a class="gnb__mobileNavLink" href="#contact">CONTACT US</a></li>
</ul>
</nav>
</header>
@ -44,15 +52,10 @@
<main>
<!-- 01. INTRO -->
<section id="intro" class="intro">
<div class="intro__blobs" aria-hidden="true">
<div class="blob blobCyan"></div>
<div class="blob blobPurple"></div>
<div class="blob blobBlue"></div>
</div>
<div class="intro__bg" aria-hidden="true"></div>
<div class="intro__content">
<p class="intro__sub">Creative Development Company</p>
<p class="intro__sub">Our Company</p>
<h1 class="intro__title">THE BODA LAB</h1>
</div>
@ -62,269 +65,248 @@
</section>
<!-- 02. ABOUT -->
<!-- 02. ABOUT US -->
<section id="about" class="about">
<div class="about__bg" aria-hidden="true"></div>
<div class="about__inner">
<div class="about__text">
<div class="about__head">
<h2 class="sectionTitle">ABOUT US</h2>
<p class="desc">
The BODA LAB은 디지털시대에 발맞춰 클라이언트의 비즈니스를 위한<br class="breakLine" />
다양한 기술적 노하우로 완성된 경험을 제공합니다.<br class="breakLine" />
우리의 활동은 웹, 앱, 모바일을 넘나들며 세상의 모든 비즈니스 활동에 강한 영향력을 전달합니다.
<p class="about__desc">
디지털 시대에 발맞춰, 차별화된 기술적 노하우로 클라이언트의 비즈니스에 완벽한 디지털 경험을 선사합니다.<br class="breakLine" />
우리의 스펙트럼은 웹과 앱을 넘어 세상의 모든 비즈니스에 강력한 영향력을 전합니다.
</p>
</div>
<div class="about__image">
<img class="about__imageThumb" src="images/about-hand.jpg" alt="스케치하는 손" />
</div>
<div class="about__caption">
<div class="about__captionTrack">
<span class="about__captionText">Creative Development Company BODA.Lab</span>
<span class="about__captionText">Creative Development Company BODA.Lab</span>
<span class="about__captionText">Creative Development Company BODA.Lab</span>
<span class="about__captionText">Creative Development Company BODA.Lab</span>
<div class="about__quote">
<span class="about__quoteMark" aria-hidden="true"></span>
<p class="about__quoteText">Creative Development Company<br />BODA.Lab</p>
</div>
</div>
<ul class="about__expertiseList">
<li class="about__expertiseItem">
<span class="num">01</span>
<h3 class="name">UX<br />Consulting</h3>
<p class="text">UX 컨설팅</p>
</li>
<li class="about__expertiseItem">
<span class="num">02</span>
<h3 class="name">Plarform<br />Building</h3>
<p class="text">웹사이트 구축</p>
</li>
<li class="about__expertiseItem">
<span class="num">03</span>
<h3 class="name">Mobile<br />App &amp; Web</h3>
<p class="text">모바일 앱 &amp;</p>
</li>
<li class="about__expertiseItem">
<span class="num">04</span>
<h3 class="name">Service<br />Management</h3>
<p class="text">서비스 운영</p>
</li>
</ul>
</div>
</section>
<!-- 03. HISTORY -->
<section id="history" class="history">
<div class="history__top">
<h2 class="sectionTitle sectionTitleDark">HISTORY</h2>
<div class="history__inner">
<h2 class="sectionTitle sectionTitleDark history__title">HISTORY</h2>
<div class="history__photo">
<img class="img" src="images/history-1.jpg" alt="" />
</div>
<div class="history__timeline">
<div class="history__yearGroup">
<span class="history__year">2024</span>
<ul class="history__list">
<div class="history__yearGroup isOpen">
<button class="history__yearToggle" aria-expanded="true" aria-controls="history2025">
<span class="history__year">2025</span>
<span class="icon" aria-hidden="true"></span>
</button>
<ul class="history__list" id="history2025">
<li class="history__listItem">
<strong class="history__listDate">12.01</strong>
<span class="history__listText">신한은행 슈퍼소울 운영 계약</span>
<div class="main">
<h3 class="title">한국전자기술연구원 대쉬보드 구축</h3>
<p class="sub">
유체기기 위험 운전 알고리즘 모니터링 프로그램 / 송풍 제어 모듈 비정상 운전 상태 진단 프로그램<br />
윈도우 프로그래밍 개발, 대시보드 UX UI 기획/디자인
</p>
</div>
<span class="date">25.12 - 26.02</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">09.01</strong>
<span class="history__listText">한화금융통합 서비스 구축 계약</span>
<div class="main">
<h3 class="title">현대차 판매시스템 구축</h3>
<p class="sub">React.Js, F/E, B/E 개발</p>
</div>
<span class="date">25.08 - 26.06</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">05.30</strong>
<span class="history__listText">신한은행 슈퍼소울 구축 계약</span>
<div class="main">
<h3 class="title">LG 개인정보삭제 프로그램개발</h3>
<p class="sub">React.Js, F/E, B/E 개발</p>
</div>
<span class="date">25.08 - 25.12</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">05.01</strong>
<span class="history__listText">롯데 렌터카 오토리스 구축 계약</span>
<div class="main">
<h3 class="title">신한투자증권_New 슈퍼SOL 통합 프로젝트 <span class="badge">Finance</span></h3>
<p class="sub">Vue.Js, Publishing</p>
</div>
<span class="date">25.07 - 26.07</span>
</li>
<li class="history__listItem">
<div class="main">
<h3 class="title">신한은행_New 슈퍼SOL 통합 프로젝트 <span class="badge">Finance</span></h3>
<p class="sub">React.Js, Purescript, Publishing</p>
</div>
<span class="date">25.07 - 26.06</span>
</li>
<li class="history__listItem">
<div class="main">
<h3 class="title">한화생명 신탁시스템 재구축 <span class="badge">Finance</span></h3>
<p class="sub">React.Js, Pblishing, UX UI 기획, F/E 개발</p>
</div>
<span class="date">25.06 - 26.06</span>
</li>
<li class="history__listItem">
<div class="main">
<h3 class="title">SK매직 운영 개발</h3>
<p class="sub">React.Js, Vue.Js, F/E, B/E 개발</p>
</div>
<span class="date">25.07 - 25.12</span>
</li>
<li class="history__listItem">
<div class="main">
<h3 class="title">롯데카드 외국인 선불카드 연계플랫폼 구축대행 <span class="badge">Finance</span></h3>
<p class="sub">Vue.Js, Next.Js, Publishing, F/E 개발</p>
</div>
<span class="date">25.04 - 25.11</span>
</li>
<li class="history__listItem">
<div class="main">
<h3 class="title">LG전자 홈스타일(리빙) 서비스 구축 프로젝트</h3>
<p class="sub">UX UI 기획</p>
</div>
<span class="date">25.04 - 25.08</span>
</li>
<li class="history__listItem">
<div class="main">
<h3 class="title">에어인천 ERP 구축 프로젝트</h3>
<p class="sub">UX UI 디자인, Publishing</p>
</div>
<span class="date">25.03 - 25.04</span>
</li>
<li class="history__listItem">
<div class="main">
<h3 class="title">하나캐피탈 자산관리시스템 재구축 프로젝트 <span class="badge">Finance</span></h3>
<p class="sub">Vue.Js, Nuxt.Js, Publishing, F/E 개발</p>
</div>
<span class="date">25.03 - 25.08</span>
</li>
<li class="history__listItem">
<div class="main">
<h3 class="title">현대해상 고도화 구축 <span class="badge">Finance</span></h3>
<p class="sub">React, Typescript, Scss</p>
</div>
<span class="date">25.02 - 26.01</span>
</li>
<li class="history__listItem">
<div class="main">
<h3 class="title">우리은행 전자지갑 구축 <span class="badge">Finance</span></h3>
<p class="sub">React, Typescript, Recoil, Spring Boot</p>
</div>
<span class="date">25.01 - 25.07</span>
</li>
</ul>
</div>
<div class="history__yearGroup">
<span class="history__year">2023</span>
<ul class="history__list">
<button class="history__yearToggle" aria-expanded="false" aria-controls="history2024">
<span class="history__year">2024</span>
<span class="icon" aria-hidden="true"></span>
</button>
<ul class="history__list" id="history2024" hidden>
<li class="history__listItem">
<strong class="history__listDate">12.01</strong>
<span class="history__listText">신한은행 슈퍼소울 운영 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">11.01</strong>
<span class="history__listText">한화금융 라이프 플러스 아카데미 구축 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">10.01</strong>
<span class="history__listText">대교 차세대 구축 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">09.01</strong>
<span class="history__listText">한화금융통합 서비스 구축 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">05.30</strong>
<span class="history__listText">신한은행 슈퍼소울 구축 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">05.01</strong>
<span class="history__listText">롯데 렌터카 오토리스 구축 계약</span>
<div class="main">
<h3 class="title">우리은행 로보어드바이저 구축 <span class="badge">Finance</span></h3>
<p class="sub">React, Typescript, Recoil</p>
</div>
<span class="date">24.11 - 25.07</span>
</li>
</ul>
</div>
<div class="history__yearGroup">
<span class="history__year">2022</span>
<ul class="history__list">
<button class="history__yearToggle" aria-expanded="false" aria-controls="history2023">
<span class="history__year">2023</span>
<span class="icon" aria-hidden="true"></span>
</button>
<ul class="history__list" id="history2023" hidden>
<li class="history__listItem">
<strong class="history__listDate">11.01</strong>
<span class="history__listText">한화금융 서비스앱 플러스 리뉴얼 2차 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">09.01</strong>
<span class="history__listText">한화금융 서비스앱 플러스 리뉴얼 1차 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">08.01</strong>
<span class="history__listText">밀레 쇼핑몰 리뉴얼 구축 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">07.01</strong>
<span class="history__listText">오뚜기 쇼핑몰 리뉴얼 구축 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">05.01</strong>
<span class="history__listText">캐나다구스 코리아 쇼핑몰 구축 계약</span>
<div class="main">
<h3 class="title">신한은행 슈퍼SOL 운영 계약 <span class="badge">Finance</span></h3>
<p class="sub">Vue</p>
</div>
<span class="date">23.12</span>
</li>
</ul>
</div>
<div class="history__yearGroup">
<span class="history__year">2023</span>
<ul class="history__list">
<button class="history__yearToggle" aria-expanded="false" aria-controls="history2022">
<span class="history__year">2022</span>
<span class="icon" aria-hidden="true"></span>
</button>
<ul class="history__list" id="history2022" hidden>
<li class="history__listItem">
<strong class="history__listDate">12.01</strong>
<span class="history__listText">신한은행 슈퍼소울 운영 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">11.01</strong>
<span class="history__listText">한화금융 라이프 플러스 아카데미 구축 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">10.01</strong>
<span class="history__listText">대교 차세대 구축 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">09.01</strong>
<span class="history__listText">한화금융통합 서비스 구축 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">05.30</strong>
<span class="history__listText">신한은행 슈퍼소울 구축 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">05.01</strong>
<span class="history__listText">롯데 렌터카 오토리스 구축 계약</span>
<div class="main">
<h3 class="title">한화금융 서비스앱 플러스 리뉴얼 2차 계약 <span class="badge">Finance</span></h3>
</div>
<span class="date">22.11</span>
</li>
</ul>
</div>
<div class="history__yearGroup">
<span class="history__year">2022</span>
<ul class="history__list">
<button class="history__yearToggle" aria-expanded="false" aria-controls="history2021">
<span class="history__year">2021</span>
<span class="icon" aria-hidden="true"></span>
</button>
<ul class="history__list" id="history2021" hidden>
<li class="history__listItem">
<strong class="history__listDate">11.01</strong>
<span class="history__listText">한화금융 서비스앱 플러스 리뉴얼 2차 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">09.01</strong>
<span class="history__listText">한화금융 서비스앱 플러스 리뉴얼 1차 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">08.01</strong>
<span class="history__listText">밀레 쇼핑몰 리뉴얼 구축 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">07.01</strong>
<span class="history__listText">오뚜기 쇼핑몰 리뉴얼 구축 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">05.01</strong>
<span class="history__listText">케나다구스 코리아 쇼핑몰 구축 계약</span>
<div class="main">
<h3 class="title">롯데 렌터카 차세대 구축 계약</h3>
</div>
<span class="date">21.11</span>
</li>
</ul>
</div>
<div class="history__yearGroup">
<span class="history__year">2021</span>
<ul class="history__list">
<li class="history__listItem">
<strong class="history__listDate">11.22</strong>
<span class="history__listText">롯데 렌터카 차세대 구축 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">11.01</strong>
<span class="history__listText">LSN MALL 구축 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">7.29</strong>
<span class="history__listText">(주)보다랩 설립</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">5.15</strong>
<span class="history__listText">현대홈쇼핑 리뉴얼 구축 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">01.11</strong>
<span class="history__listText">KONA I 헬스케어 구축 계약</span>
</li>
<li class="history__listItem">
<strong class="history__listDate">01.11</strong>
<span class="history__listText">유아이팩토리 설립</span>
</li>
</ul>
</div>
</div>
</div>
<div class="history__bottom">
<img class="history__img history__img--1" src="images/history-1.jpg" alt="" />
<img class="history__img history__img--2" src="images/history-2.jpg" alt="" />
<img class="history__img history__img--3" src="images/history-3.jpg" alt="" />
</div>
</section>
<!-- 04. BODA INTRO -->
<section id="boda-intro" class="bodaIntro">
<div class="bodaIntro__content">
<h2 class="bodaIntro__title">BODA Lab Co., Ltd.</h2>
<p class="bodaIntro__desc">
accurately identifies customer needs to<br class="breakLine" />
achieve the best completeness and satisfaction.<br class="breakLine" />
We are working on a project with talented<br class="breakLine" />
people with high technology.
</p>
</div>
<a href="#vision" class="scrollDown scrollDownSm" aria-label="아래로 스크롤"><img src="images/icon-scroll-down.svg" alt="" /></a>
</section>
<!-- 05. VISION -->
<!-- 04. VISION -->
<section id="vision" class="vision">
<div class="vision__inner">
<div class="vision__item">
<div class="vision__text">
<em class="vision__keyword">Perspective</em>
<p class="vision__textDesc">
클라이언트의 고유한 가치를 발견하고
<br class="breakLine" />
차별화된 디지털 경험을 설계합니다.
</p>
</div>
<div class="vision__image">
<img class="vision__imageThumb" src="images/vision-1.jpg" alt="Uniqueness" />
</div>
<div class="vision__head">
<h2 class="sectionTitle">VISION</h2>
<p class="vision__desc">우리는 고객사의 니즈를 정확히 파악하고, 우수한 기술력을 가진 인재들을 투입하여 프로젝트의 완성도와 만족도를 극대화합니다.</p>
</div>
<div class="vision__item vision__itemReverse">
<div class="vision__image">
<img class="vision__imageThumb" src="images/vision-2.jpg" alt="Expertise" />
</div>
<div class="vision__text">
<em class="vision__keyword">Expertise</em>
<p class="vision__textDesc">
10년 이상의 기술 노하우를 기반으로
<br class="breakLine" />
최적의 솔루션을 제공합니다.
</p>
</div>
</div>
<div class="vision__item">
<div class="vision__text">
<em class="vision__keyword">Satisfaction</em>
<p class="vision__textDesc">
고객의 만족을 최우선 가치로 삼아
<br class="breakLine" />
완성도 높은 결과물을 만듭니다.
</p>
</div>
<div class="vision__image">
<img class="vision__imageThumb" src="images/vision-3.jpg" alt="Satisfaction" />
</div>
<div class="vision__quote">
<span class="mark" aria-hidden="true"></span>
<p class="text">Flawless execution, absolute satisfaction. BODA Lab delivers excellence through advanced tech talent.</p>
</div>
<ul class="vision__keywordList">
<li class="vision__keywordItem">
<h3 class="keyword">PERSPECTIVE</h3>
<p class="desc">고객사의 눈으로 관점을 바라봅니다.</p>
</li>
<li class="vision__keywordItem">
<h3 class="keyword">EXPERTISE</h3>
<p class="desc">다양한 기술력을 가진 인재들을 보유하고 있습니다.</p>
</li>
<li class="vision__keywordItem">
<h3 class="keyword">SATISFACTION</h3>
<p class="desc">타사보다 높은 만족도와 완성도를 갖추고 있습니다.</p>
</li>
</ul>
</div>
</section>
@ -338,10 +320,7 @@
<img class="project__thumbImg" src="images/project-1.jpg" alt="신한유니버설앱 구축" />
</div>
<div class="project__info">
<div class="project__meta">
<h3 class="project__name">신한유니버설앱 구축</h3>
<span class="project__date">2023.12</span>
</div>
<h3 class="project__name">신한유니버설앱 구축</h3>
<p class="project__company">신한은행</p>
<div class="project__stack">
<span class="project__tag">vue</span>
@ -356,10 +335,7 @@
<img class="project__thumbImg" src="images/project-2.jpg" alt="SK그룹 공식앱 내부 모바일" />
</div>
<div class="project__info">
<div class="project__meta">
<h3 class="project__name">SK그룹 공식앱 내부 모바일</h3>
<span class="project__date">2023.12</span>
</div>
<h3 class="project__name">SK그룹 공식앱 내부 모바일</h3>
<p class="project__company">SK그룹</p>
<div class="project__stack">
<span class="project__tag">vue</span>
@ -373,10 +349,7 @@
<img class="project__thumbImg" src="images/project-3.jpg" alt="PNS네트웍스 디지털 플랫폼 구축" />
</div>
<div class="project__info">
<div class="project__meta">
<h3 class="project__name">PNS네트웍스 디지털 플랫폼 구축</h3>
<span class="project__date">2023.04</span>
</div>
<h3 class="project__name">PNS네트웍스 디지털 플랫폼 구축</h3>
<p class="project__company">PNS 네트웍스</p>
<div class="project__stack">
<span class="project__tag">react</span>
@ -390,10 +363,7 @@
<img class="project__thumbImg" src="images/project-4.jpg" alt="롯데렌터카 차세대" />
</div>
<div class="project__info">
<div class="project__meta">
<h3 class="project__name">롯데렌터카 차세대</h3>
<span class="project__date">2022.05</span>
</div>
<h3 class="project__name">롯데렌터카 차세대</h3>
<p class="project__company">롯데</p>
<div class="project__stack">
<span class="project__tag">vue</span>
@ -406,10 +376,7 @@
<img class="project__thumbImg" src="images/project-5.jpg" alt="오뚜기 쇼핑몰 구축" />
</div>
<div class="project__info">
<div class="project__meta">
<h3 class="project__name">오뚜기 쇼핑몰 구축</h3>
<span class="project__date">2022.07</span>
</div>
<h3 class="project__name">오뚜기 쇼핑몰 구축</h3>
<p class="project__company">오뚜기</p>
<div class="project__stack">
<span class="project__tag">vue</span>
@ -424,10 +391,7 @@
<img class="project__thumbImg" src="images/project-6.jpg" alt="캐나다구스 구축" />
</div>
<div class="project__info">
<div class="project__meta">
<h3 class="project__name">캐나다구스 구축</h3>
<span class="project__date">2022.05</span>
</div>
<h3 class="project__name">캐나다구스 구축</h3>
<p class="project__company">캐나다구스 코리아</p>
<div class="project__stack">
<span class="project__tag">html5</span>
@ -441,10 +405,7 @@
<img class="project__thumbImg" src="images/project-7.jpg" alt="한옥홈페이지 서버 이관" />
</div>
<div class="project__info">
<div class="project__meta">
<h3 class="project__name">한옥홈페이지 서버 이관</h3>
<span class="project__date">2022.11</span>
</div>
<h3 class="project__name">한옥홈페이지 서버 이관</h3>
<p class="project__company">더한옥</p>
<div class="project__stack">
<span class="project__tag">vue</span>
@ -460,10 +421,7 @@
<img class="project__thumbImg" src="images/project-8.jpg" alt="그린카 차세대" />
</div>
<div class="project__info">
<div class="project__meta">
<h3 class="project__name">그린카 차세대</h3>
<span class="project__date">2022.11</span>
</div>
<h3 class="project__name">그린카 차세대</h3>
<p class="project__company">그린카</p>
<div class="project__stack">
<span class="project__tag">html5</span>
@ -477,10 +435,7 @@
<article class="project__card">
<div class="project__thumb project__thumbEmpty"></div>
<div class="project__info">
<div class="project__meta">
<h3 class="project__name">프로스펙스 구축</h3>
<span class="project__date">2021.01</span>
</div>
<h3 class="project__name">프로스펙스 구축</h3>
<p class="project__company">(주)LS네트웍스</p>
<div class="project__stack">
<span class="project__tag">react</span>
@ -492,10 +447,7 @@
<article class="project__card">
<div class="project__thumb project__thumbEmpty"></div>
<div class="project__info">
<div class="project__meta">
<h3 class="project__name">중소기업창업</h3>
<span class="project__date">2021.11</span>
</div>
<h3 class="project__name">중소기업창업</h3>
<p class="project__company">중소벤처기업부</p>
<div class="project__stack">
<span class="project__tag">html5</span>
@ -507,11 +459,8 @@
<article class="project__card">
<div class="project__thumb project__thumbEmpty"></div>
<div class="project__info">
<div class="project__meta">
<h3 class="project__name">한화 GAsk 구축 프로젝트</h3>
<span class="project__date">2021.11</span>
</div>
<p class="project__company">한화</p>
<h3 class="project__name">롯데 GA2ck 구축 프로젝트 (롯데 렌터카)</h3>
<p class="project__company">롯데</p>
<div class="project__stack">
<span class="project__tag">html5</span>
<span class="project__tag">css3</span>
@ -523,14 +472,11 @@
<article class="project__card">
<div class="project__thumb project__thumbEmpty"></div>
<div class="project__info">
<div class="project__meta">
<h3 class="project__name">
<h3 class="project__name">
(주)국민은행_KB국민은행
<br />
리브 Reboot One 구축, 프론트개발
</h3>
<span class="project__date">2021.10</span>
</div>
<p class="project__company">국민은행</p>
<div class="project__stack">
<span class="project__tag">vue</span>
@ -543,10 +489,7 @@
<article class="project__card">
<div class="project__thumb project__thumbEmpty"></div>
<div class="project__info">
<div class="project__meta">
<h3 class="project__name">코나아이 PC</h3>
<span class="project__date">2021.01</span>
</div>
<h3 class="project__name">코나아이 PC</h3>
<p class="project__company">코나아이</p>
<div class="project__stack">
<span class="project__tag">html5</span>
@ -561,104 +504,58 @@
</div>
</section>
<!-- 07. EXPERTISE -->
<section id="expertise" class="expertise">
<div class="expertise__inner">
<h2 class="sectionTitle">EXPERTISE</h2>
<p class="expertise__desc">
<!-- 07. CONTACT / FOOTER -->
<section id="contact" class="contact">
<div class="contact__inner">
<h2 class="contact__heading">WELCOME BODA LAB</h2>
<p class="contact__desc">
The BODA LAB은 서비스와 사용자를 고려하여 다양한 경험을 제공하며,
<br />
거쳐간 모든 곳에서 지속적인 성장이 이루어질 수 있도록 함께합니다.
</p>
<ul class="expertise__list">
<li class="expertise__item">
<span class="expertise__num">01</span>
<h3 class="expertise__name">UX Consulting</h3>
<p class="expertise__text">UX 컨설팅</p>
</li>
<li class="expertise__item">
<span class="expertise__num">02</span>
<h3 class="expertise__name">Plarform Building</h3>
<p class="expertise__text">플랫폼 구축</p>
</li>
<li class="expertise__item">
<span class="expertise__num">03</span>
<h3 class="expertise__name">Mobile App &amp; Web</h3>
<p class="expertise__text">&amp; 웹 개발</p>
</li>
<li class="expertise__item">
<span class="expertise__num">04</span>
<h3 class="expertise__name">Service Management</h3>
<p class="expertise__text">서비스 운영</p>
</li>
</ul>
<address class="contact__office">
<p class="contact__label">Head Office</p>
<dl class="contact__infoList">
<div class="contact__infoItem">
<dt class="contact__infoLabel">Address</dt>
<dd class="contact__infoValue">서울시 강서구 마곡중앙로 161-8, 두산더랜드파크 C동 618호</dd>
</div>
<div class="contact__infoItem">
<dt class="contact__infoLabel">e-mail</dt>
<dd class="contact__infoValue">
<a class="contact__infoLink" href="mailto:koji@bodalab.co.kr">koji@bodalab.co.kr</a>
</dd>
</div>
<div class="contact__infoItem">
<dt class="contact__infoLabel">tel</dt>
<dd class="contact__infoValue">010-4169-4728</dd>
</div>
</dl>
</address>
</div>
</section>
<!-- 08. CONTACT / FOOTER -->
<section id="contact" class="contact">
<div class="contact__inner">
<div class="contact__left">
<h2 class="contact__greeting">
Welcome!
<br />
<span class="contact__greetingBrand">BODA LAB</span>
</h2>
<address class="contact__address">
<p class="contact__label">Head Office</p>
<dl class="contact__infoList">
<div class="contact__infoItem">
<dt class="contact__infoLabel">Address</dt>
<dd class="contact__infoValue">
서울특별시 금천구 가산디지털2로 169-16,
<br />
907호 (가산하우스디퍼스타)
</dd>
</div>
<div class="contact__infoItem">
<dt class="contact__infoLabel">e-mail</dt>
<dd class="contact__infoValue">
<a class="contact__infoLink" href="mailto:bodalab@bodalab.com">bodalab@bodalab.com</a>
</dd>
</div>
<div class="contact__infoItem">
<dt class="contact__infoLabel">tel</dt>
<dd class="contact__infoValue">010-1234-5678</dd>
</div>
<div class="contact__infoItem">
<dt class="contact__infoLabel">fax</dt>
<dd class="contact__infoValue">010-1234-5678</dd>
</div>
</dl>
</address>
</div>
<div class="contact__right">
<div class="contact__map"></div>
</div>
</div>
<!-- 프로젝트 문의 -->
<!-- Contact Us -->
<div class="contactAccordion">
<div class="contactAccordion__item isOpen" id="acc-project">
<button class="contactAccordion__header" aria-expanded="true" aria-controls="acc-project-body">
<span>프로젝트 문의</span>
<span>Contact Us</span>
<img class="contactAccordion__icon" src="images/icon-chevron.svg" alt="" />
</button>
<div class="contactAccordion__body" id="acc-project-body">
<form class="contactForm" onsubmit="return false;">
<div class="contactForm__row">
<input type="text" class="contactForm__input" placeholder="회사명" />
<input type="text" class="contactForm__input" placeholder="담당자 이름" />
<div class="contactForm__cols">
<div class="contactForm__fields">
<input type="text" class="contactForm__input" placeholder="회사명*" />
<input type="text" class="contactForm__input" placeholder="담당자 이름*" />
<input type="tel" class="contactForm__input" placeholder="연락처*" />
<input type="email" class="contactForm__input" placeholder="이메일*" />
</div>
<textarea class="contactForm__textarea" placeholder="문의내용"></textarea>
</div>
<div class="contactForm__row">
<input type="tel" class="contactForm__input" placeholder="연락처" />
<input type="email" class="contactForm__input" placeholder="이메일" />
</div>
<textarea class="contactForm__textarea" placeholder="문의내용"></textarea>
<div class="contactForm__agree">
<label class="contactForm__checkbox">
<input class="contactForm__checkboxInput" type="checkbox" />
<span class="contactForm__checkboxBox"></span>
<span>개인정보보호정책에 동의합니다.</span>
<span>[필수] 개인정보 수집 및 이용 동의</span>
</label>
</div>
<div class="contactForm__submit">
@ -668,10 +565,10 @@
</div>
</div>
<!-- 채용 -->
<!-- Recruitment -->
<div class="contactAccordion__item" id="acc-career">
<button class="contactAccordion__header" aria-expanded="false" aria-controls="acc-career-body">
<span>채용</span>
<span>Recruitment</span>
<img class="contactAccordion__icon" src="images/icon-chevron.svg" alt="" />
</button>
<div class="contactAccordion__body" id="acc-career-body" hidden>

View File

@ -1,61 +1,11 @@
import { gsap } from "gsap";
const BLOB_ENTER = 2;
const blobFront = { scale: 1.5, opacity: 0.65, filter: "blur(20px)", duration: 8, ease: "sine.inOut" };
const blobBack = { scale: 0.6, opacity: 0.25, filter: "blur(52px)", duration: 8, ease: "sine.inOut" };
function randomBlob(selector, frontOverrides, delay) {
const rand = (min, max) => gsap.utils.random(min, max);
const isMo = () => window.innerWidth <= 768;
function cycle() {
const xRange = isMo() ? 60 : 180;
const yRange = isMo() ? 140 : 100;
const x = rand(-xRange, xRange);
const y = rand(-yRange, yRange);
gsap.timeline()
.to(selector, { ...blobFront, ...frontOverrides, x, y })
.to(selector, { duration: 20 })
.to(selector, { ...blobBack, x: 0, y: 0 })
.call(cycle);
}
gsap.delayedCall(delay, cycle);
}
function morphBlob(selector, targetRadius, duration) {
gsap.to(selector, {
borderRadius: targetRadius,
duration,
repeat: -1,
yoyo: true,
ease: "sine.inOut",
});
}
export function initIntroAnimation() {
gsap.set([".blobCyan", ".blobPurple", ".blobBlue"], {
opacity: 0,
scale: 0.4,
filter: "blur(60px)",
});
gsap.to(".blobCyan", { opacity: 0.25, scale: 0.6, filter: "blur(50px)", duration: 1.6, ease: "power2.out" });
gsap.to(".blobPurple", { opacity: 0.2, scale: 0.6, filter: "blur(55px)", duration: 1.6, ease: "power2.out", delay: 0.35 });
gsap.to(".blobBlue", { opacity: 0.2, scale: 0.6, filter: "blur(55px)", duration: 1.6, ease: "power2.out", delay: 0.7 });
// gsap.set(".intro__bg", { opacity: 0 });
// gsap.to(".intro__bg", { opacity: 0.2, duration: 2, ease: "power1.out" });
// 텍스트 순차 등장
gsap.set([".intro__sub", ".intro__title"], { opacity: 0, y: 30 });
gsap.to(".intro__sub", { opacity: 1, y: 0, duration: 0.9, ease: "power3.out", delay: 1.0 });
gsap.to(".intro__sub", { opacity: 1, y: 0, duration: 0.9, ease: "power3.out", delay: 1.0 });
gsap.to(".intro__title", { opacity: 1, y: 0, duration: 0.9, ease: "power3.out", delay: 1.3 });
randomBlob(".blobCyan", { opacity: 0.65, filter: "blur(20px)" }, BLOB_ENTER);
randomBlob(".blobPurple", { opacity: 0.55, filter: "blur(22px)" }, BLOB_ENTER + 6);
randomBlob(".blobBlue", { opacity: 0.55, filter: "blur(22px)" }, BLOB_ENTER + 12);
morphBlob(".blobCyan", "60% 40% 55% 45% / 45% 60% 40% 55%", 1.8);
morphBlob(".blobPurple", "45% 55% 40% 60% / 60% 40% 55% 45%", 2.4);
morphBlob(".blobBlue", "55% 45% 60% 40% / 40% 60% 45% 55%", 2.1);
}

View File

@ -5,22 +5,20 @@ import { initIntroAnimation } from "./introAnimation.js";
gsap.registerPlugin(ScrollTrigger);
initIntroAnimation();
$(function () {
initIntroAnimation();
const $gnb = $("#gnb");
const $hamburger = $(".gnb__hamburger");
const $mobileNav = $(".gnb__mobileNav");
const $mobileNavClose = $(".gnb__mobileNavClose");
// 섹션 → nav 귀속 맵
const sectionToNav = {
intro: "intro",
about: "about",
history: "about",
"boda-intro": "about",
vision: "about",
history: "history",
vision: "vision",
project: "project",
expertise: "project",
contact: "contact",
};
@ -77,6 +75,28 @@ $(function () {
$mobileNav.removeClass("isOpen");
});
// 모바일 메뉴 닫기 버튼
$mobileNavClose.on("click", function () {
$hamburger.removeClass("isOpen").attr("aria-expanded", false);
$mobileNav.removeClass("isOpen");
});
// History 아코디언
$(".history__yearToggle").on("click", function () {
const $group = $(this).closest(".history__yearGroup");
const $list = $("#" + $(this).attr("aria-controls"));
const isOpen = $group.hasClass("isOpen");
$group.toggleClass("isOpen", !isOpen);
$(this).attr("aria-expanded", !isOpen);
if (isOpen) {
$list.attr("hidden", "");
} else {
$list.removeAttr("hidden");
}
});
// Contact 아코디언
$(".contactAccordion__header").on("click", function () {
const $item = $(this).closest(".contactAccordion__item");

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 545 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 546 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 868 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 674 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 439 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 356 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 459 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 359 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 698 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 764 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 922 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 622 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 555 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 620 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 727 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 791 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 749 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 489 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 672 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 331 KiB

View File

@ -3,6 +3,7 @@ $color-bg-light: #e5e5e5;
$color-cyan: #00f0ff;
$color-purple: #8f00ff;
$color-blue: #7796ff;
$color-badge-blue: #0071f2;
$color-white: #ffffff;
$color-dark: #0d0d0d;
$color-gray: #999;
@ -10,7 +11,7 @@ $color-gray: #999;
$기본글꼴: "SUIT Variable", "SUIT", sans-serif;
$font-serif: "DM Serif Display", serif;
$gnb-height: 80px;
$gnb-height: 60px;
$gnb-height-mo: 60px;
$bp-mo: 768px;

View File

@ -9,7 +9,8 @@
@use "page/gnb";
@use "page/intro";
@use "page/about";
@use "page/projects";
@use "page/vision";
@use "page/project";
@use "page/contact";
.sectionTitle {
@ -27,7 +28,7 @@
.scrollDown {
position: absolute;
bottom: 40px;
bottom: 80px;
left: 50%;
transform: translateX(-50%);
width: 72px;

View File

@ -1,360 +1,301 @@
@use "../base/variable" as *;
@use "../base/mixin" as *;
// About
// About + Expertise
.about {
height: 956px;
position: relative;
min-height: 100vh;
background: $color-bg;
align-items: stretch;
display: flex;
flex-direction: column;
justify-content: center;
padding: clamp(80px, 6.25vw, 120px) clamp(24px, 6.25vw, 120px);
overflow: hidden;
}
.about__bg {
position: absolute;
inset: 0;
background: url("../../images/unsplash_Cq5NaI0yKBE.png") center / cover no-repeat;
// opacity: 0.2;
pointer-events: none;
}
.about__inner {
position: relative;
height: 100%;
z-index: 1;
display: flex;
flex-direction: column;
gap: clamp(60px, 10.4vw, 200px);
}
.about__text {
padding: 120px 16.7% 60px;
.about__head {
display: flex;
flex-direction: column;
gap: clamp(30px, 3.1vw, 60px);
.sectionTitle {
margin: 0 0 70px;
}
.desc {
padding: 0 0 0 80px;
font-size: clamp(13px, 1.1vw, 16px);
font-weight: 300;
line-height: 1.8;
color: $color-white;
opacity: 0.9;
margin: 0;
}
}
.about__image {
position: absolute;
top: 229px;
right: 0;
width: 42%;
}
.about__imageThumb {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
}
.about__caption {
position: absolute;
bottom: 120px;
left: 0;
right: 0;
padding: 0;
background: linear-gradient(to top, rgba($color-bg, 0.7) 0%, transparent 100%);
overflow: hidden;
}
.about__captionTrack {
display: flex;
width: max-content;
animation: marquee 18s linear infinite;
}
.about__captionText {
font-size: clamp(18px, 2.5vw, 36px);
font-weight: 400;
.about__desc {
font-size: clamp(13px, 1.1vw, 16px);
font-weight: 300;
line-height: 1.8;
color: $color-white;
white-space: nowrap;
padding-right: 80px;
opacity: 0.9;
}
@keyframes marquee {
from {
transform: translateX(0);
.about__quote {
display: flex;
align-items: flex-end;
gap: 10px;
}
.about__quoteMark {
font-size: clamp(60px, 7.6vw, 146px);
font-weight: 600;
line-height: 1;
color: $color-white;
}
.about__quoteText {
font-size: clamp(22px, 2.4vw, 46px);
font-weight: 100;
line-height: 1.2;
color: $color-white;
}
.about__expertiseList {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: clamp(24px, 3vw, 60px);
list-style: none;
}
.about__expertiseItem {
display: flex;
flex-direction: column;
gap: 8px;
.num {
font-size: clamp(14px, 0.85vw, 16px);
font-weight: 800;
color: $color-blue;
}
to {
transform: translateX(-25%);
.name {
font-size: clamp(24px, 2.1vw, 40px);
font-weight: 800;
text-transform: uppercase;
line-height: 1.2;
color: $color-white;
}
.text {
font-size: clamp(12px, 0.75vw, 14px);
font-weight: 300;
color: $color-white;
}
}
// History
.history {
background: $color-bg-light;
padding: 0 0 0;
padding: clamp(60px, 6.25vw, 120px) clamp(24px, 6.25vw, 120px);
}
.history__top {
max-width: 1280px;
padding: 120px 40px 120px;
margin: 0 auto;
.history__inner {
position: relative;
display: flex;
align-items: flex-start;
gap: clamp(40px, 6.25vw, 120px);
}
.history__top .sectionTitleDark {
margin-bottom: 88px;
.history__photo {
position: relative;
flex: 0 0 clamp(220px, 26vw, 500px);
align-self: stretch;
overflow: hidden;
background: $color-dark;
.img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.history__title {
position: absolute;
top: clamp(16px, 2vw, 32px);
left: clamp(16px, 2vw, 32px);
z-index: 1;
color: $color-white;
}
.history__timeline {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 60px 24px;
flex: 1;
min-width: 0;
}
.history__yearGroup {
border-top: 1px solid rgba($color-dark, 0.15);
&:last-child {
border-bottom: 1px solid rgba($color-dark, 0.15);
}
}
.history__yearToggle {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
width: 100%;
padding: clamp(16px, 1.8vw, 24px) 0;
background: none;
border: none;
cursor: pointer;
.icon {
position: relative;
width: 28px;
height: 28px;
border: 1px solid $color-dark;
border-radius: 50%;
flex-shrink: 0;
&::before,
&::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 10px;
height: 1px;
background: $color-dark;
transform: translate(-50%, -50%);
}
&::after {
transform: translate(-50%, -50%) rotate(90deg);
transition: opacity 0.2s;
}
}
}
.history__yearGroup.isOpen .history__yearToggle .icon::after {
opacity: 0;
}
.history__year {
font-size: clamp(24px, 2.5vw, 32px);
font-size: clamp(28px, 2.5vw, 40px);
font-weight: 100;
color: $color-dark;
margin-bottom: 32px;
line-height: 1;
}
.history__list {
display: flex;
flex-direction: column;
gap: 12px;
border-left: 1px solid #0d0d0d;
padding: 0 0 0 23px;
}
.history__listItem {
display: flex;
flex-direction: column;
gap: 4px;
}
align-items: flex-start;
justify-content: space-between;
gap: 24px;
padding: clamp(12px, 1.2vw, 16px) 0;
border-top: 1px solid rgba($color-dark, 0.08);
.history__listDate {
font-size: 14px;
font-weight: 700;
color: $color-dark;
line-height: 1.6;
}
.history__listText {
font-size: clamp(12px, 1vw, 16px);
font-weight: 300;
color: $color-dark;
line-height: 1.6;
}
.history__bottom {
position: relative;
background: $color-bg;
height: 480px;
}
.history__img {
position: absolute;
object-fit: cover;
&.history__img--1 {
width: 16.67%;
top: 0px;
left: 0;
&:first-child {
border-top: none;
}
&.history__img--2 {
width: 27.1%;
left: 50%;
transform: translateX(-50%);
top: -60px;
.main {
display: flex;
flex-direction: column;
gap: 4px;
}
&.history__img--3 {
width: 18.23%;
top: 0px;
left: 0;
.title {
font-size: clamp(14px, 1vw, 16px);
font-weight: 400;
color: $color-dark;
}
}
// Boda Intro
.bodaIntro {
position: relative;
padding: 120px 0 210px;
background: $color-bg;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
.scrollDown {
position: absolute;
left: 50%;
bottom: 0;
transform: translateX(-50%);
.badge {
display: inline-block;
margin-left: 6px;
padding: 2px 8px;
font-size: 10px;
font-weight: 700;
color: $color-badge-blue;
border: 1px solid $color-badge-blue;
border-radius: 4px;
vertical-align: middle;
}
}
.bodaIntro__content {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
.sub {
font-size: clamp(11px, 0.8vw, 13px);
font-weight: 300;
color: rgba($color-dark, 0.55);
line-height: 1.6;
}
font-size: clamp(20px, 3vw, 56px);
line-height: 1.5;
font-weight: 600;
}
.bodaIntro__desc {
color: rgba($color-white, 0.3);
}
// Vision
.vision {
background: $color-bg;
}
.vision__inner {
display: flex;
flex-direction: column;
}
.vision__item {
display: flex;
align-items: stretch;
height: 33.333vh;
min-height: 280px;
}
.vision__itemReverse {
flex-direction: row-reverse;
}
.vision__text {
display: flex;
flex-direction: column;
justify-content: center;
width: 50%;
padding: 40px 80px;
gap: 20px;
}
.vision__keyword {
font-family: $font-serif;
font-style: italic;
font-size: clamp(32px, 4vw, 56px);
color: $color-white;
line-height: 1;
}
.vision__textDesc {
font-size: clamp(13px, 1vw, 15px);
font-weight: 300;
line-height: 1.8;
color: rgba($color-white, 0.75);
}
.vision__image {
width: 50%;
overflow: hidden;
}
.vision__imageThumb {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.6s ease;
}
.vision__image:hover .vision__imageThumb {
transform: scale(1.04);
.date {
flex-shrink: 0;
font-size: clamp(12px, 0.85vw, 14px);
font-weight: 400;
color: rgba($color-dark, 0.65);
white-space: nowrap;
}
}
@include mo {
.about {
height: auto;
min-height: 100vh;
min-height: auto;
padding: calc(#{$gnb-height-mo} + 40px) 24px 60px;
}
.about__quote {
flex-direction: column;
align-items: flex-start;
gap: 4px;
}
.about__inner {
.about__expertiseList {
flex-direction: column;
}
.about__text {
width: 100%;
padding: calc(#{$gnb-height-mo} + 40px) 24px 40px;
gap: 40px;
}
.about__image {
width: 100%;
height: 56vw;
min-height: 260px;
}
.about__caption {
font-size: 16px;
padding: 16px;
gap: 32px;
}
.breakLine {
display: none;
}
.history__top {
padding: 60px 24px 40px;
.history {
padding: 60px 24px;
}
.history__top .sectionTitleDark {
.history__inner {
flex-direction: column;
}
.history__title {
position: static;
margin-bottom: 32px;
color: $color-dark;
}
.history__timeline {
grid-template-columns: 1fr 1fr;
gap: 40px 20px;
.history__photo {
display: none;
}
.history__bottom {
padding: 0 24px 60px;
}
.history__images {
height: 260px;
margin-top: -40px;
}
.history__img1 {
width: 120px;
height: 80px;
}
.history__img2 {
width: 180px;
height: 200px;
left: 50%;
}
.history__img3 {
width: 130px;
height: 90px;
bottom: 20px;
}
.bodaIntro {
min-height: 100vh;
height: auto;
padding: 80px 24px;
}
.vision__item {
flex-direction: column !important;
height: auto;
min-height: unset;
}
.vision__text {
width: 100%;
padding: 32px 24px;
}
.vision__image {
width: 100%;
height: 56vw;
min-height: 220px;
.history__listItem {
flex-direction: column;
gap: 6px;
}
}

View File

@ -1,109 +1,37 @@
@use "../base/variable" as *;
@use "../base/mixin" as *;
// Expertise
.expertise {
background: $color-bg;
padding: 100px 48px;
border-top: 1px solid rgba($color-white, 0.08);
}
.expertise__inner {
max-width: 1200px;
margin: 0 auto;
}
.expertise__desc {
margin-top: 20px;
margin-bottom: 64px;
font-size: 15px;
font-weight: 300;
color: rgba($color-white, 0.6);
}
.expertise__list {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0;
border-top: 1px solid rgba($color-white, 0.12);
}
.expertise__item {
padding: 40px 32px 40px 0;
border-right: 1px solid rgba($color-white, 0.12);
&:last-child {
border-right: none;
}
}
.expertise__num {
display: block;
font-size: 12px;
font-weight: 400;
color: $color-cyan;
letter-spacing: 0.1em;
margin-bottom: 20px;
}
.expertise__name {
font-size: clamp(16px, 1.4vw, 20px);
font-weight: 400;
color: $color-white;
margin-bottom: 16px;
line-height: 1.3;
}
.expertise__text {
font-size: 13px;
font-weight: 300;
line-height: 1.7;
color: rgba($color-white, 0.55);
}
// Contact
// 섹션만 Figma 디자인이 라이트 테마( 배경/검은 텍스트) 다른 섹션과 색상 반전
.contact {
background: $color-bg;
background: $color-white;
display: flex;
flex-direction: column;
border-top: 1px solid rgba($color-white, 0.08);
border-top: 1px solid rgba($color-dark, 0.08);
}
.contact__inner {
display: flex;
align-items: stretch;
flex: 1;
min-height: 60vh;
max-width: 1200px;
margin: 0 auto;
width: 100%;
padding: 100px 48px 64px;
}
.contact__left {
display: flex;
flex-direction: column;
justify-content: center;
gap: 40px;
width: 50%;
padding: 80px 80px 80px 48px;
}
.contact__greeting {
font-family: $font-serif;
font-style: italic;
font-size: clamp(36px, 5vw, 72px);
font-weight: 400;
line-height: 1.1;
color: $color-white;
}
.contact__greetingBrand {
display: block;
font-size: clamp(16px, 1.5vw, 22px);
.contact__heading {
font-family: $기본글꼴;
font-style: normal;
font-weight: 900;
letter-spacing: 0.15em;
text-transform: uppercase;
margin-top: 8px;
color: $color-cyan;
font-size: clamp(28px, 3vw, 40px);
font-weight: 600;
letter-spacing: 0.02em;
color: $color-dark;
line-height: 1;
}
.contact__desc {
margin-top: 20px;
margin-bottom: 48px;
font-size: 15px;
font-weight: 300;
color: rgba($color-dark, 0.6);
}
.contact__label {
@ -111,34 +39,34 @@
font-weight: 600;
letter-spacing: 0.1em;
text-transform: uppercase;
color: rgba($color-white, 0.5);
margin-bottom: 16px;
color: rgba($color-dark, 0.5);
margin-bottom: 20px;
}
.contact__infoList {
display: flex;
flex-direction: column;
gap: 16px;
flex-wrap: wrap;
gap: 48px;
}
.contact__infoItem {
display: flex;
flex-direction: column;
gap: 4px;
gap: 6px;
}
.contact__infoLabel {
font-size: 12px;
font-weight: 600;
letter-spacing: 0.08em;
color: $color-cyan;
color: $color-blue;
}
.contact__infoValue {
font-size: 14px;
font-weight: 300;
line-height: 1.7;
color: rgba($color-white, 0.85);
color: rgba($color-dark, 0.85);
}
.contact__infoLink {
@ -150,30 +78,13 @@
}
}
.contact__right {
width: 50%;
display: flex;
flex-direction: column;
justify-content: center;
padding: 80px 48px 80px 0;
gap: 24px;
}
.contact__map {
width: 100%;
aspect-ratio: 4 / 3;
background: #1a1a1a url("../../images/map.svg") center / cover no-repeat;
border: 1px solid rgba($color-white, 0.1);
overflow: hidden;
}
// Contact accordion
.contactAccordion {
border-top: 1px solid rgba($color-white, 0.08);
border-top: 1px solid rgba($color-dark, 0.08);
}
.contactAccordion__item {
border-bottom: 1px solid rgba($color-white, 0.08);
border-bottom: 1px solid rgba($color-dark, 0.08);
}
.contactAccordion__header {
@ -185,7 +96,7 @@
background: none;
border: none;
cursor: pointer;
color: $color-white;
color: $color-dark;
font-size: clamp(16px, 1.4vw, 20px);
font-weight: 400;
font-family: $기본글꼴;
@ -203,6 +114,7 @@
flex-shrink: 0;
transition: transform 0.3s ease;
object-fit: unset;
filter: invert(1);
}
.contactAccordion__item.isOpen .contactAccordion__icon {
@ -232,18 +144,24 @@
gap: 12px;
}
.contactForm__row {
.contactForm__cols {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
}
.contactForm__fields {
display: flex;
flex-direction: column;
gap: 12px;
}
.contactForm__input,
.contactForm__textarea {
width: 100%;
background: rgba($color-white, 0.04);
border: 1px solid rgba($color-white, 0.1);
color: $color-white;
background: $color-white;
border: 1px solid rgba($color-dark, 0.2);
color: $color-dark;
font-family: $기본글꼴;
font-size: 14px;
font-weight: 300;
@ -252,16 +170,17 @@
transition: border-color 0.2s;
&::placeholder {
color: rgba($color-white, 0.35);
color: rgba($color-dark, 0.35);
}
&:focus {
border-color: rgba($color-white, 0.3);
border-color: rgba($color-dark, 0.4);
}
}
.contactForm__textarea {
resize: none;
height: 180px;
min-height: 180px;
height: 100%;
}
.contactForm__agree {
@ -275,7 +194,7 @@
cursor: pointer;
font-size: 13px;
font-weight: 300;
color: rgba($color-white, 0.6);
color: rgba($color-dark, 0.6);
}
.contactForm__checkboxInput {
@ -283,8 +202,8 @@
}
.contactForm__checkboxInput:checked + .contactForm__checkboxBox {
background: $color-cyan;
border-color: $color-cyan;
background: $color-blue;
border-color: $color-blue;
}
.contactForm__checkboxInput:checked + .contactForm__checkboxBox::after {
@ -292,15 +211,15 @@
display: block;
width: 10px;
height: 6px;
border-left: 1.5px solid $color-dark;
border-bottom: 1.5px solid $color-dark;
border-left: 1.5px solid $color-white;
border-bottom: 1.5px solid $color-white;
transform: rotate(-45deg) translateY(-2px);
}
.contactForm__checkboxBox {
width: 18px;
height: 18px;
border: 1px solid rgba($color-white, 0.3);
border: 1px solid rgba($color-dark, 0.3);
flex-shrink: 0;
display: flex;
align-items: center;
@ -318,10 +237,10 @@
.btnSend {
padding: 12px 48px;
background: $color-cyan;
background: $color-blue;
border: none;
border-radius: 100px;
color: $color-dark;
color: $color-white;
font-family: $기본글꼴;
font-size: 14px;
font-weight: 700;
@ -347,18 +266,18 @@
align-items: center;
gap: 8px;
padding: 10px 20px;
border: 1px solid rgba($color-white, 0.25);
border: 1px solid rgba($color-dark, 0.25);
border-radius: 100px;
font-size: 14px;
font-weight: 300;
color: $color-white;
color: $color-dark;
transition:
border-color 0.2s,
color 0.2s;
&:hover {
border-color: $color-cyan;
color: $color-cyan;
border-color: $color-blue;
color: $color-blue;
}
}
@ -370,7 +289,7 @@
// Footer
.footer {
border-top: 1px solid rgba($color-white, 0.08);
border-top: 1px solid rgba($color-dark, 0.08);
padding: 32px 48px;
}
@ -386,7 +305,7 @@
font-size: clamp(18px, 2vw, 28px);
font-weight: 700;
letter-spacing: 0.08em;
color: rgba($color-white, 0.4);
color: rgba($color-dark, 0.4);
line-height: 1.2;
text-transform: uppercase;
}
@ -394,71 +313,38 @@
.footer__contact {
font-size: 13px;
font-weight: 300;
color: rgba($color-white, 0.5);
color: rgba($color-dark, 0.5);
}
.footer__contactLink {
color: rgba($color-white, 0.5);
color: rgba($color-dark, 0.5);
transition: color 0.2s;
&:hover {
color: $color-white;
color: $color-dark;
}
}
.footer__copy {
font-size: 12px;
font-weight: 300;
color: rgba($color-white, 0.3);
color: rgba($color-dark, 0.3);
letter-spacing: 0.03em;
}
@include mo {
.expertise {
padding: 60px 24px;
.contact__inner {
padding: 60px 24px 40px;
}
.expertise__desc {
margin-bottom: 40px;
.contact__desc {
margin-bottom: 32px;
font-size: 14px;
}
.expertise__list {
grid-template-columns: 1fr 1fr;
}
.expertise__item {
padding: 28px 20px 28px 0;
&:last-child {
border-right: 1px solid rgba($color-white, 0.12);
}
&:nth-child(2),
&:nth-child(4) {
border-right: none;
}
&:nth-child(3),
&:nth-child(4) {
border-top: 1px solid rgba($color-white, 0.12);
}
}
.contact__inner {
.contact__infoList {
flex-direction: column;
min-height: unset;
}
.contact__left {
width: 100%;
padding: 60px 24px 40px;
gap: 32px;
}
.contact__right {
width: 100%;
padding: 0 24px 60px;
gap: 24px;
}
.contactAccordion__header {
@ -469,10 +355,14 @@
padding: 8px 24px 40px;
}
.contactForm__row {
.contactForm__cols {
grid-template-columns: 1fr;
}
.contactForm__textarea {
height: auto;
}
.careerTags {
padding: 8px 24px 40px;
}

View File

@ -7,13 +7,12 @@
top: 0;
left: 0;
width: 100%;
height: $gnb-height;
z-index: 100;
transition: background 0.4s;
&.isScrolled {
background: rgba($color-bg, 0.92);
backdrop-filter: blur(12px);
// background: rgba($color-bg, 0.92);
// backdrop-filter: blur(12px);
}
}
@ -21,8 +20,7 @@
display: flex;
align-items: center;
justify-content: space-between;
height: 100%;
padding: 0 48px;
padding: 80px clamp(24px, 5.2vw, 100px);
}
.gnb__logo {
@ -31,7 +29,7 @@
}
.gnb__logoImg {
width: 90px;
width: 126px;
height: auto;
object-fit: unset;
}
@ -43,6 +41,7 @@
.gnb__navList {
display: flex;
align-items: center;
gap: 12px;
}
.gnb__navItem {
@ -51,20 +50,20 @@
.gnb__navLink {
display: block;
padding: 24px 32px;
font-size: 16px;
padding: 20px clamp(14px, 1.7vw, 32px);
font-size: clamp(13px, 0.85vw, 16px);
font-weight: 400;
letter-spacing: 0.05em;
color: $color-white;
transition: color 0.2s;
&:hover {
color: $color-cyan;
color: $color-blue;
}
}
.gnb__navLink.isActive {
color: $color-cyan;
color: $color-blue;
}
.gnb__hamburger {
@ -102,37 +101,67 @@
.gnb__mobileNav {
display: none;
position: absolute;
top: $gnb-height-mo;
left: 0;
width: 100%;
background: rgba($color-bg, 0.97);
backdrop-filter: blur(16px);
padding: 16px 0 24px;
transform: translateY(-100%);
position: fixed;
inset: 0;
z-index: 200;
background: $color-bg;
padding: 32px 32px 40px;
opacity: 0;
transition:
transform 0.35s ease,
opacity 0.35s ease;
pointer-events: none;
transition: opacity 0.35s ease;
&.isOpen {
transform: translateY(0);
opacity: 1;
pointer-events: auto;
}
}
.gnb__mobileNavClose {
position: absolute;
top: 28px;
right: 28px;
width: 28px;
height: 28px;
background: none;
border: none;
padding: 0;
cursor: pointer;
}
.gnb__mobileNavCloseLine {
position: absolute;
top: 50%;
left: 0;
width: 100%;
height: 1px;
background: $color-white;
&:nth-child(1) {
transform: rotate(45deg);
}
&:nth-child(2) {
transform: rotate(-45deg);
}
}
.gnb__mobileNavList {
display: flex;
flex-direction: column;
justify-content: center;
height: 100%;
gap: clamp(20px, 6vh, 36px);
}
.gnb__mobileNavLink {
display: block;
padding: 14px 24px;
font-size: 18px;
font-family: $font-serif;
font-style: italic;
font-size: clamp(28px, 8vw, 36px);
font-weight: 400;
letter-spacing: 0.05em;
letter-spacing: 0.02em;
color: $color-white;
}
.gnb__mobileNavLink.isActive {
color: $color-blue;
}

View File

@ -11,41 +11,12 @@
background: $color-bg;
}
.intro__blobs {
.intro__bg {
position: absolute;
inset: 0;
background: url("../../images/unsplash_-cKXtsJWU-I.png") center / cover no-repeat;
// opacity: 0.2;
pointer-events: none;
overflow: hidden;
.blob {
position: absolute;
border-radius: 50%;
}
.blobCyan {
width: 20vw;
height: 20vw;
background: $color-cyan;
top: 50%;
right: 20%;
transform: translateY(-50%);
}
.blobPurple {
width: 14vw;
height: 14vw;
background: $color-purple;
top: 38%;
left: 46%;
}
.blobBlue {
width: 14vw;
height: 14vw;
background: $color-blue;
top: 42%;
left: 28%;
}
}
.intro__content {
@ -55,7 +26,7 @@
}
.intro__sub {
font-size: clamp(16px, 2.5vw, 36px);
font-size: clamp(18px, 2.6vw, 50px);
font-weight: 100;
letter-spacing: 0.02em;
color: $color-white;
@ -64,11 +35,12 @@
}
.intro__title {
font-size: clamp(12px, 1.5vw, 20px);
font-size: clamp(32px, 5.2vw, 100px);
font-weight: 700;
letter-spacing: 0.03em;
letter-spacing: 0.01em;
text-transform: uppercase;
color: $color-white;
line-height: 1.2;
}
@include mo {
@ -77,6 +49,10 @@
height: $gnb-height-mo;
}
.gnb__logoImg {
width: 90px;
}
.gnb__nav {
display: none;
}
@ -88,26 +64,4 @@
.gnb__mobileNav {
display: block;
}
.blobCyan {
width: 80vw;
height: 80vw;
right: -20%;
top: -5%;
}
.blobPurple {
width: 65vw;
height: 65vw;
left: -15%;
top: 38%;
transform: translateY(-50%);
}
.blobBlue {
width: 70vw;
height: 70vw;
right: -15%;
bottom: -5%;
}
}

View File

@ -34,19 +34,19 @@
.project__thumb {
width: 100%;
aspect-ratio: 16 / 10;
overflow: hidden;
background: #1a1a1a;
}
.project__thumbImg {
width: 100%;
height: 100%;
object-fit: cover;
height: auto;
display: block;
transition: transform 0.5s ease;
}
.project__thumbEmpty {
aspect-ratio: 16 / 10;
background: #1a1a1a;
}
@ -56,13 +56,6 @@
gap: 8px;
}
.project__meta {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 8px;
}
.project__name {
font-size: clamp(14px, 1.1vw, 16px);
font-weight: 500;
@ -70,14 +63,6 @@
line-height: 1.4;
}
.project__date {
font-size: 12px;
font-weight: 300;
color: $color-gray;
white-space: nowrap;
padding-top: 2px;
}
.project__company {
font-size: 13px;
font-weight: 300;

View File

@ -0,0 +1,99 @@
@use "../base/variable" as *;
@use "../base/mixin" as *;
// Vision
.vision {
background: $color-bg;
padding: clamp(80px, 6.25vw, 120px) clamp(24px, 6.25vw, 120px);
}
.vision__inner {
display: flex;
flex-direction: column;
gap: clamp(60px, 8vw, 140px);
}
.vision__head {
display: flex;
flex-direction: column;
gap: clamp(16px, 1.5vw, 24px);
.sectionTitle {
margin: 0;
}
}
.vision__desc {
max-width: 560px;
font-size: clamp(13px, 1.1vw, 16px);
font-weight: 300;
line-height: 1.8;
color: $color-white;
opacity: 0.9;
}
.vision__quote {
display: flex;
align-items: flex-start;
gap: 12px;
align-self: flex-end;
max-width: 640px;
.mark {
font-size: clamp(40px, 4.2vw, 80px);
font-weight: 700;
line-height: 1;
color: $color-white;
}
.text {
font-size: clamp(18px, 1.9vw, 32px);
font-weight: 300;
line-height: 1.4;
color: $color-white;
}
}
.vision__keywordList {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: clamp(24px, 3vw, 60px);
list-style: none;
}
.vision__keywordItem {
display: flex;
flex-direction: column;
gap: 12px;
.keyword {
font-size: clamp(28px, 3.1vw, 60px);
font-weight: 800;
letter-spacing: 0.01em;
color: $color-white;
line-height: 1;
}
.desc {
font-size: clamp(12px, 0.8vw, 14px);
font-weight: 300;
color: rgba($color-white, 0.75);
}
}
@include mo {
.vision {
padding: 60px 24px;
}
.vision__quote {
align-self: stretch;
max-width: none;
}
.vision__keywordList {
flex-direction: column;
gap: 40px;
}
}

View File

@ -3,7 +3,7 @@ import viteImagemin from 'vite-plugin-imagemin'
export default defineConfig({
root: 'src',
base: process.env.NODE_ENV === 'production' ? '/project-bodalab/' : './',
base: './',
build: {
outDir: '../dist',
emptyOutDir: true,