diff --git a/apps/site/.htmlvalidateignore b/apps/site/.htmlvalidateignore new file mode 100644 index 0000000..e24589c --- /dev/null +++ b/apps/site/.htmlvalidateignore @@ -0,0 +1,2 @@ +# Preserve the upstream NAVER license pages verbatim; these are font provenance, not showcase routes. +public/work/*/assets/fonts/LICENSE.html diff --git a/apps/site/design.md b/apps/site/design.md index d8fd4c0..be10103 100644 --- a/apps/site/design.md +++ b/apps/site/design.md @@ -1159,6 +1159,83 @@ Pretendard `dynamic-subset` 은 유니코드 범위별로 파일을 쪼개고 - 갤러리 카드 네 장과 공유 이미지 두 장은 확정 화면을 실제 Chrome으로 다시 캡처했다. - 구현 중 발견한 21개 교훈은 `research/showcase-duo-learning-ledger-2026-08-29.md`에 근거와 함께 남겼고, 재사용 가능한 규칙은 `packages/skill/references/trustworthy-showcases.md`와 관련 게이트 문서에 반영했다. +## 전 쇼케이스 반응형·여백 재감사 (2026-08-30) + +### 연장 범위와 유지한 방향 + +이 판은 새 콘셉트로 갈아엎지 않는 **연장 경로**다. 21개 showcase의 서로 다른 프리셋과 실제/생성 이미지, 정보 구조는 유지하고, 화면이 커지거나 작아질 때 그 의도가 무너지는 지점만 고쳤다. 위의 "기존 16종에 남아 있는 것"은 이 항목으로 대체된다. + +- **본문과 정보 표면을 분리했다.** 1920·2560px에서 문장·폼은 기존 `measure`를 지키고, CFD 사양·시세·원장·관리 작업대·히어로처럼 정보 밀도가 필요한 표면만 named wide container로 넓혔다. 전역 `max-width`를 풀어 빈 여백을 만든 곳은 없다. +- **가시 내용의 경계를 고쳤다.** 버튼·검색·select·저장 동작·모바일 프리셋·지도 핀의 hitbox와 실제 텍스트에 여백을 주고, 첫/마지막 table/flex 셀의 0px padding을 제거했다. 입력 상자의 실제 겹침도 DOM rect로 검사한다. +- **읽기와 접근성을 함께 고쳤다.** 저대비 보조 토큰을 WCAG AA에 맞게 조정하고, `transition: all`을 대상 속성으로 분리했다. 갤러리의 클릭 div는 overlay button으로 바꾸고, 표 header `scope`, skip link, input label/name/autocomplete, `prefers-reduced-motion`, icon button 이름, 이미지 intrinsic size를 보완했다. +- **가상 흐름의 진실 범위를 가깝게 표시했다.** 청온·카스크·마테리아의 견적/예약/갤러리 예시는 행동 근처에서 예시·저장/전송 없음 범위를 알리고, 만들어 낸 연락처·기본 개인정보·가짜 평점은 제거했다. + +### 감사기와 기준 화면 + +`tools/showcase-audit.mjs`는 기본 폭을 `320, 390, 768, 1440, 1920, 2560`으로 확장했다. 실제 렌더에서 가로 overflow, 대비, h1, 컨트롤 줄바꿈뿐 아니라 다음을 hard fail로 잰다. + +- 버튼 라벨·field value·표/ARIA cell의 가시 좌우 inset(기본 8 CSS px) +- visible input/select/textarea의 면적 겹침 +- native/ARIA table cell의 실제 글자와 셀 테두리 사이 여백 + +CSS `color-mix()`가 Chromium에서 반환하는 CSS Color 4 `color(srgb …)`와 반투명 background 합성을 파서에 반영했다. 또 sr-only/aria-hidden 장식/빈 overlay를 `Range.selectNodeContents()`로 가시 텍스트에 섞어 여백 실패를 만들던 측정 오류를 text node 단위로 고쳤다. 테스트 도구의 false RED를 UI 수정으로 덮지 않는다. + +가온의 세 시각 기준은 44px 알림 hitbox와 캘린더·요약 표의 좌우 여백이라는 의도 변경을 실제 current/baseline 캡처로 비교한 뒤에만 갱신했다. `tools/visual.mjs --update-baseline=<이름,...>`로 대상 기준만 갱신할 수 있게 하여 다른 기준 화면을 재촬영으로 덮지 않는다. + +### 6단계 증거 + +- 전 쇼케이스 정적 실렌더: **26개 HTML × 6개 폭 = 156/156 PASS** +- 저장소 전체 `npm run verify`: L0~L6 **전 계층 PASS**. 여기에는 실렌더 156, 메인 디자인 게이트 178, 제품 게이트 15, 시각 회귀 30, WebKit 8, 최근 쇼케이스 E2E 115, TWENTYOZ E2E 148, 쇼케이스 듀오 90 scenario / 350 assertion / 12 capture가 포함된다. +- `npm run build`: 성공. 배포 텍스트 한자 검사도 **98개 파일 PASS**. +- 21개 카드의 현재 화면/보조 화면과 듀오 OG를 실제 Chromium으로 다시 캡처했다. + +### 재사용 규칙 승격 + +문헌 근거와 이번의 RED→GREEN 증거는 designpaca skill의 `references/layout.md`, `references/preflight.md`, `references/audit-gate.md`에 반영했다. 초광폭 레이아웃을 별도 상태로 다루고, WCAG의 최소 target size와 프로젝트의 시각 여백 기본값을 구분하며, 반응형 표·폼·진실 라벨·측정기 정확도를 함께 게이트로 유지한다. + +## 정적 쇼케이스 재구성 · 모달 위치 · 초광폭 이미지 계약 (2026-08-30) + +### 이번 판의 판단 + +최근의 상태형 작업물(목요일 화원, 마테리아, 한남자리, 철판클럽, RFS, 새벽청과, TWENTYOZ)은 이미 각 도메인의 정보 구조와 상호작용이 충분히 구분되어 있어 새 문법으로 덮지 않았다. 대신 그 안의 팝업 위치·짧은 화면·초광폭 수축 결함만 고쳤다. 오래된 정적 쇼케이스는 다음 10개를 실제 정보 표면과 첫 화면의 판단 근거가 보이도록 재구성했다. + +- `baekje-celadon`, `font-foundry`, `form-architecture`, `hyang-incense`: 전시·활자·도면·기록이 첫 시야에서 행동과 함께 읽히도록 재배치 +- `lumina-optics`, `orbit-aerospace`, `pulsegate`, `synapse-bci`: 빛/비행/접근/임상이라는 주장에 대응하는 실제 시험 조건·표본·한계를 판독 레지스터로 고정 +- `muwol-coffee`, `overtone-sound`: 장식적 영웅면 대신 로스터의 좌표/원장과 설치 아카이브의 조건을 정보 밀도로 구성 + +### 사용자 보고에서 고정한 계약 + +- 마테리아의 native dialog는 전역 reset이 UA `margin`을 지워 좌상단에 붙었던 결함이었다. 프로젝트 modal과 한남 듀플렉스 gallery lightbox에 `fixed + inset:0 + margin:auto`와 viewport 상한·내부 scroll owner를 명시했다. 390·1440·2560에서 중심 오차 0~0.008px, 배경 scroll lock을 자동 단언한다. +- 가온의 알림 메뉴, 한남자리 공개 메뉴와 관리자 조사관은 390×320에서 화면 밖/0px scroll 상태가 되지 않도록 viewport-bound와 short-height 구성을 분리했다. +- 철판클럽은 2560에서 hero `1680px`, copy `688px`, media `856.7px`, 다음 content rail `1400px`으로 고정했다. 사진을 화면 반까지 무한 확장하지 않으며, `stage-wide/media-wide/copy-wide/workbench-wide`를 구분한다. + +### 재발 방지와 증거 + +`tools/audit.mjs`가 마테리아 두 modal의 중심/scroll lock을 390·1440·2560에서, 한남자리 짧은 화면 scroll owner와 가온 알림 메뉴를 390×320에서, 철판클럽 hero/media/content rail을 2560에서 hard fail로 검사한다. 이 규칙은 공통 스킬의 `layout.md`, `preflight.md`, `audit-gate.md`에 승격했다. 모달의 포커스·키보드·닫기 계약은 [WAI-ARIA APG](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/)를 근거로 한다. + +### 공개 캐시 확인 + +정적 CSS의 stable URL은 HTML만 새로 배포해도 사용자 브라우저에 이전 스타일을 남길 수 있다. 이번 수정의 `main/site/tokens/franchise/landing/admin` 링크와 CSS `@import` 버전을 함께 올렸다. 공개 검증은 HTTP 200이 아니라 새 stylesheet href와 새 토큰·핵심 computed value가 실제로 로드됐는지까지 확인한다. + +### 후속 정착 프레임 캡처·초광폭 보정 (2026-08-30) + +- 모든 쇼케이스 카드·OG 캡처 경로를 `tools/capture-stable.mjs`로 통합했다. `file://` 즉시 스크린샷 대신 no-store 로컬 HTTP에서 폰트·이미지 decode·페이지별 bounded settle을 기다린 뒤, reduced-motion 환경과 video/audio·WAAPI·rAF 정지로 완성된 한 프레임을 저장한다. local 4xx, pageerror, 깨진 이미지는 결과물 생성 실패로 취급한다. +- 철판클럽의 2560px 히어로는 기존 1680px cap이 실제로 지나치게 좁아 양쪽에 맹탕을 만들었다. 히어로만 `2160px`, 카피 `900px`, 미디어 `1120px`으로 분리하고 메뉴/본문 레일은 `1400~1480px`에 남겼다. 넓은 화면은 하나의 전역 상한이 아니라, 시선의 중심이 되는 히어로와 읽기/정보 표면이 각각 다른 폭을 소유한다. +- 이미지 생성은 제공된 실제 사진을 대체하지 않는다. 브랜드가 요구하는 정확한 장면·광학적 분위기 같은 시각 자산이 실제로 비어 있고, 생성물·연출 라벨을 함께 둘 수 있을 때만 이미지 바이블의 슬롯별로 생성한다. 이번 두 결함은 각각 레이아웃과 WebGL 역할의 문제라서 생성 이미지로 덮지 않는다. + +### 사용자 보고로 보강한 과정 분할 계약 (2026-08-30) + +- 철판클럽의 `process`는 hero와 별도의 텍스트/이미지 분할 표면이다. 기존 모바일/중간 폭의 `padding-left: calc((100vw - --wrap) / 2)`가 초광폭 규칙에 남아 2560px에서 실제 제목·설명 너비를 **12px**로 만들었다. hero만 통과한 것은 이 결함의 증거가 아니다. +- 초광폭 과정 표면은 `--stage-wide` 1680px 안에서 copy **822px**, media **856px**로 제한하고 양쪽 logical padding을 함께 재설정했다. 제목은 의도한 2줄, 목록 문장은 읽는 폭으로 돌아왔으며 사진은 화면 절반까지 팽창하지 않는다. +- `tools/audit.mjs`는 hero뿐 아니라 이처럼 DOM/여백 규칙이 다른 각 text-media split의 rail, copy/media 폭, 실제 제목 폭과 줄 수를 2560px에서 hard fail로 잠근다. 재사용 스킬의 preflight·layout·audit 규칙도 같은 원리로 보강했다. + +### 사용자 코멘트로 정정한 제품 카피와 이미지 계약 (2026-08-30) + +- 가상 흐름이라도 사용자가 하려는 일이 아닌 제작 목적을 문구로 노출하지 않는다. `화면 동작용`, `쇼케이스`, `저장`처럼 구현을 설명하는 말은 `실제 주문·결제·저장을 제공하지 않습니다`처럼 행동과 한계를 함께 이해할 수 있는 말로 바꾼다. +- 조합 결과에 영속 동작이 없으면 저장 버튼이나 성공 상태를 만들지 않는다. 다음 행동은 실제로 가능한 범위 안에서 가상 매장 안내처럼 목적이 분명한 경로로 연결한다. +- CSS 조각으로 제품 자체를 흉내 내지 않는다. 철판클럽의 싱글 버거는 전용 4:3 생성 이미지(`assets/single-smash-generated.webp`, `960×720`)로 바꾸고 카드 안에 `생성 이미지` 라벨을 붙였다. 제품 사진은 제품을 고르는 근거이고, DOM 도식은 비교·설명에만 쓴다. +- 조합기처럼 반복되는 fieldset은 경계선만으로 묶지 않는다. 다음 fieldset 앞에 16px의 명시적 간격을 두고 1217px 실화면에서 legend와 이전 선택지가 붙어 보이지 않는지 확인한다. + ## 홍보 사이트 전면 재설계 — Quiet Editorial Proof Surface (2026-08-30) ### 문제와 방향 @@ -1214,3 +1291,15 @@ Pretendard `dynamic-subset` 은 유니코드 범위별로 파일을 쪼개고 - `2026-08-30` · 국소 — 히어로 아래 방향 결정·토큰 조판·검증 프레임과 7단계 진행 레일도 각각의 named CSS view timeline에 연결한다. 본문과 수치는 움직이지 않고 방향선·글립·토큰 표본·검사 화살표·짧은 진행선만 transform/opacity로 보간하며, 검증 프레임의 가장 넓은 판은 두 작은 판을 맞추는 고정 기준면으로 남긴다. 모바일 검증 완료 지점은 sticky GNB 아래 제목 여유 24px 이상에서 끝나도록 앞당기고, 미지원 브라우저·감소 모션·이펙트 제거 상태는 정적 완료 화면을 사용한다. KO/EN 전진·역스크롤 geometry 8개, 320~2560px 반응형, effects-off와 감소 모션을 80/80 시나리오·1000/1000 단언으로 고정한다. - `2026-08-30` · 국소 — 사용자 체감 실패를 반영해 방향 결정·토큰과 조판의 timeline subject를 article에서 실제 `.direction-stage`·`.type-stage`로 내리고, 방향 면·벡터·세 노드와 글립·세 토큰 표본을 각 자식의 첫 가시 시점 이후에 서로 다른 범위로 조립한다. 글자 대비는 opacity로 낮추지 않으며 미지원·감소 모션·이펙트 제거 상태는 정적 완료 화면이다. KO/EN × 390/1440에서 110px 실제 wheel 전진·역진, offscreen 진행 상한, 가시 구간 dwell, 독립 위상과 token stagger를 새 E2E 계약으로 추가했고 전체 85/85 시나리오·1094/1094 단언을 통과했다. - `2026-08-30` · 사용자 실화면 정정 — Direction의 한 줄짜리 독립 변형을 폐기하고, 정확한 세 점 좌표를 공유하는 두 SVG 선분으로 나눠 시작점을 고정한 채 스크롤로 길이만 드러낸다. 노드는 이동하지 않고 앞 선분이 좌표에 닿은 뒤 같은 중심에서 나타나며, 모바일도 `xMidYMid meet`로 비율을 보존한다. 마지막 선과 점은 `cover 80% / 86%` 안에 끝내 sticky GNB 아래에서 완성 상태를 읽을 시간을 남긴다. Tokens는 글립·기준선·세 역할 표본, Verification은 두 가변 프레임·네 검사 화살표, Process는 작은 행 장식 대신 목록 전체 높이의 연속 진행선을 각 named view timeline으로 보간한다. 실제 앱 브라우저 1316×1272에서 110px 전진·역진과 Direction endpoint 연결을 확인했고, KO/EN 320~2560px 전체 게이트는 86/86 시나리오·1122/1122 단언·8/8 캡처로 통과했다. + +### 디자인 전문성 근거와 홍보 카피 정렬 (2026-09-12) + +- Quiet Editorial Proof Surface의 밝은 Wanted Sans·신호 적색·이미지 없는 산출물 표본 세 개와 히어로의 양방향 스크롤 계약은 그대로 둔다. 고객 성과처럼 읽힐 수 있는 프로젝트 캡처를 홈에 되돌리지 않으며, 실제 사이트는 낮은 위계의 `/showcase/` 또는 `/en/showcase/` 링크로 직접 찾는다. +- 히어로는 웹 디자인 원리와 실제 사례 조사, 브랜드 맥락에 맞는 방향 결정, 반응형 구현, 실화면 검증을 한 제품 흐름으로 설명한다. 이 순서는 [NN/g의 사용성 휴리스틱](https://www.nngroup.com/articles/ten-usability-heuristics/)으로 확인하는 보편 기준과, 프로젝트 목적에 맞춰 선택하는 시각 스타일을 구분하는 근거를 드러낸다. +- 검증 근거는 수나 전환 성과로 포장하지 않는다. `7`은 0~6 파이프라인이고, 나머지 두 사실은 근거·맥락의 분리와 기능 검사/실화면 검토의 분리다. [Webby Awards 심사 기준](https://www.webbyawards.com/judging-criteria/)의 콘텐츠·구조와 내비게이션·시각 디자인·기능성·상호작용·전반 경험 구분도 화면의 인상만으로 품질을 단정하지 않는 보조 근거로 쓴다. +- 세부 검사에는 320px, 대비, 키보드, 감소 모션, 200% 확대, 실제 전후 화면의 구성·위계·반응형 동작, 출처 연결을 포함한다. 기존의 토큰·SEO 검사는 유지하되, 프로젝트에 따라 달라지는 검증 범위를 단일 하드 게이트 수로 홍보하지 않는다. +- 보존한 계약: 실제 고객 성과 주장 없음, 홈 산출물에는 이미지 없음, 히어로 그래픽과 모션은 변경하지 않음, 한국어·영어는 같은 정보 구조와 목적지 링크를 가짐. 빌드한 사이트 E2E는 86개 시나리오·1,122개 단언·8개 캡처를 통과했고, 개발 서버의 별도 증거는 KO/EN × 320·390·768·1440·1920·2560에서 overflow 0, 새 링크 12/12의 44px 이상 hit area와 키보드 목적지 2/2를 확인했다. 실제 클립보드 권한은 이 headless 환경에서 거절되어 두 언어 모두 선택 복사 안내와 전체 명령 선택으로 안전하게 전환됨을 확인했다. 새 캡처와 JSON은 `outputs/design-expertise-20260912/home/`에 보관한다. + +### 확대 텍스트 표본 보정 (2026-09-12) + +- 홈의 Direction 표본 문장은 절대 배치와 `overflow: clip` 조합에서 200% 확대 시 잘릴 수 있었다. 문장을 `position: relative`의 normal flow로 옮기고 기존 왼쪽 48%·너비를 유지했다. stage는 `display: flow-root`로 첫 자식 margin의 외부 collapse를 막는다. 기본 2:1 표본은 stage width 기준 `margin-top: 24%`, `margin-bottom: 5%`로 기존 중앙 위치를 보존하며, 긴 문장은 stage 높이를 자연스럽게 늘린다. 모바일 16:9에서는 `margin-top: 27%`, 28rem 이하에서는 기존 왼쪽 39%·너비 55%를 유지한다. diff --git a/apps/site/gate.config.json b/apps/site/gate.config.json index b19ac5c..2bec3c5 100644 --- a/apps/site/gate.config.json +++ b/apps/site/gate.config.json @@ -15,7 +15,7 @@ "report", "notice" ], - "h1": "h2.v-h", + "h1": ".view.is-on h2.v-h", "brand": ".brand" }, { @@ -30,7 +30,7 @@ "archive", "notices" ], - "h1": "h2.v-h", + "h1": ".view.is-on h2.v-h", "brand": ".brand" }, { diff --git a/apps/site/package.json b/apps/site/package.json index 49691ad..1f10bd5 100644 --- a/apps/site/package.json +++ b/apps/site/package.json @@ -11,6 +11,7 @@ "test:e2e:recent-showcases": "node tools/recent-showcases-e2e.mjs", "test:e2e:twentyoz": "node tools/twentyoz-e2e.mjs", "test:e2e:showcase-duo": "node tools/showcase-duo-e2e.mjs", + "capture:showcase": "node tools/capture-shots.mjs && node tools/capture-work-shots.mjs && node tools/capture-new-shots.mjs && node tools/capture-showcase-duo.mjs", "capture:showcase-duo": "node tools/capture-showcase-duo.mjs", "capture:site-og": "node tools/capture-site-og.mjs", "prebuild": "npm run build:showcase-assets", diff --git a/apps/site/public/work/baekje-celadon/assets/fonts/LICENSE.html b/apps/site/public/work/baekje-celadon/assets/fonts/LICENSE.html new file mode 100644 index 0000000..571387d --- /dev/null +++ b/apps/site/public/work/baekje-celadon/assets/fonts/LICENSE.html @@ -0,0 +1,169 @@ +네이버 나눔글꼴 라이선스안내 : 고객센터
빈줄

      + + + +
      +
      +
      +
      +
      +

      네이버 나눔글꼴의 지적 재산권은 네이버와 네이버 문화재단에 있습니다.

      +

      ​

      +

      네이버 나눔글꼴은 개인 및 기업 사용자를 포함한 모든 사용자에게 무료로 제공되며 글꼴 자체를 유료로 판매하는 것을 제외한 상업적인 사용이 가능합니다.

      +

      ​

      +

      네이버 나눔글꼴은 본 저작권 안내와 라이선스 전문을 포함해서 다른 소프트웨어와 번들하거나 재배포 또는 판매가 가능하고 자유롭게 수정, 재배포하실 수 있습니다.

      +

      ​

      +

      네이버 나눔글꼴 라이선스 전문을 포함하기 어려울 경우, 나눔글꼴의 출처 표기를 권장합니다.

      +

      예) 이 페이지에는 네이버에서 제공한 나눔글꼴이 적용되어 있습니다.

      +

      ​

      +

      네이버 나눔글꼴을 사용한 인쇄물, 광고물(온라인 포함)의 이미지는 나눔글꼴 프로모션을 위해 활용될 수 있습니다.

      +

      ​

      +

      이를 원치 않는 사용자는 언제든지 당사에 요청하실 수 있습니다.

      +

      ​

      +

      정확한 사용 조건은 아래 네이버 나눔글꼴 라이선스 전문을 참고하시기 바랍니다.

      +

      ​

      +

      네이버 마루 부리 글꼴도 나눔 글꼴과 같은 오픈라이센스 폰트로 동일한 저작권 규정을 적용받습니다.

      +

      ​

      +

      ※ 참고해 주세요!

      +

      - 나눔글꼴 라이선스 전문의 한글은 이용자의 이해를 돕기 위해 영문 원본을 번역해 서비스하고 있으며, 법적 효력은 영문에 한합니다.

      +

      ​

      +

      1. 라이선스

      +

      Copyright (c) 2010, NAVER Corporation (https://www.navercorp.com/) with Reserved Font Name Nanum, Naver Nanum, NanumGothic, Naver NanumGothic, NanumMyeongjo, Naver NanumMyeongjo, NanumBrush, Naver NanumBrush, NanumPen, Naver NanumPen, Naver NanumGothicEco, NanumGothicEco, Naver NanumMyeongjoEco, NanumMyeongjoEco, Naver NanumGothicLight, NanumGothicLight, NanumBarunGothic, Naver NanumBarunGothic, NanumSquareRound, NanumBarunPen, MaruBuri, NanumSquareNeo

      +

      ​

      +

      This Font Software is licensed under the SIL Open Font License, Version 1.1.

      +

      ​

      +

      This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL

      +

      ​

      +

      SIL OPEN FONT LICENSE

      +

      Version 1.1 - 26 February 2007

      +

      ​

      +

      ‘나눔, 네이버 나눔, 나눔고딕, 네이버 나눔고딕, 나눔명조, 네이버 나눔명조, 나눔손글씨, 네이버 나눔손글씨, 나눔펜, 네이버 나눔펜, 네이버 나눔고딕에코, 나눔고딕에코, 네이버 나눔명조에코, 나눔명조에코, 네이버 나눔고딕라이트, 나눔고딕라이트, 나눔바른고딕, 네이버나눔바른고딕, 나눔스퀘어라운드, 나눔바른펜, 마루 부리, 나눔스퀘어네오’ 폰트명에 대해 NAVER(https://www.navercorp.com/)가 저작권을 소유하고 있습니다.

      +

      ​

      +

      본 폰트 소프트웨어는 SIL 오픈 폰트 라이선스 버전 1.1에 따라 라이선스 취득을 하였습니다.

      +

      ​

      +

      본 라이선스는 하단에 복사되었고 http://scripts.sil.org/OFL의 FAQ 란에서도 열람 가능합니다.

      +

      ​

      +

      SIL 오픈 폰트 라이선스

      +

      버전 1.1 (2007년 2월 26일)

      +

      ​

      +

      [DEFINITIONS (정의)]

      +

      ""Font Software"" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.

      +

      ​

      +

      ""Reserved Font Name"" refers to any names specified as such after the copyright statement(s).

      +

      ​

      +

      ""Original Version"" refers to the collection of Font Software components as distributed by the Copyright Holder(s).

      +

      ​

      +

      ""Modified Version"" refers to any derivative made by adding to, deleting, or substituting in part or in whole any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.‘

      +

      ​

      +

      ""Author"" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.

      +

      ​

      +

      ‘폰트 소프트웨어’는 본 라이선스에 입거해 저작권자가 배포하고 명확하게 같은 표시가 된 파일들의 집합을 뜻하며, 여기에는 소스 파일, 빌드 스크립트와 문서가 이에 포함됩니다.

      +

      ​

      +

      ‘저작권이 있는 폰트명’은 저작권 정책에 따라서 지정된 이름을 말합니다.

      +

      ​

      +

      ‘원본’은 저작권자가 배포한 폰트 소프트웨어 구성요소를 의미합니다.

      +

      ​

      +

      ‘수정본’은 포맷의 변경이나 폰트 소프트웨어를 새로운 환경에 포팅 시켜, 원본의 일부 혹은 전체에 추가, 삭제 대체해 만든 파생 저작물을 의미합니다.

      +

      ​

      +

      ‘저자’는 폰트 소프트웨어에 기여한 디자이너, 엔지니어, 프로그래머, 기술 전문가 등을 의미합니다.

      +

      ​

      +

      2. PREAMBLE (전문)

      +

      The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.

      +

      ​

      +

      The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works.

      +

      ​

      +

      The fonts and derivatives, however, cannot be released under any other type of license.

      +

      ​

      +

      The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives.

      +

      ​

      +

      본 폰트 라이선스를 오픈하는 것은(이하 OFL)는 전 세계 폰트 개발 프로젝트를 지원하고 학계와 언어 관련 학계의 폰트 개발을 위한 연구를 지지하기 위해서인 동시에, 폰트 제휴를 통해 폰트가 공유되고 개선될 수 있는 자유롭게 개방된 환경을 만들기 위해서입니다.

      +

      ​

      +

      OFL은 라이선스를 취득한 폰트가 그 자체로 판매되지 않는 한 자유롭게 사용, 연구, 수정, 재배포 하는 것을 허가합니다.

      +

      ​

      +

      수정된 폰트를 포함한 폰트는 저작권 명이 사용되지 않는 한 기타 소프트웨어와 함께 묶이거나 삽입, 재배포 할 수 있습니다.

      +

      ​

      +

      단 폰트와 수정된 폰트는 기타 다른 라이선스에 포함되어 배포될 수는 없습니다.

      +

      ​

      +

      이 라이선스 하에 있기 위한 폰트에 대한 요구사항은 본 폰트나 수정본을 사용하여 제작된 어떠한 문서에도 적용되지 않습니다.

      +

      ​

      +

      3. PERMISSION & CONDITIONS (허가 및 조건)

      +

      Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:

      +

      ​

      +

      본 폰트 소프트웨어를 사용하도록 허가받은 개인/기업/단체 누구라도 다음 명시된 조건에 따라 폰트 소프트웨어의 수정 혹은 수정되지 않은 복사본을 무료로 사용, 연구, 복사, 통합, 삽입, 수정, 재배포할 수 있도록 허가합니다.

      +

      ​

      +

      1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.

      +

      ​

      +

      원본이나 수정본의 폰트 소프트웨어 혹은 개별 구성요소인 폰트 자체가 판매되어서는 안됩니다.

      +

      ​

      +

      2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license.

      +

      ​

      +

      These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.

      +

      ​

      +

      본 폰트 소프트웨어의 원본 혹은 수정본은 상기 저작권 안내와 본 라이선스에 대한 내용을 포함하는 경우에는 다른 소프트웨어와 함께 묶이거나 재배포 혹은 판매가 가능합니다.

      +

      ​

      +

      이는 독립 텍스트 파일과 가독성이 있는 헤더 혹은 유저가 용이하게 열람 가능한 이상 텍스트 파일 혹은 이진 파일 내 기계가 읽을 수 있는 메타데이터 형태를 모두 의미합니다.

      +

      ​

      +

      3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder.

      +

      ​

      +

      This restriction only applies to the primary font name as presented to the users.

      +

      ​

      +

      본 폰트 소프트웨어의 어떠한 수정본도 동일한 저작권자가 명시적 허가서를 부여하지 않는 한 저작권이 있는 폰트명을 사용해서는 안 됩니다.

      +

      ​

      +

      본 제한 사항은 유저들에게 제공된 기존 폰트명을 뜻합니다.

      +

      ​

      +

      4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.

      +

      ​

      +

      본 폰트 소프트웨어의 저작권자 혹은 저자의 이름은 그들의 명시적 서면 허가가 있거나 또는 그들의 공헌을 인정하기 위한 경우를 제외하고는 수정본에 대한 사용을 유도, 추천 혹은 광고하기 위한 목적으로 사용할 수 없습니다.

      +

      ​

      +

      5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed any other license.

      +

      ​

      +

      The requirement for fonts to remain under this license does not apply to any document created using the Font Software.

      +

      ​

      +

      본 폰트 소프트웨어는 전체나 부분, 혹은 수정 여부에 상관없이 본 라이선스 하에 배포가 되어야 하며 기타 다른 라이선스 하에서는 배포를 할 수 없습니다.

      +

      ​

      +

      폰트에 대한 요구 조건은 이 라이선스 하에서만 유효하며 이 라이선스 하에 있기 위한 폰트에 대한 요구사항은 본 폰트 소프트웨어를 사용해 제작한 어떠한 문서에도 적용되지 않습니다.

      +

      ​

      +

      4. TERMINATION (계약의 종료)

      +

      This license becomes null and void if any of the above conditions are not met.

      +

      ​

      +

      본 라이선스는 상기 조건 중 일부라도 부합되지 않으면 무효가 될 수 있습니다.

      +

      ​

      +

      5. DISCLAIMER (면책조항)

      +

      THE FONT SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT.

      +

      ​

      +

      IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.

      +

      ​

      +

      본 폰트 소프트웨어는 저작권, 특허권, 상표권 및 기타 권리의 비침해성과 특정 목적에의 적합성 포함한 명시적, 묵시적인 어떠한 종류의 보증 없이 “있는 그대로” 제공됩니다.

      +

      ​

      +

      어떠한 경우에도 저작권자는 본 폰트 소프트웨어의 사용 또는 이의 사용 불가, 그밖에 폰트 소프트웨어의 취급과 관련하여 발생하는 모든 계약, 불법행위 혹은 다른 일로 하여금 발생하는 일반적, 특수적, 간접적, 부차적 혹은 필연적 손해를 포함하는 소송, 손해, 혹은 기타 책임에 대한 의무를 가지지 않습니다.

      + +
      +
      +
      + +
      +
      만족도 평가
    \ No newline at end of file diff --git a/apps/site/public/work/baekje-celadon/assets/fonts/MaruBuri-Regular.woff2 b/apps/site/public/work/baekje-celadon/assets/fonts/MaruBuri-Regular.woff2 new file mode 100644 index 0000000..3bc205f Binary files /dev/null and b/apps/site/public/work/baekje-celadon/assets/fonts/MaruBuri-Regular.woff2 differ diff --git a/apps/site/public/work/baekje-celadon/assets/fonts/MaruBuri-SemiBold.woff2 b/apps/site/public/work/baekje-celadon/assets/fonts/MaruBuri-SemiBold.woff2 new file mode 100644 index 0000000..be593a5 Binary files /dev/null and b/apps/site/public/work/baekje-celadon/assets/fonts/MaruBuri-SemiBold.woff2 differ diff --git a/apps/site/public/work/baekje-celadon/assets/fonts/SOURCES.md b/apps/site/public/work/baekje-celadon/assets/fonts/SOURCES.md new file mode 100644 index 0000000..66d2c89 --- /dev/null +++ b/apps/site/public/work/baekje-celadon/assets/fonts/SOURCES.md @@ -0,0 +1,13 @@ +# MaruBuri source record + +Downloaded 2026-09-12 from the official NAVER Hangeul static host. The files are retained unchanged: no conversion or subsetting was performed. + +| File | Official URL | HTTP content type | Size | SHA-256 | +| --- | --- | --- | --- | --- | +| `MaruBuri-Regular.woff2` | https://hangeul.pstatic.net/hangeul_static/webfont/MaruBuri/MaruBuri-Regular.woff2 | `font/woff2` | 433776 bytes | `4CF1341CF2F23FB3E263712DFDE1D8F25EEDCC328B696A2E5A2C8ADD55E5C17B` | +| `MaruBuri-SemiBold.woff2` | https://hangeul.pstatic.net/hangeul_static/webfont/MaruBuri/MaruBuri-SemiBold.woff2 | `font/woff2` | 466108 bytes | `7AEF4862FA3219B0A7DEB6746E27116A38C4069F4424EB51EDF103B29795F5C2` | + +- Official stylesheet checked: https://hangeul.pstatic.net/hangeul_static/css/maru-buri.css +- Official NAVER license page saved verbatim as `LICENSE.html`: https://help.naver.com/service/11029/contents/18088?lang=ko&osType=PC +- `LICENSE.html` SHA-256: `8538F7921744D5E040F603BC301465EFBD038F1054D0754B7508DE3286452EC3` +- The saved official page includes the NAVER copyright notice and the SIL Open Font License 1.1 text for MaruBuri. diff --git a/apps/site/public/work/baekje-celadon/design.md b/apps/site/public/work/baekje-celadon/design.md new file mode 100644 index 0000000..11b1f32 --- /dev/null +++ b/apps/site/public/work/baekje-celadon/design.md @@ -0,0 +1,17 @@ +# 비색의 침묵 + +암실의 청자 사진을 주연으로 유지하고 회색 카드나 격자는 추가하지 않는다. 제1·2실의 방 번호, 제목, 재질 설명, 매크로 캡션을 공통 레일로 정리했다. 첫 사진은 기존 4:5 비율을 보존하고 관람 구성 CTA와 가상 관람 안내를 인접하게 둔다. + +| 판단 축 | 적용 | 한계 | +| --- | --- | --- | +| 구도 | Hofmann의 레일과 비대칭을 참고해 방 정보와 캡션을 같은 열에 맞췄다. | 전시 사진의 감상 효과를 보편적으로 예측하지 않는다. | +| 타입 | Ruder를 참고해 방 번호와 제목·설명의 크기 차이를 명확히 했다. | 서체만으로 체류나 이해가 바뀐다고 단정하지 않는다. | +| 색 | Albers를 참고해 어두운 바탕, 비색 강조, 밝은 CTA의 역할을 나눴다. | 실제 명도 대비는 브라우저 검증에서 확인한다. | + +토큰은 `--surface`, `--ink`, `--accent`, `--container`, `--space-*`를 유지한다. 로컬 MaruBuri 400/600은 `styles/fonts.css`, Pretendard는 기존 CDN을 유지한다. 가상 전시·관람 안내와 기존 앵커는 보존했다. + +## 2026-09-12 현재 검증 기록 + +- `verify-final` 18개 묶음은 16개가 즉시 통과했다. 전체 묶음의 invariant·visual 검사는 Gaon·Dure를 대상으로 하며, 나머지 2개는 수정 뒤 release 독립 재실행에서 ALL PASS·ALL MATCH였다. +- root는 28개 모바일, 21개 데스크톱, 7개 하위 경로와 30개 앱 상태를 직접 검토해 수용했다. stress 112건은 hard failure 0이며, 가로 넘침 4건은 targeted fix 뒤 390px 재측정에서 0이다. +- 이 기록은 렌더·계약 범위의 현재 결과다. 모든 폭·키보드 경로·인쇄 등 개별 기능을 완전 재실행했다는 뜻이 아니며, 참여자 과업 효과도 미측정이다. diff --git a/apps/site/public/work/baekje-celadon/index.html b/apps/site/public/work/baekje-celadon/index.html index e930dd0..c2e2e80 100644 --- a/apps/site/public/work/baekje-celadon/index.html +++ b/apps/site/public/work/baekje-celadon/index.html @@ -3,15 +3,15 @@ - 비색의 침묵 · 고려청자 특별전 + 비색의 침묵 · 고려청자 전시 구성 - + @@ -19,13 +19,13 @@ - +
    -
    @@ -63,13 +59,13 @@ fetchpriority="high" />
    - 청자 상감운학문 주자 · 12세기 - 호암미술관 소장 + 청자 주자 · 전시 연출 이미지 + 가상 전시 소품

    - 특별전 · 2026 가을 + 가상 전시 구성 · 고려청자

    천 년의 비색은
    말이 없다 @@ -80,17 +76,13 @@ 않고 세 개의 암실에 놓아 두었습니다.

    - 도슨트 예약 -

    9월 5일 – 11월 22일 · 국립중앙박물관 기획전시실

    + 관람 구성 보기 +

    일정·장소·예약 정보는 전시 구성 예시이며 실제 관람을 접수하지 않습니다.

    -

    제1실

    @@ -110,15 +102,11 @@ loading="lazy" />
    - 빙렬 확대 · 12세기 청자 표면 · 측광 + 빙렬 확대 · 12세기 청자 표면 · 측광
    -
    @@ -151,35 +139,32 @@
    -

    안내

    -

    세 개의 방, 예약제

    +

    세 개의 방으로 보는 전시 구성

    - 암실 조명 때문에 회당 인원을 30명으로 제한합니다. 도슨트는 하루 세 번, - 유약과 가마 이야기만 합니다. + 조명과 동선이 관람 경험을 어떻게 바꾸는지 보여 주기 위한 예시입니다. + 아래 일정과 해설 방식은 실제 전시 운영 정보가 아닙니다.

    -
    기간
    +
    전시 기간 예시
    2026년 9월 5일 – 11월 22일 · 월요일 휴관
    -
    시간
    +
    관람 시간 예시
    10:00–18:00 · 금·토 21:00까지
    -
    도슨트
    +
    해설 구성 예시
    11:00 / 14:00 / 16:00 · 회당 40분
    예약
    -
    국립중앙박물관 예약 시스템
    +
    실제 예약 시스템과 연결되지 않습니다.
    @@ -188,23 +173,10 @@
    -

    비색의 침묵 · 고려청자 특별전

    -

    국립중앙박물관 기획전시실 · 서울 용산

    +

    비색의 침묵 · 고려청자 전시 구성

    +

    가상 전시 프로젝트 · 장소와 소장 정보는 예시입니다.

    - diff --git a/apps/site/public/work/baekje-celadon/styles/fonts.css b/apps/site/public/work/baekje-celadon/styles/fonts.css new file mode 100644 index 0000000..f5234d6 --- /dev/null +++ b/apps/site/public/work/baekje-celadon/styles/fonts.css @@ -0,0 +1,15 @@ +@font-face { + font-family: "MaruBuri"; + src: url("../assets/fonts/MaruBuri-Regular.woff2") format("woff2"); + font-style: normal; + font-weight: 400; + font-display: swap; +} + +@font-face { + font-family: "MaruBuri"; + src: url("../assets/fonts/MaruBuri-SemiBold.woff2") format("woff2"); + font-style: normal; + font-weight: 600; + font-display: swap; +} diff --git a/apps/site/public/work/baekje-celadon/styles/main.css b/apps/site/public/work/baekje-celadon/styles/main.css index 90c3154..4758637 100644 --- a/apps/site/public/work/baekje-celadon/styles/main.css +++ b/apps/site/public/work/baekje-celadon/styles/main.css @@ -1,4 +1,4 @@ -@import url("./tokens.css"); +@import url("./tokens.css?v=20260912all"); /* ========================================================================== 비색의 침묵 — editorial-archival. 암실의 세 개의 방. @@ -132,6 +132,7 @@ a { } .nav { display: flex; + flex-wrap: wrap; gap: clamp(var(--space-3), 2vw, var(--space-5)); font-size: var(--step--1); } @@ -151,13 +152,25 @@ a { /* ── 첫 방(히어로) ────────────────────────────────────────────────────── */ .hero { - padding-block: var(--space-7); + display: grid; + align-items: center; + min-block-size: min(46rem, calc(100svh - 4rem)); + padding-block: var(--space-6); + border-bottom: 1px solid var(--line); } .hero-grid { display: grid; - grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); - gap: var(--space-6) var(--space-7); - align-items: end; + grid-template-columns: minmax(15rem, 34rem) minmax(0, 1fr); + gap: clamp(var(--space-5), 6vw, var(--space-8)); + align-items: center; +} +.hero-grid > *, +.two > *, +.visit-grid > * { + min-width: 0; +} +.hero-figure { + width: min(100%, 34rem); } .hero-figure img { display: block; @@ -179,6 +192,10 @@ a { letter-spacing: 0.12em; margin-bottom: var(--space-4); } +.hero-text { + max-width: 39rem; + padding-block: var(--space-4); +} .hero-text .lead { margin-top: var(--space-4); } @@ -194,7 +211,10 @@ a { color: var(--ink-faint); } .btn { - display: inline-block; + display: inline-flex; + align-items: center; + min-height: 44px; + padding-inline: var(--space-4); background: var(--ink); color: var(--surface); font-weight: 500; @@ -221,6 +241,9 @@ a { .section { padding-block: var(--space-8); } +.section[id] { + scroll-margin-top: 6rem; +} .band { background: var(--surface-raised); border-block: 1px solid var(--line); @@ -229,16 +252,27 @@ a { /* ── 제1실 — 풀블리드 판 ──────────────────────────────────────────────── */ .plate-head { - max-width: 40em; + display: grid; + grid-template-columns: minmax(8rem, 1fr) minmax(0, 5fr); + column-gap: var(--space-5); + max-width: var(--container); +} +.plate-head .room-no { + grid-column: 1; + grid-row: 1 / span 2; + margin: 0; } .plate-head h2 { + grid-column: 2; margin-top: var(--space-1); } .plate-head .lead { + grid-column: 2; margin-top: var(--space-4); } .plate-figure { - margin-top: var(--space-6); + width: min(100% - 2 * var(--pad-inline), var(--container-wide)); + margin: var(--space-6) auto 0; } .plate-figure img { display: block; @@ -246,10 +280,16 @@ a { height: auto; } .plate-figure figcaption { + display: grid; + grid-template-columns: minmax(8rem, 1fr) minmax(0, 5fr); + column-gap: var(--space-5); font-size: var(--step--1); color: var(--ink-faint); margin-top: var(--space-2); } +.plate-figure figcaption span { + grid-column: 2; +} /* ── 제2실 — 2단 ──────────────────────────────────────────────────────── */ @@ -317,22 +357,22 @@ a { /* ── 등장 모션 ────────────────────────────────────────────────────────── */ .reveal { - opacity: 0; - translate: 0 14px; - transition: opacity var(--dur-normal) var(--ease-soft), - translate var(--dur-normal) var(--ease-soft); - transition-delay: var(--delay, 0ms); -} -.reveal.is-in { opacity: 1; translate: 0 0; } -@media (prefers-reduced-motion: reduce) { - .reveal { - opacity: 1; - translate: 0 0; - transition: none; - } +.two-text { + display: grid; + grid-template-columns: minmax(8rem, 1fr) minmax(0, 5fr); + column-gap: var(--space-5); +} +.two-text .room-no { + grid-column: 1; + grid-row: 1 / span 3; + margin: 0; +} +.two-text h2, +.two-text p { + grid-column: 2; } /* ── 반응형 ───────────────────────────────────────────────────────────── */ @@ -347,6 +387,13 @@ a { .hero-grid { align-items: start; } + .hero { + min-block-size: auto; + } + .hero-text { + order: -1; + padding-top: 0; + } .hero-figure { max-width: 26rem; } @@ -354,6 +401,24 @@ a { .section { padding-block: var(--space-6); } + .plate-head, + .two-text, + .plate-figure figcaption { + grid-template-columns: 1fr; + row-gap: var(--space-3); + } + .plate-head .room-no, + .plate-head h2, + .plate-head .lead, + .two-text .room-no, + .two-text h2, + .two-text p { + grid-column: 1; + grid-row: auto; + } + .plate-figure figcaption span { + grid-column: 1; + } } @media (max-width: 560px) { .head-inner { @@ -363,6 +428,6 @@ a { } .nav { width: 100%; - justify-content: space-between; + justify-content: flex-start; } } diff --git a/apps/site/public/work/baekje-celadon/styles/tokens.css b/apps/site/public/work/baekje-celadon/styles/tokens.css index 8278875..276ff2f 100644 --- a/apps/site/public/work/baekje-celadon/styles/tokens.css +++ b/apps/site/public/work/baekje-celadon/styles/tokens.css @@ -28,10 +28,10 @@ --surface-raised: #191d1c; --ink: #eceae2; /* 백색이 아니라 골동지의 밝기 */ --ink-muted: #a7a69b; - --ink-faint: #7b7d76; + --ink-faint: #878982; --line: #2b302e; --accent: #8fbcaa; /* 비색 — 텍스트용으로 밝힘. 배경 채움 금지 */ - --accent-dim: #5e8274; + --accent-dim: #80ac99; --ink-bright: #ffffff; /* CTA hover */ --space-1: 0.25rem; @@ -45,8 +45,11 @@ --radius: 2px; - --container: 1120px; - --pad-inline: clamp(1.25rem, 1rem + 2.5vw, 4rem); + /* 읽는 폭과 유물 판은 분리한다. 2560px에서도 문장이 늘어지지 않고, + 빙렬 이미지만 전시 벽처럼 넓어진다. */ + --container: 1200px; + --container-wide: 1600px; + --pad-inline: clamp(1.25rem, 1rem + 2.5vw, 4.5rem); --dur-quick: 160ms; --dur-normal: 480ms; diff --git a/apps/site/public/work/cask-archive/assets/fonts/LICENSE.html b/apps/site/public/work/cask-archive/assets/fonts/LICENSE.html new file mode 100644 index 0000000..571387d --- /dev/null +++ b/apps/site/public/work/cask-archive/assets/fonts/LICENSE.html @@ -0,0 +1,169 @@ +네이버 나눔글꼴 라이선스안내 : 고객센터
    빈줄

        + + + +
        +
        +
        +
        +
        +

        네이버 나눔글꼴의 지적 재산권은 네이버와 네이버 문화재단에 있습니다.

        +

        ​

        +

        네이버 나눔글꼴은 개인 및 기업 사용자를 포함한 모든 사용자에게 무료로 제공되며 글꼴 자체를 유료로 판매하는 것을 제외한 상업적인 사용이 가능합니다.

        +

        ​

        +

        네이버 나눔글꼴은 본 저작권 안내와 라이선스 전문을 포함해서 다른 소프트웨어와 번들하거나 재배포 또는 판매가 가능하고 자유롭게 수정, 재배포하실 수 있습니다.

        +

        ​

        +

        네이버 나눔글꼴 라이선스 전문을 포함하기 어려울 경우, 나눔글꼴의 출처 표기를 권장합니다.

        +

        예) 이 페이지에는 네이버에서 제공한 나눔글꼴이 적용되어 있습니다.

        +

        ​

        +

        네이버 나눔글꼴을 사용한 인쇄물, 광고물(온라인 포함)의 이미지는 나눔글꼴 프로모션을 위해 활용될 수 있습니다.

        +

        ​

        +

        이를 원치 않는 사용자는 언제든지 당사에 요청하실 수 있습니다.

        +

        ​

        +

        정확한 사용 조건은 아래 네이버 나눔글꼴 라이선스 전문을 참고하시기 바랍니다.

        +

        ​

        +

        네이버 마루 부리 글꼴도 나눔 글꼴과 같은 오픈라이센스 폰트로 동일한 저작권 규정을 적용받습니다.

        +

        ​

        +

        ※ 참고해 주세요!

        +

        - 나눔글꼴 라이선스 전문의 한글은 이용자의 이해를 돕기 위해 영문 원본을 번역해 서비스하고 있으며, 법적 효력은 영문에 한합니다.

        +

        ​

        +

        1. 라이선스

        +

        Copyright (c) 2010, NAVER Corporation (https://www.navercorp.com/) with Reserved Font Name Nanum, Naver Nanum, NanumGothic, Naver NanumGothic, NanumMyeongjo, Naver NanumMyeongjo, NanumBrush, Naver NanumBrush, NanumPen, Naver NanumPen, Naver NanumGothicEco, NanumGothicEco, Naver NanumMyeongjoEco, NanumMyeongjoEco, Naver NanumGothicLight, NanumGothicLight, NanumBarunGothic, Naver NanumBarunGothic, NanumSquareRound, NanumBarunPen, MaruBuri, NanumSquareNeo

        +

        ​

        +

        This Font Software is licensed under the SIL Open Font License, Version 1.1.

        +

        ​

        +

        This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL

        +

        ​

        +

        SIL OPEN FONT LICENSE

        +

        Version 1.1 - 26 February 2007

        +

        ​

        +

        ‘나눔, 네이버 나눔, 나눔고딕, 네이버 나눔고딕, 나눔명조, 네이버 나눔명조, 나눔손글씨, 네이버 나눔손글씨, 나눔펜, 네이버 나눔펜, 네이버 나눔고딕에코, 나눔고딕에코, 네이버 나눔명조에코, 나눔명조에코, 네이버 나눔고딕라이트, 나눔고딕라이트, 나눔바른고딕, 네이버나눔바른고딕, 나눔스퀘어라운드, 나눔바른펜, 마루 부리, 나눔스퀘어네오’ 폰트명에 대해 NAVER(https://www.navercorp.com/)가 저작권을 소유하고 있습니다.

        +

        ​

        +

        본 폰트 소프트웨어는 SIL 오픈 폰트 라이선스 버전 1.1에 따라 라이선스 취득을 하였습니다.

        +

        ​

        +

        본 라이선스는 하단에 복사되었고 http://scripts.sil.org/OFL의 FAQ 란에서도 열람 가능합니다.

        +

        ​

        +

        SIL 오픈 폰트 라이선스

        +

        버전 1.1 (2007년 2월 26일)

        +

        ​

        +

        [DEFINITIONS (정의)]

        +

        ""Font Software"" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.

        +

        ​

        +

        ""Reserved Font Name"" refers to any names specified as such after the copyright statement(s).

        +

        ​

        +

        ""Original Version"" refers to the collection of Font Software components as distributed by the Copyright Holder(s).

        +

        ​

        +

        ""Modified Version"" refers to any derivative made by adding to, deleting, or substituting in part or in whole any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.‘

        +

        ​

        +

        ""Author"" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.

        +

        ​

        +

        ‘폰트 소프트웨어’는 본 라이선스에 입거해 저작권자가 배포하고 명확하게 같은 표시가 된 파일들의 집합을 뜻하며, 여기에는 소스 파일, 빌드 스크립트와 문서가 이에 포함됩니다.

        +

        ​

        +

        ‘저작권이 있는 폰트명’은 저작권 정책에 따라서 지정된 이름을 말합니다.

        +

        ​

        +

        ‘원본’은 저작권자가 배포한 폰트 소프트웨어 구성요소를 의미합니다.

        +

        ​

        +

        ‘수정본’은 포맷의 변경이나 폰트 소프트웨어를 새로운 환경에 포팅 시켜, 원본의 일부 혹은 전체에 추가, 삭제 대체해 만든 파생 저작물을 의미합니다.

        +

        ​

        +

        ‘저자’는 폰트 소프트웨어에 기여한 디자이너, 엔지니어, 프로그래머, 기술 전문가 등을 의미합니다.

        +

        ​

        +

        2. PREAMBLE (전문)

        +

        The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.

        +

        ​

        +

        The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works.

        +

        ​

        +

        The fonts and derivatives, however, cannot be released under any other type of license.

        +

        ​

        +

        The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives.

        +

        ​

        +

        본 폰트 라이선스를 오픈하는 것은(이하 OFL)는 전 세계 폰트 개발 프로젝트를 지원하고 학계와 언어 관련 학계의 폰트 개발을 위한 연구를 지지하기 위해서인 동시에, 폰트 제휴를 통해 폰트가 공유되고 개선될 수 있는 자유롭게 개방된 환경을 만들기 위해서입니다.

        +

        ​

        +

        OFL은 라이선스를 취득한 폰트가 그 자체로 판매되지 않는 한 자유롭게 사용, 연구, 수정, 재배포 하는 것을 허가합니다.

        +

        ​

        +

        수정된 폰트를 포함한 폰트는 저작권 명이 사용되지 않는 한 기타 소프트웨어와 함께 묶이거나 삽입, 재배포 할 수 있습니다.

        +

        ​

        +

        단 폰트와 수정된 폰트는 기타 다른 라이선스에 포함되어 배포될 수는 없습니다.

        +

        ​

        +

        이 라이선스 하에 있기 위한 폰트에 대한 요구사항은 본 폰트나 수정본을 사용하여 제작된 어떠한 문서에도 적용되지 않습니다.

        +

        ​

        +

        3. PERMISSION & CONDITIONS (허가 및 조건)

        +

        Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:

        +

        ​

        +

        본 폰트 소프트웨어를 사용하도록 허가받은 개인/기업/단체 누구라도 다음 명시된 조건에 따라 폰트 소프트웨어의 수정 혹은 수정되지 않은 복사본을 무료로 사용, 연구, 복사, 통합, 삽입, 수정, 재배포할 수 있도록 허가합니다.

        +

        ​

        +

        1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.

        +

        ​

        +

        원본이나 수정본의 폰트 소프트웨어 혹은 개별 구성요소인 폰트 자체가 판매되어서는 안됩니다.

        +

        ​

        +

        2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license.

        +

        ​

        +

        These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.

        +

        ​

        +

        본 폰트 소프트웨어의 원본 혹은 수정본은 상기 저작권 안내와 본 라이선스에 대한 내용을 포함하는 경우에는 다른 소프트웨어와 함께 묶이거나 재배포 혹은 판매가 가능합니다.

        +

        ​

        +

        이는 독립 텍스트 파일과 가독성이 있는 헤더 혹은 유저가 용이하게 열람 가능한 이상 텍스트 파일 혹은 이진 파일 내 기계가 읽을 수 있는 메타데이터 형태를 모두 의미합니다.

        +

        ​

        +

        3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder.

        +

        ​

        +

        This restriction only applies to the primary font name as presented to the users.

        +

        ​

        +

        본 폰트 소프트웨어의 어떠한 수정본도 동일한 저작권자가 명시적 허가서를 부여하지 않는 한 저작권이 있는 폰트명을 사용해서는 안 됩니다.

        +

        ​

        +

        본 제한 사항은 유저들에게 제공된 기존 폰트명을 뜻합니다.

        +

        ​

        +

        4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.

        +

        ​

        +

        본 폰트 소프트웨어의 저작권자 혹은 저자의 이름은 그들의 명시적 서면 허가가 있거나 또는 그들의 공헌을 인정하기 위한 경우를 제외하고는 수정본에 대한 사용을 유도, 추천 혹은 광고하기 위한 목적으로 사용할 수 없습니다.

        +

        ​

        +

        5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed any other license.

        +

        ​

        +

        The requirement for fonts to remain under this license does not apply to any document created using the Font Software.

        +

        ​

        +

        본 폰트 소프트웨어는 전체나 부분, 혹은 수정 여부에 상관없이 본 라이선스 하에 배포가 되어야 하며 기타 다른 라이선스 하에서는 배포를 할 수 없습니다.

        +

        ​

        +

        폰트에 대한 요구 조건은 이 라이선스 하에서만 유효하며 이 라이선스 하에 있기 위한 폰트에 대한 요구사항은 본 폰트 소프트웨어를 사용해 제작한 어떠한 문서에도 적용되지 않습니다.

        +

        ​

        +

        4. TERMINATION (계약의 종료)

        +

        This license becomes null and void if any of the above conditions are not met.

        +

        ​

        +

        본 라이선스는 상기 조건 중 일부라도 부합되지 않으면 무효가 될 수 있습니다.

        +

        ​

        +

        5. DISCLAIMER (면책조항)

        +

        THE FONT SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT.

        +

        ​

        +

        IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.

        +

        ​

        +

        본 폰트 소프트웨어는 저작권, 특허권, 상표권 및 기타 권리의 비침해성과 특정 목적에의 적합성 포함한 명시적, 묵시적인 어떠한 종류의 보증 없이 “있는 그대로” 제공됩니다.

        +

        ​

        +

        어떠한 경우에도 저작권자는 본 폰트 소프트웨어의 사용 또는 이의 사용 불가, 그밖에 폰트 소프트웨어의 취급과 관련하여 발생하는 모든 계약, 불법행위 혹은 다른 일로 하여금 발생하는 일반적, 특수적, 간접적, 부차적 혹은 필연적 손해를 포함하는 소송, 손해, 혹은 기타 책임에 대한 의무를 가지지 않습니다.

        + +
        +
        +
        + +
        +
        만족도 평가
      \ No newline at end of file diff --git a/apps/site/public/work/cask-archive/assets/fonts/MaruBuri-Regular.woff2 b/apps/site/public/work/cask-archive/assets/fonts/MaruBuri-Regular.woff2 new file mode 100644 index 0000000..3bc205f Binary files /dev/null and b/apps/site/public/work/cask-archive/assets/fonts/MaruBuri-Regular.woff2 differ diff --git a/apps/site/public/work/cask-archive/assets/fonts/MaruBuri-SemiBold.woff2 b/apps/site/public/work/cask-archive/assets/fonts/MaruBuri-SemiBold.woff2 new file mode 100644 index 0000000..be593a5 Binary files /dev/null and b/apps/site/public/work/cask-archive/assets/fonts/MaruBuri-SemiBold.woff2 differ diff --git a/apps/site/public/work/cask-archive/assets/fonts/SOURCES.md b/apps/site/public/work/cask-archive/assets/fonts/SOURCES.md new file mode 100644 index 0000000..66d2c89 --- /dev/null +++ b/apps/site/public/work/cask-archive/assets/fonts/SOURCES.md @@ -0,0 +1,13 @@ +# MaruBuri source record + +Downloaded 2026-09-12 from the official NAVER Hangeul static host. The files are retained unchanged: no conversion or subsetting was performed. + +| File | Official URL | HTTP content type | Size | SHA-256 | +| --- | --- | --- | --- | --- | +| `MaruBuri-Regular.woff2` | https://hangeul.pstatic.net/hangeul_static/webfont/MaruBuri/MaruBuri-Regular.woff2 | `font/woff2` | 433776 bytes | `4CF1341CF2F23FB3E263712DFDE1D8F25EEDCC328B696A2E5A2C8ADD55E5C17B` | +| `MaruBuri-SemiBold.woff2` | https://hangeul.pstatic.net/hangeul_static/webfont/MaruBuri/MaruBuri-SemiBold.woff2 | `font/woff2` | 466108 bytes | `7AEF4862FA3219B0A7DEB6746E27116A38C4069F4424EB51EDF103B29795F5C2` | + +- Official stylesheet checked: https://hangeul.pstatic.net/hangeul_static/css/maru-buri.css +- Official NAVER license page saved verbatim as `LICENSE.html`: https://help.naver.com/service/11029/contents/18088?lang=ko&osType=PC +- `LICENSE.html` SHA-256: `8538F7921744D5E040F603BC301465EFBD038F1054D0754B7508DE3286452EC3` +- The saved official page includes the NAVER copyright notice and the SIL Open Font License 1.1 text for MaruBuri. diff --git a/apps/site/public/work/cask-archive/design.md b/apps/site/public/work/cask-archive/design.md new file mode 100644 index 0000000..88eb7b7 --- /dev/null +++ b/apps/site/public/work/cask-archive/design.md @@ -0,0 +1,17 @@ +# 캐스크 아카이브 — 디자인 결정 기록 + +## 관찰과 방향 + +- 관찰: 어두운 앰버 표면의 병 사진은 이중 베젤과 떠 있는 태그 때문에 작은 카드처럼 보였다. +- 원리 적용 범위: 병 사진은 4:5의 큰 표면으로 두고 캐스크 번호·종류·향미 조건은 바로 이어지는 원장형 캡션으로 묶는다. 검색·필터·도슨트 세션 선택은 같은 선과 상태 대비로 읽힌다. +- 결정: 병 사진의 베젤을 제거하고 캡션을 사진 아래 정렬선에 맞췄다. 실제 수입·인증·예약을 뜻하는 문구는 예시 메타데이터와 세션 안내로 제한한다. +- 기각 조건: 긴 캐스크 메타가 320px에서 넘치거나 필터·폼 상태가 앰버 대비에서 읽히지 않으면 캡션과 컨트롤의 줄바꿈 규칙을 조정한다. + +## 토큰과 검증 + +- 타입: 로컬 `MaruBuri` 400·600과 기존 Pretendard·모노 역할을 유지한다. +- 색: `--accent` 앰버, 어두운 `--surface`, 얇은 원장 선을 유지한다. +- 구도: 넓은 화면의 hero는 5:7 텍스트/병 사진, 병은 4:5, 캡션은 사진과 같은 폭을 사용한다. +- `verify-final` 18개 묶음은 16개가 즉시 통과했다. 전체 묶음의 invariant·visual 검사는 Gaon·Dure를 대상으로 하며, 나머지 2개는 수정 뒤 release 독립 재실행에서 ALL PASS·ALL MATCH였다. +- root는 28개 모바일, 21개 데스크톱, 7개 하위 경로와 30개 앱 상태를 직접 검토해 수용했다. stress 112건은 hard failure 0이며, 가로 넘침 4건은 targeted fix 뒤 390px 재측정에서 0이다. +- 이 기록은 렌더·계약 범위의 현재 결과다. 모든 폭·키보드 경로·인쇄 등 개별 기능을 완전 재실행했다는 뜻이 아니며, 참여자 과업 효과도 미측정이다. diff --git a/apps/site/public/work/cask-archive/docent/index.html b/apps/site/public/work/cask-archive/docent/index.html index 583a584..b4b2245 100644 --- a/apps/site/public/work/cask-archive/docent/index.html +++ b/apps/site/public/work/cask-archive/docent/index.html @@ -9,10 +9,7 @@ - + - - + + + +
      @@ -209,7 +208,7 @@
      -
      +
      - 순서 - 라인업 구성 - ABV + 순서 + 라인업 구성 + ABV @@ -313,9 +312,9 @@ - - - + + + @@ -368,7 +367,7 @@
      -
      +
      미식 페어링

      @@ -393,14 +392,15 @@
      -
      예약 신청
      +
      세션 항목

      - 도슨트 테이스팅 세션 실시간 예약 + 도슨트 테이스팅 세션 선택

      -
      +

      안내: 아래 예약 항목과 가격은 예시입니다. 입력 정보는 저장·전송되지 않으며 실제 예약으로 이어지지 않습니다.

      +
      - @@ -409,11 +409,11 @@
      - +
      - @@ -424,21 +424,21 @@
      - +
      - +
      - +
      @@ -448,9 +448,8 @@
      -

      캐스크 아카이브 · 서울 용산구 한남대로 27길 19 지하 1층

      -

      매일 18:00 – 02:00 (사전 예약제)

      -

      bottling@caskarchive.kr

      +

      캐스크 아카이브 · 독립병입 위스키 안내

      +

      이 페이지의 코스·가격·신청 흐름은 예시이며 입력 정보는 저장·전송되지 않습니다.

      diff --git a/apps/site/public/work/cask-archive/index.html b/apps/site/public/work/cask-archive/index.html index 619354b..21605aa 100644 --- a/apps/site/public/work/cask-archive/index.html +++ b/apps/site/public/work/cask-archive/index.html @@ -3,23 +3,20 @@ - 캐스크 아카이브 (CASK ARCHIVE) · 독립병입자 위스키바 & 도슨트 큐레이션 + 캐스크 아카이브 (CASK ARCHIVE) · 독립병입 위스키 안내 - - + + - + - + - 도슨트 예약 + 도슨트 세션
      @@ -67,29 +64,29 @@
      - OFFICIALLY CERTIFIED INDEPENDENT BOTTLER BAR + INDEPENDENT BOTTLER TASTING ARCHIVE

      - 시간과 배럴이 빚어낸
      - 오직 단 하나의 원액(Single Cask) + 시간과 배럴이 만든
      + 단 하나의 캐스크 원액

      - 증류소의 기본 공식 라인업에서는 맛볼 수 없는 독립병입자(Independent Bottler)의 희귀 원액들. 공식 정식 수입 필증과 단일 캐스크 일련번호(Single Cask Number)를 보증하며, 전담 도슨트가 취향에 맞춘 위스키를 1:1로 큐레이션합니다. + 독립병입 위스키의 숙성 정보와 향미를 비교하며, 취향에 맞는 테이스팅 선택 방식을 살펴볼 수 있습니다.

      +

      안내: 이 페이지의 원장·인증 정보·가격·예약·구독은 예시입니다. 입력 정보는 저장·전송되지 않으며 실제 예약 또는 구독으로 이어지지 않습니다.

      -
      -
      -
      +
      +
      차링된 오크 배럴 상판 위 싱글 캐스크 위스키 보틀과 테이스팅 글라스 -
      -
      -
      +
      CASK #8821 · 58.4% ABV
      Signatory Vintage 1997 · Bottle 42 of 186
      -
      + +
      -
      +
      GORDON & MACPHAIL
      -
      1895년 설립 · 스코틀랜드 최고 권위 정식 수입
      +
      병입자 표기를 원장에 연결하는 예시
      SIGNATORY VINTAGE
      -
      언칠필터드 / 내추럴 컬러 캐스크 스트렝스 보증
      +
      숙성 조건과 도수 메타데이터 예시
      THE SCOTCH MALT WHISKY SOCIETY
      -
      SMWS 공식 파트너 베뉴 · 넘버링 큐레이션
      +
      캐스크 번호와 향미 기준의 연결 예시
      CADENHEAD'S
      1842년 설립, 스코틀랜드에서 가장 오래된 독립병입자 라인업
      +

      아래 병입자·수입 정보는 예시입니다. 실제 인증이나 입고 현황을 뜻하지 않습니다.

      -

      독립병입자 캐스크 실시간 보유 원장

      -

      모든 병은 단일 캐스크(Single Cask)에서 추출되어 병입 수량이 한정되어 있습니다. 필터로 원하는 향미 스펙을 검색하십시오.

      +

      독립병입 캐스크 목록

      +

      아래 병입 정보·수량·인증 표시는 예시입니다. 향미 기준으로 원하는 캐스크를 비교해 보세요.

      @@ -149,7 +146,7 @@ type="search" id="caskSearch" class="search-input" - placeholder="증류소명 or 캐스크 번호 검색..." + placeholder="증류소명 또는 캐스크 번호 검색" aria-label="캐스크 검색" />
      @@ -158,14 +155,14 @@

      순서라인업 구성ABV순서라인업 구성ABV
      - - - - - - - - + + + + + + + + @@ -177,7 +174,7 @@ - + @@ -187,7 +184,7 @@ - + @@ -197,7 +194,7 @@ - + @@ -207,7 +204,7 @@ - + @@ -217,7 +214,7 @@ - +
      캐스크 번호증류소 & 원액 명칭독립병입자 (Bottler)숙성 배럴 / 년수도수 (ABV)한정 수량향미 노트 요약인증 정보캐스크 번호증류소 & 원액 명칭독립병입자 (Bottler)숙성 배럴 / 년수도수 (ABV)한정 수량향미 노트 요약인증 정보
      54.2% 180 Btls 말린 무화과, 밀랍, 시나몬, 다크초콜릿
      #29.28157.8% 214 Btls 모닥불 연기, 바다 소금, 레몬 제스트, 피트 45ppm
      #93/4151.6% 142 Btls 열대 과일 잼, 가죽, 부드러운 유황, 정향
      #PX-8856.4% 260 Btls 스모크 베이컨, 건포도, 블랙베리, 훈제 파프리카
      #98/1258.1% 195 Btls 바닐라 커스터드, 구운 코코넛, 청사과, 후추
      @@ -262,12 +259,12 @@

      - 도슨트 프라이빗 세션 예약 신청 + 도슨트 프라이빗 세션 항목

      - @@ -276,11 +273,11 @@
      - +
      - @@ -291,21 +288,21 @@
      - +
      - +
      - +
      @@ -360,25 +357,28 @@ 신규 캐스크 입고 알림 & 인스타그램

      - 수량이 극소량인 독립병입자 캐스크 오프닝 소식을 이메일 뉴스레터로 가장 먼저 발송해 드립니다. + 신규 캐스크와 테이스팅 콘텐츠를 둘러보세요.

      +

      이메일은 이 화면에 저장되지 않으며 실제 구독으로 등록되지 않습니다.

      @@ -390,7 +390,7 @@

      - 공식 독립병입자 수입 보증서 + 병입 정보 예시

      @@ -409,9 +409,8 @@
      -

      캐스크 아카이브 · 서울 용산구 한남대로 27길 19 지하 1층

      -

      매일 18:00 – 02:00 (사전 예약제)

      -

      bottling@caskarchive.kr

      +

      캐스크 아카이브 · 독립병입 위스키 안내

      +

      이 페이지의 원장·가격·신청 흐름은 예시이며 입력 정보는 저장·전송되지 않습니다.

      @@ -458,7 +457,7 @@ const date = document.getElementById("bookingDate").value; const time = document.getElementById("bookingTime").value; const course = document.getElementById("bookingCourse").value; - alert(`[캐스크 아카이브] ${name}님의 1:1 위스키 도슨트 세션(코스 ${course})이 예약 접수되었습니다.\n일정: ${date} ${time}\n담당 도슨트가 당일 사전 안내 연락을 드립니다.`); + alert(`${name}님이 선택한 도슨트 세션(코스 ${course})을 확인했습니다.\n실제 예약은 접수되지 않았으며 입력 정보는 저장하거나 전송하지 않습니다.`); }); } @@ -471,7 +470,7 @@ alert("유효한 이메일 주소를 입력해 주십시오."); return; } - alert(`[캐스크 아카이브] ${email} 주소로 신규 독립병입자 캐스크 릴리즈 알림이 등록되었습니다.`); + alert(`${email} 주소는 이 화면에 저장되지 않으며 실제 구독으로 등록되지 않습니다.`); document.getElementById("newsEmail").value = ""; }); } diff --git a/apps/site/public/work/cask-archive/styles/fonts.css b/apps/site/public/work/cask-archive/styles/fonts.css new file mode 100644 index 0000000..f5234d6 --- /dev/null +++ b/apps/site/public/work/cask-archive/styles/fonts.css @@ -0,0 +1,15 @@ +@font-face { + font-family: "MaruBuri"; + src: url("../assets/fonts/MaruBuri-Regular.woff2") format("woff2"); + font-style: normal; + font-weight: 400; + font-display: swap; +} + +@font-face { + font-family: "MaruBuri"; + src: url("../assets/fonts/MaruBuri-SemiBold.woff2") format("woff2"); + font-style: normal; + font-weight: 600; + font-display: swap; +} diff --git a/apps/site/public/work/cask-archive/styles/main.css b/apps/site/public/work/cask-archive/styles/main.css index e596fce..a62dbff 100644 --- a/apps/site/public/work/cask-archive/styles/main.css +++ b/apps/site/public/work/cask-archive/styles/main.css @@ -1,4 +1,4 @@ -@import "./tokens.css"; +@import "./tokens.css?v=20260912all"; /* ========================================================================== 캐스크 아카이브 (CASK ARCHIVE) — 메인 스타일시트 SSOT @@ -266,7 +266,7 @@ button { .hero-grid { display: grid; - grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.95fr); + grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--space-7); align-items: center; } @@ -304,15 +304,8 @@ button { position: relative; } -.bezel-outer { - background: rgba(217, 155, 56, 0.06); - border: 1px solid var(--line); - padding: 6px; - border-radius: var(--radius-md); -} - .hero-frame { - border-radius: calc(var(--radius-md) - 4px); + margin: 0; overflow: hidden; border: 1px solid rgba(255, 255, 255, 0.08); box-shadow: 0 20px 48px -12px rgba(0, 0, 0, 0.7); @@ -321,17 +314,15 @@ button { .hero-frame img { width: 100%; - aspect-ratio: 4/3; + aspect-ratio: 4/5; object-fit: cover; display: block; } .hero-cask-tag { - margin-top: var(--space-2); - padding: 6px 12px; - background: var(--surface-raised); - border: 1px solid var(--line); - border-radius: var(--radius); + padding: var(--space-3) 0 0; + background: transparent; + border: 0; display: flex; justify-content: space-between; align-items: baseline; @@ -390,9 +381,9 @@ button { } .section-head { - text-align: center; - max-width: 680px; - margin-inline: auto; + text-align: left; + max-width: 48rem; + margin-inline: 0; margin-bottom: var(--space-6); } @@ -439,7 +430,7 @@ button { color: var(--ink-muted); font-size: 12px; font-weight: 600; - transition: all var(--dur-quick); + transition: background-color var(--dur-quick), border-color var(--dur-quick), color var(--dur-quick); } .filter-btn:hover { @@ -726,11 +717,14 @@ button { inset: 0; margin: auto; width: min(90vw, 480px); + max-height: calc(100dvh - (var(--space-4) * 2)); background: #141418; color: #f3f3f5; border: 1px solid rgba(217, 155, 56, 0.4); border-radius: var(--radius-sm); padding: var(--space-5); + overflow: auto; + overscroll-behavior: contain; box-shadow: 0 24px 64px rgba(0, 0, 0, 0.8); outline: none; } @@ -784,3 +778,60 @@ button { display: none; } } + +html:has(dialog[open]) { + overflow: hidden; +} + +/* 예약·원장 표면의 조작 여백과 키보드 상태를 토큰으로 맞춘다. */ +:where(a, button, input, select, textarea):focus-visible { + outline: 3px solid var(--accent); + outline-offset: 2px; +} + +.btn-amber, +.btn-outline, +.head-actions .btn, +.filter-btn, +.search-input, +.form-input, +.form-select, +.newsletter-form input { + min-height: var(--control-block); + padding-inline: var(--control-pad-inline); +} + +.ledger-table th, +.ledger-table td { + padding-inline: var(--control-pad-inline); +} + +.demo-notice { + max-width: 58ch; + margin-top: var(--space-4); + padding: var(--space-3) var(--space-4); + border-left: 3px solid var(--accent); + background: var(--accent-light); + color: var(--ink-muted); + font-size: var(--step--1); + line-height: 1.55; + word-break: keep-all; +} + +@media (max-width: 600px) { + .head-actions .btn { display: none; } + .hero-title { font-size: clamp(1.65rem, 7.8vw, 2.15rem); } + .hero-ctas { align-items: stretch; } + .hero-ctas > a { width: 100%; } + .course-header { align-items: flex-start; flex-direction: column; gap: var(--space-2); } + .docent-booking-form { padding: var(--space-5); } +} + +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { + animation-duration: 1ms !important; + animation-iteration-count: 1 !important; + scroll-behavior: auto !important; + transition-duration: 1ms !important; + } +} diff --git a/apps/site/public/work/cask-archive/styles/tokens.css b/apps/site/public/work/cask-archive/styles/tokens.css index 3c8b1a2..13a3b8d 100644 --- a/apps/site/public/work/cask-archive/styles/tokens.css +++ b/apps/site/public/work/cask-archive/styles/tokens.css @@ -64,8 +64,10 @@ --space-8: clamp(4.5rem, 3rem + 6vw, 9rem); /* 컨테이너 및 패딩 — 전체 쇼케이스 절대 통일 SSOT */ - --container: 1120px; + --container: clamp(70rem, 62vw, 85rem); --pad-inline: clamp(1.25rem, 1rem + 2.5vw, 4rem); + --control-block: 2.75rem; + --control-pad-inline: 0.875rem; /* 모션 */ --dur-quick: 180ms; diff --git a/apps/site/public/work/cheongon-care/assets/fonts/LICENSE.html b/apps/site/public/work/cheongon-care/assets/fonts/LICENSE.html new file mode 100644 index 0000000..571387d --- /dev/null +++ b/apps/site/public/work/cheongon-care/assets/fonts/LICENSE.html @@ -0,0 +1,169 @@ +네이버 나눔글꼴 라이선스안내 : 고객센터
      빈줄

          + + + +
          +
          +
          +
          +
          +

          네이버 나눔글꼴의 지적 재산권은 네이버와 네이버 문화재단에 있습니다.

          +

          ​

          +

          네이버 나눔글꼴은 개인 및 기업 사용자를 포함한 모든 사용자에게 무료로 제공되며 글꼴 자체를 유료로 판매하는 것을 제외한 상업적인 사용이 가능합니다.

          +

          ​

          +

          네이버 나눔글꼴은 본 저작권 안내와 라이선스 전문을 포함해서 다른 소프트웨어와 번들하거나 재배포 또는 판매가 가능하고 자유롭게 수정, 재배포하실 수 있습니다.

          +

          ​

          +

          네이버 나눔글꼴 라이선스 전문을 포함하기 어려울 경우, 나눔글꼴의 출처 표기를 권장합니다.

          +

          예) 이 페이지에는 네이버에서 제공한 나눔글꼴이 적용되어 있습니다.

          +

          ​

          +

          네이버 나눔글꼴을 사용한 인쇄물, 광고물(온라인 포함)의 이미지는 나눔글꼴 프로모션을 위해 활용될 수 있습니다.

          +

          ​

          +

          이를 원치 않는 사용자는 언제든지 당사에 요청하실 수 있습니다.

          +

          ​

          +

          정확한 사용 조건은 아래 네이버 나눔글꼴 라이선스 전문을 참고하시기 바랍니다.

          +

          ​

          +

          네이버 마루 부리 글꼴도 나눔 글꼴과 같은 오픈라이센스 폰트로 동일한 저작권 규정을 적용받습니다.

          +

          ​

          +

          ※ 참고해 주세요!

          +

          - 나눔글꼴 라이선스 전문의 한글은 이용자의 이해를 돕기 위해 영문 원본을 번역해 서비스하고 있으며, 법적 효력은 영문에 한합니다.

          +

          ​

          +

          1. 라이선스

          +

          Copyright (c) 2010, NAVER Corporation (https://www.navercorp.com/) with Reserved Font Name Nanum, Naver Nanum, NanumGothic, Naver NanumGothic, NanumMyeongjo, Naver NanumMyeongjo, NanumBrush, Naver NanumBrush, NanumPen, Naver NanumPen, Naver NanumGothicEco, NanumGothicEco, Naver NanumMyeongjoEco, NanumMyeongjoEco, Naver NanumGothicLight, NanumGothicLight, NanumBarunGothic, Naver NanumBarunGothic, NanumSquareRound, NanumBarunPen, MaruBuri, NanumSquareNeo

          +

          ​

          +

          This Font Software is licensed under the SIL Open Font License, Version 1.1.

          +

          ​

          +

          This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL

          +

          ​

          +

          SIL OPEN FONT LICENSE

          +

          Version 1.1 - 26 February 2007

          +

          ​

          +

          ‘나눔, 네이버 나눔, 나눔고딕, 네이버 나눔고딕, 나눔명조, 네이버 나눔명조, 나눔손글씨, 네이버 나눔손글씨, 나눔펜, 네이버 나눔펜, 네이버 나눔고딕에코, 나눔고딕에코, 네이버 나눔명조에코, 나눔명조에코, 네이버 나눔고딕라이트, 나눔고딕라이트, 나눔바른고딕, 네이버나눔바른고딕, 나눔스퀘어라운드, 나눔바른펜, 마루 부리, 나눔스퀘어네오’ 폰트명에 대해 NAVER(https://www.navercorp.com/)가 저작권을 소유하고 있습니다.

          +

          ​

          +

          본 폰트 소프트웨어는 SIL 오픈 폰트 라이선스 버전 1.1에 따라 라이선스 취득을 하였습니다.

          +

          ​

          +

          본 라이선스는 하단에 복사되었고 http://scripts.sil.org/OFL의 FAQ 란에서도 열람 가능합니다.

          +

          ​

          +

          SIL 오픈 폰트 라이선스

          +

          버전 1.1 (2007년 2월 26일)

          +

          ​

          +

          [DEFINITIONS (정의)]

          +

          ""Font Software"" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.

          +

          ​

          +

          ""Reserved Font Name"" refers to any names specified as such after the copyright statement(s).

          +

          ​

          +

          ""Original Version"" refers to the collection of Font Software components as distributed by the Copyright Holder(s).

          +

          ​

          +

          ""Modified Version"" refers to any derivative made by adding to, deleting, or substituting in part or in whole any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.‘

          +

          ​

          +

          ""Author"" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.

          +

          ​

          +

          ‘폰트 소프트웨어’는 본 라이선스에 입거해 저작권자가 배포하고 명확하게 같은 표시가 된 파일들의 집합을 뜻하며, 여기에는 소스 파일, 빌드 스크립트와 문서가 이에 포함됩니다.

          +

          ​

          +

          ‘저작권이 있는 폰트명’은 저작권 정책에 따라서 지정된 이름을 말합니다.

          +

          ​

          +

          ‘원본’은 저작권자가 배포한 폰트 소프트웨어 구성요소를 의미합니다.

          +

          ​

          +

          ‘수정본’은 포맷의 변경이나 폰트 소프트웨어를 새로운 환경에 포팅 시켜, 원본의 일부 혹은 전체에 추가, 삭제 대체해 만든 파생 저작물을 의미합니다.

          +

          ​

          +

          ‘저자’는 폰트 소프트웨어에 기여한 디자이너, 엔지니어, 프로그래머, 기술 전문가 등을 의미합니다.

          +

          ​

          +

          2. PREAMBLE (전문)

          +

          The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.

          +

          ​

          +

          The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works.

          +

          ​

          +

          The fonts and derivatives, however, cannot be released under any other type of license.

          +

          ​

          +

          The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives.

          +

          ​

          +

          본 폰트 라이선스를 오픈하는 것은(이하 OFL)는 전 세계 폰트 개발 프로젝트를 지원하고 학계와 언어 관련 학계의 폰트 개발을 위한 연구를 지지하기 위해서인 동시에, 폰트 제휴를 통해 폰트가 공유되고 개선될 수 있는 자유롭게 개방된 환경을 만들기 위해서입니다.

          +

          ​

          +

          OFL은 라이선스를 취득한 폰트가 그 자체로 판매되지 않는 한 자유롭게 사용, 연구, 수정, 재배포 하는 것을 허가합니다.

          +

          ​

          +

          수정된 폰트를 포함한 폰트는 저작권 명이 사용되지 않는 한 기타 소프트웨어와 함께 묶이거나 삽입, 재배포 할 수 있습니다.

          +

          ​

          +

          단 폰트와 수정된 폰트는 기타 다른 라이선스에 포함되어 배포될 수는 없습니다.

          +

          ​

          +

          이 라이선스 하에 있기 위한 폰트에 대한 요구사항은 본 폰트나 수정본을 사용하여 제작된 어떠한 문서에도 적용되지 않습니다.

          +

          ​

          +

          3. PERMISSION & CONDITIONS (허가 및 조건)

          +

          Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:

          +

          ​

          +

          본 폰트 소프트웨어를 사용하도록 허가받은 개인/기업/단체 누구라도 다음 명시된 조건에 따라 폰트 소프트웨어의 수정 혹은 수정되지 않은 복사본을 무료로 사용, 연구, 복사, 통합, 삽입, 수정, 재배포할 수 있도록 허가합니다.

          +

          ​

          +

          1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.

          +

          ​

          +

          원본이나 수정본의 폰트 소프트웨어 혹은 개별 구성요소인 폰트 자체가 판매되어서는 안됩니다.

          +

          ​

          +

          2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license.

          +

          ​

          +

          These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.

          +

          ​

          +

          본 폰트 소프트웨어의 원본 혹은 수정본은 상기 저작권 안내와 본 라이선스에 대한 내용을 포함하는 경우에는 다른 소프트웨어와 함께 묶이거나 재배포 혹은 판매가 가능합니다.

          +

          ​

          +

          이는 독립 텍스트 파일과 가독성이 있는 헤더 혹은 유저가 용이하게 열람 가능한 이상 텍스트 파일 혹은 이진 파일 내 기계가 읽을 수 있는 메타데이터 형태를 모두 의미합니다.

          +

          ​

          +

          3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder.

          +

          ​

          +

          This restriction only applies to the primary font name as presented to the users.

          +

          ​

          +

          본 폰트 소프트웨어의 어떠한 수정본도 동일한 저작권자가 명시적 허가서를 부여하지 않는 한 저작권이 있는 폰트명을 사용해서는 안 됩니다.

          +

          ​

          +

          본 제한 사항은 유저들에게 제공된 기존 폰트명을 뜻합니다.

          +

          ​

          +

          4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.

          +

          ​

          +

          본 폰트 소프트웨어의 저작권자 혹은 저자의 이름은 그들의 명시적 서면 허가가 있거나 또는 그들의 공헌을 인정하기 위한 경우를 제외하고는 수정본에 대한 사용을 유도, 추천 혹은 광고하기 위한 목적으로 사용할 수 없습니다.

          +

          ​

          +

          5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed any other license.

          +

          ​

          +

          The requirement for fonts to remain under this license does not apply to any document created using the Font Software.

          +

          ​

          +

          본 폰트 소프트웨어는 전체나 부분, 혹은 수정 여부에 상관없이 본 라이선스 하에 배포가 되어야 하며 기타 다른 라이선스 하에서는 배포를 할 수 없습니다.

          +

          ​

          +

          폰트에 대한 요구 조건은 이 라이선스 하에서만 유효하며 이 라이선스 하에 있기 위한 폰트에 대한 요구사항은 본 폰트 소프트웨어를 사용해 제작한 어떠한 문서에도 적용되지 않습니다.

          +

          ​

          +

          4. TERMINATION (계약의 종료)

          +

          This license becomes null and void if any of the above conditions are not met.

          +

          ​

          +

          본 라이선스는 상기 조건 중 일부라도 부합되지 않으면 무효가 될 수 있습니다.

          +

          ​

          +

          5. DISCLAIMER (면책조항)

          +

          THE FONT SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT.

          +

          ​

          +

          IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.

          +

          ​

          +

          본 폰트 소프트웨어는 저작권, 특허권, 상표권 및 기타 권리의 비침해성과 특정 목적에의 적합성 포함한 명시적, 묵시적인 어떠한 종류의 보증 없이 “있는 그대로” 제공됩니다.

          +

          ​

          +

          어떠한 경우에도 저작권자는 본 폰트 소프트웨어의 사용 또는 이의 사용 불가, 그밖에 폰트 소프트웨어의 취급과 관련하여 발생하는 모든 계약, 불법행위 혹은 다른 일로 하여금 발생하는 일반적, 특수적, 간접적, 부차적 혹은 필연적 손해를 포함하는 소송, 손해, 혹은 기타 책임에 대한 의무를 가지지 않습니다.

          + +
          +
          +
          + +
          +
          만족도 평가
        \ No newline at end of file diff --git a/apps/site/public/work/cheongon-care/assets/fonts/MaruBuri-Regular.woff2 b/apps/site/public/work/cheongon-care/assets/fonts/MaruBuri-Regular.woff2 new file mode 100644 index 0000000..3bc205f Binary files /dev/null and b/apps/site/public/work/cheongon-care/assets/fonts/MaruBuri-Regular.woff2 differ diff --git a/apps/site/public/work/cheongon-care/assets/fonts/MaruBuri-SemiBold.woff2 b/apps/site/public/work/cheongon-care/assets/fonts/MaruBuri-SemiBold.woff2 new file mode 100644 index 0000000..be593a5 Binary files /dev/null and b/apps/site/public/work/cheongon-care/assets/fonts/MaruBuri-SemiBold.woff2 differ diff --git a/apps/site/public/work/cheongon-care/assets/fonts/SOURCES.md b/apps/site/public/work/cheongon-care/assets/fonts/SOURCES.md new file mode 100644 index 0000000..66d2c89 --- /dev/null +++ b/apps/site/public/work/cheongon-care/assets/fonts/SOURCES.md @@ -0,0 +1,13 @@ +# MaruBuri source record + +Downloaded 2026-09-12 from the official NAVER Hangeul static host. The files are retained unchanged: no conversion or subsetting was performed. + +| File | Official URL | HTTP content type | Size | SHA-256 | +| --- | --- | --- | --- | --- | +| `MaruBuri-Regular.woff2` | https://hangeul.pstatic.net/hangeul_static/webfont/MaruBuri/MaruBuri-Regular.woff2 | `font/woff2` | 433776 bytes | `4CF1341CF2F23FB3E263712DFDE1D8F25EEDCC328B696A2E5A2C8ADD55E5C17B` | +| `MaruBuri-SemiBold.woff2` | https://hangeul.pstatic.net/hangeul_static/webfont/MaruBuri/MaruBuri-SemiBold.woff2 | `font/woff2` | 466108 bytes | `7AEF4862FA3219B0A7DEB6746E27116A38C4069F4424EB51EDF103B29795F5C2` | + +- Official stylesheet checked: https://hangeul.pstatic.net/hangeul_static/css/maru-buri.css +- Official NAVER license page saved verbatim as `LICENSE.html`: https://help.naver.com/service/11029/contents/18088?lang=ko&osType=PC +- `LICENSE.html` SHA-256: `8538F7921744D5E040F603BC301465EFBD038F1054D0754B7508DE3286452EC3` +- The saved official page includes the NAVER copyright notice and the SIL Open Font License 1.1 text for MaruBuri. diff --git a/apps/site/public/work/cheongon-care/design.md b/apps/site/public/work/cheongon-care/design.md new file mode 100644 index 0000000..7529aa7 --- /dev/null +++ b/apps/site/public/work/cheongon-care/design.md @@ -0,0 +1,17 @@ +# 청온 케어 — 디자인 결정 기록 + +## 관찰과 방향 + +- 관찰: 기존 첫 화면은 카드 안의 사진과 떠 있는 수치 배지가 서비스 범위보다 먼저 읽혔다. +- 원리 적용 범위: 소개와 견적 행동은 왼쪽 읽기 폭에, 생활 공간 사진과 32개 검수 항목 예시는 오른쪽 한 장면에 둔다. 견적은 입력 작업표와 합계 명세를 분리한다. +- 결정: 이중 프레임·떠 있는 배지를 제거하고 사진 캡션으로 검수 항목의 맥락을 연결했다. 성능 수치·인증·의학적 표현은 근거가 없으므로 작업표에 기록할 확인 절차로 바꿨다. +- 기각 조건: 사진이 견적 행동을 밀거나 작은 폭에서 입력과 합계가 동시에 읽히지 않으면 1열 순서와 간격을 다시 조정한다. + +## 토큰과 검증 + +- 타입: `MaruBuri` 로컬 400·600은 제목 역할, Pretendard는 본문·입력 역할이다. 본문은 `--step-0`, 보조 기록은 `--step--1`을 유지한다. +- 색: 기존 청록 `--accent`, 밝은 표면과 선 토큰을 유지한다. 청록은 상태·행동과 검수 표시에만 쓴다. +- 구도: 넓은 화면은 5:7 소개/사진, 견적은 입력/합계 두 열이며 860px 이하에서는 한 열이다. +- `verify-final` 18개 묶음은 16개가 즉시 통과했다. 전체 묶음의 invariant·visual 검사는 Gaon·Dure를 대상으로 하며, 나머지 2개는 수정 뒤 release 독립 재실행에서 ALL PASS·ALL MATCH였다. +- root는 28개 모바일, 21개 데스크톱, 7개 하위 경로와 30개 앱 상태를 직접 검토해 수용했다. stress 112건은 hard failure 0이며, 가로 넘침 4건은 targeted fix 뒤 390px 재측정에서 0이다. +- 이 기록은 렌더·계약 범위의 현재 결과다. 모든 폭·키보드 경로·인쇄 등 개별 기능을 완전 재실행했다는 뜻이 아니며, 참여자 과업 효과도 미측정이다. diff --git a/apps/site/public/work/cheongon-care/index.html b/apps/site/public/work/cheongon-care/index.html index ade9e20..e6f8e79 100644 --- a/apps/site/public/work/cheongon-care/index.html +++ b/apps/site/public/work/cheongon-care/index.html @@ -3,10 +3,10 @@ - 청온 케어 · 프리미엄 주거·오피스 전문 위생 케어 & 관제 콘솔 + 청온 케어 · 프리미엄 주거·오피스 위생 케어 안내 @@ -24,7 +24,8 @@ rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap" /> - + +
        @@ -76,43 +77,38 @@
        -
        -
        - 정밀 입주 케어가 완료된 미니멀한 프리미엄 주거 거실 전경 -
        -
        -
        - 32 Point - 마스터 클리너
        정밀 검수 체크리스트
        -
        +
        + 정돈된 주거 공간의 거실 전경 +
        주거 공간 케어 예시 · 현장에서는 32개 검수 항목을 확인하는 흐름을 표시합니다.
        +
        @@ -121,8 +117,9 @@
        -

        투명한 정찰제 실시간 견적 산정

        -

        추가금 없는 명확한 기준. 공간 면적과 맞춤 옵션을 선택하시면 즉시 예상 금액이 산출됩니다.

        +

        견적 작업표

        +

        항목별 예상 견적

        +

        공간 면적과 선택 항목을 기준으로 예상 금액의 구성 방식을 확인합니다.

        @@ -153,6 +150,7 @@
        @@ -309,27 +313,27 @@
        -

        전문 위생 장비 및 검수 스펙

        -

        가정용 장비가 아닌 독일 카처 정품 산업용 위생 기기를 전 현장에 투입합니다.

        +

        작업 장비와 검수 기록

        +

        현장에서 확인할 장비·필터·제품·마감 항목을 작업표에 표시하는 예시입니다.

        - 고온 스팀 압력 - Kärcher SG 4/4 (4.0 bar · 160℃) + 장비 기록 + 사용 장비와 설정값을 작업표에 표시
        - 미세먼지 집진 등급 - HEPA H14 (0.3㎛ 99.995% 포집) + 필터 확인 + 필터 종류와 교체 상태를 현장에서 확인
        - 사용 세제 인증 - ECOCERT 100% 생분해 식물성 + 사용 제품 + 제품명과 적용 표면을 작업표에 기록
        - 포름알데히드 저감 - 한국화학융합시험연구원 인증 94.2% + 마감 확인 + 환기·표면 상태를 검수 항목으로 확인
        @@ -341,8 +345,8 @@ height="600" loading="lazy" /> - 정밀 장비 규격 - QC 완결 보증 + 작업 장비 예시 + 검수 항목 확인
        @@ -350,16 +354,17 @@ -
        +
        -
        배차 관제 콘솔
        -

        실시간 배차 및 현장 관제 현황

        +
        운영 현황
        +

        오늘의 케어 현황

        +

        아래 접수·배차 정보는 운영 화면 예시입니다. 실제 고객 정보나 접수 내역이 아닙니다.

        @@ -386,7 +391,7 @@
        - 실시간 예약 및 케어 원장 (Live Ledger) + 접수·배차 현황
        @@ -399,14 +404,14 @@ - - - - - - - - + + + + + + + + @@ -418,7 +423,7 @@ - + @@ -428,7 +433,7 @@ - + @@ -438,7 +443,7 @@ - +
        접수번호고객명 / 연락처공간 / 면적현장 주소견적액배정 팀장상태조치접수번호고객명 / 연락처공간 / 면적현장 주소견적액배정 팀장상태조치
        432,000원 김정온 마스터 신규 접수
        #CO-2026-0818520,000원 박준호 팀장 (2팀) 스팀 케어 중
        #CO-2026-0817841,000원 최수진 닥터 (1팀) 검수 승인 완료
        @@ -458,23 +463,22 @@
      • 02. 창틀 상하좌우 틈새 시멘트 가루 및 찌든때 제거
      • 03. 싱크대 하부 걸레받이 전면 탈거 및 분진 집진
      • 04. 가스레인지/인덕션 상판 및 후드 필터 기름때 고온 스팀 분해
      • -
      • 05. 욕실 벽타일 메지 및 배수구 트랩 고온 살균 세척
      • +
      • 05. 욕실 벽타일 메지 및 배수구 트랩 스팀 작업 확인
      • 06. 수납장 모든 서랍 완전 탈거 후 레일 틈새 분진 청소
      • -
      • 07. 베란다 및 다용도실 바닥 타일 약알칼리 세정
      • -
      • 08. 전 실 편백 피톤치드 훈증 및 공기질 측정기 수치 확인
      • +
      • 07. 베란다 및 다용도실 바닥 타일 세정 작업 확인
      • +
      • 08. 전 실 환기와 마감 상태 확인
      • - +
        -

        청온 케어 · 서울 마포구 마포대로 109 청온랩 4층

        -

        연중무휴 08:00 – 20:00 (사전 예약제)

        -

        care@cheongon.kr

        +

        청온 케어 · 위생 케어 안내

        +

        이 페이지의 가격·접수 정보는 예시이며 입력 정보는 저장·전송되지 않습니다.

        @@ -569,9 +573,9 @@ let submissionCount = 6; btnSubmit.addEventListener("click", () => { - const name = document.getElementById("clientName").value || "고객님"; - const phone = document.getElementById("clientPhone").value || "010-0000-0000"; - const address = document.getElementById("clientAddress").value || "서울시 현장 주소"; + const name = document.getElementById("clientName").value || "이름 미입력"; + const phone = document.getElementById("clientPhone").value || "입력 없음"; + const address = document.getElementById("clientAddress").value || "입력 없음"; const pyeong = pyeongSlider.value; const totalStr = sumTotal.textContent; @@ -593,7 +597,7 @@ `; tableBody.insertBefore(newRow, tableBody.firstChild); - alert(`[청온 케어] ${name}님의 견적(${totalStr}) 신청이 성공적으로 접수되었습니다.\n관리자 콘솔에 실시간 등록되었습니다.`); + alert(`${name}님의 예상 견적은 ${totalStr}입니다.\n실제 견적·신청은 진행되지 않았으며 입력 정보는 저장하거나 전송하지 않습니다.`); }); // 모달 열기 diff --git a/apps/site/public/work/cheongon-care/protocol/index.html b/apps/site/public/work/cheongon-care/protocol/index.html index e708b0d..a23056c 100644 --- a/apps/site/public/work/cheongon-care/protocol/index.html +++ b/apps/site/public/work/cheongon-care/protocol/index.html @@ -3,16 +3,13 @@ - 임상 6단계 위생 프로토콜 & 한남 케이스 리포트 — 청온 케어 - + 6단계 위생 케어 절차 · 예시 리포트 — 청온 케어 + - + - - + + + +
        @@ -153,28 +152,29 @@
        -

        HOSPITAL-GRADE SANITATION STANDARDS

        -

        단순한 청소를 넘어
        병원급 6단계 임상 위생 프로토콜

        +

        CARE CHECKLIST EXAMPLE

        +

        6단계 위생 케어 절차

        - 독일 카처 산업용 스팀과 H14 헤파 필터 흡진, ATP 생체 오염도 계측을 통해 인체에 무해한 안심 공간을 과학적으로 보증합니다. + 현장 장비, 필터, 표면, 마감 상태를 작업표에 기록하는 절차와 확인 항목을 소개합니다.

        +

        안내: 아래 절차와 측정 수치는 예시입니다. 실제 시공 결과를 보장하거나 예약을 접수하지 않습니다.

        Steam Temp
        -
        160℃ High-Temp
        +
        현장 장비 설정 기록
        Filtration
        -
        0.3㎛ HEPA H14 (99.995%)
        +
        필터 종류·상태 확인
        Detergent
        -
        ECOCERT 100% 식물성
        +
        사용 제품·표면 기록
        QC Points
        @@ -186,49 +186,48 @@
        완벽하게 정돈되고 살균된 프리미엄 주거 인테리어 공간
        - 나인원한남 86평형 · 6단계 정밀 프로토콜 시공 완료 + 주거 공간 · 6단계 절차 예시
        - +
        -
        +
        ATP 생체 오염도 측정기 계측 화면 (12 RLU)
        -
        ATP 데이터 검증
        +
        검수 기록 표시 예시

        - 나인원한남 86평형
        - ATP 생체 오염도 99.1% 저감 리포트 + 주거 공간 예시
        + 점검값 기록 방식

        - 실제 한남동 나인원한남 입주 청소 현장에서 주방 싱크대 상판 및 욕실 수전 부위의 미생물 오염도(ATP RLU)를 측정한 결과입니다. - 160℃ 고온 스팀과 에코서트 효소 분해 세정 후 병원 무균실 기준(30 RLU 이하)을 상회하는 12 RLU 수준으로 완벽하게 저감되었습니다. + 아래 값은 점검 기록이 표시되는 방식을 설명하기 위한 예시입니다. 실제 현장 측정값이나 시공 결과를 뜻하지 않습니다.

        -
        시공 전 (BEFORE)
        -
        1,420 RLU
        -
        심각한 미세 세균 번식
        +
        점검 전 기록
        +
        기록값 A
        +
        확인할 항목 표시 예시
        -
        시공 후 (AFTER)
        -
        12 RLU
        -
        병원 수술실 기준 패스 (99.1% 저감)
        +
        점검 후 기록
        +
        기록값 B
        +
        확인 완료 표시 예시
        @@ -239,16 +238,16 @@
        단계별 시공 절차

        - 청온 케어 임상 6단계 시공 체계 + 청온 케어 6단계 검수 절차 예시

        STEP 01
        -

        H14 헤파 필터 건식 초미세 흡진

        +

        필터 흡진 작업 확인

        - 벽면 실크벽지 미세 분진, 천장 우물 몰딩, 조명 레일 내부의 0.3㎛ 부유 입자를 99.995% 집진하여 공기 중 재비산을 완벽 차단합니다. + 벽면, 천장 몰딩, 조명 레일의 작업 범위를 확인하고 흡진 작업 여부를 작업표에 기록합니다.

        @@ -256,9 +255,9 @@
        STEP 02
        -

        160℃ 4.0bar 고온 스팀 살균

        +

        스팀 장비 설정 확인

        - 배수구 유가, 변기 틈새, 주방 후드 필터에 화학 세제 없이 4.0bar 고압 증기를 분사하여 기름때를 녹이고 99.9% 멸균합니다. + 배수구, 욕실 틈새, 주방 후드처럼 확인이 필요한 면을 구분하고 사용 장비 설정을 남깁니다.

        @@ -266,9 +265,9 @@
        STEP 03
        -

        약알칼리 에코서트 친환경 효소 분해

        +

        표면별 세정 확인

        - 원목 마루 및 천연 대리석 자재에 손상을 주지 않는 100% 생분해성 식물 세정제를 도포하여 찌든 산화 피막을 안전하게 중화합니다. + 바닥과 석재의 재질을 확인한 뒤 사용 제품과 적용 범위를 작업표에 표시합니다.

        @@ -278,7 +277,7 @@

        서랍장·걸레받이 전면 탈거 정밀 세척

        - 싱크대 하부 걸레받이와 수납장 레일을 전량 분리 탈거하여, 보이지 않는 시공 톱밥 및 유해 분진을 내측까지 완전 제거합니다. + 싱크대 하부와 수납장 레일의 접근 가능 여부를 확인하고, 분리 작업 범위를 기록합니다.

        @@ -286,9 +285,9 @@
        STEP 05
        -

        제주 편백 피톤치드 연무 훈증

        +

        환기와 마감 확인

        - 새집증후군 유발 물질인 포름알데히드 및 휘발성유기화합물(VOCs)을 중화하고 실내 숲속 공기질을 복원합니다. + 환기와 마감 상태를 확인하고, 향·마감 제품을 사용했다면 제품명과 적용 범위를 기록합니다.

        @@ -296,9 +295,9 @@
        STEP 06
        -

        32개 항목 마스터 닥터 1:1 검수 및 디지털 인증

        +

        32개 항목 현장 검수 확인

        - 배차 현장 팀장과 고객이 함께 32개 정밀 체크리스트를 1:1 대조하고, 모바일 리포트를 발행하여 최종 승인합니다. + 현장 담당자와 의뢰자가 32개 체크리스트를 함께 확인하는 흐름을 예시로 표시합니다.

        @@ -310,7 +309,7 @@
        독일 카처 4.0bar 정밀 스팀 위생 장비와 멸균 키트
        @@ -324,10 +323,10 @@ 우리 집 공간의 정찰제 견적을 확인하세요

        - 추가금 없는 평당 11,000원 명확한 기준. 1분 만에 실시간 견적 산출이 가능합니다. + 선택 항목을 기준으로 예상 금액을 확인할 수 있습니다. 실제 견적이나 신청은 진행되지 않습니다.

        - - 실시간 정찰제 견적 계산하기 → + + 항목별 예상 견적 보기 →
        @@ -336,9 +335,8 @@
        -

        청온 케어 · 서울 마포구 마포대로 109 청온랩 4층

        -

        연중무휴 08:00 – 20:00 (사전 예약제)

        -

        care@cheongon.kr

        +

        청온 케어 · 위생 케어 안내

        +

        이 페이지의 절차와 수치는 예시이며 실제 예약은 접수되지 않습니다.

        diff --git a/apps/site/public/work/cheongon-care/styles/fonts.css b/apps/site/public/work/cheongon-care/styles/fonts.css new file mode 100644 index 0000000..f5234d6 --- /dev/null +++ b/apps/site/public/work/cheongon-care/styles/fonts.css @@ -0,0 +1,15 @@ +@font-face { + font-family: "MaruBuri"; + src: url("../assets/fonts/MaruBuri-Regular.woff2") format("woff2"); + font-style: normal; + font-weight: 400; + font-display: swap; +} + +@font-face { + font-family: "MaruBuri"; + src: url("../assets/fonts/MaruBuri-SemiBold.woff2") format("woff2"); + font-style: normal; + font-weight: 600; + font-display: swap; +} diff --git a/apps/site/public/work/cheongon-care/styles/main.css b/apps/site/public/work/cheongon-care/styles/main.css index 8a4f2e3..25f961f 100644 --- a/apps/site/public/work/cheongon-care/styles/main.css +++ b/apps/site/public/work/cheongon-care/styles/main.css @@ -1,4 +1,4 @@ -@import "./tokens.css"; +@import "./tokens.css?v=20260912all"; /* ========================================================================== 청온 케어 (CHEONG-ON CARE) — 메인 스타일시트 SSOT @@ -193,7 +193,7 @@ button { display: inline-flex; align-items: center; gap: 5px; - transition: all var(--dur-quick); + transition: background-color var(--dur-quick), color var(--dur-quick), box-shadow var(--dur-quick); white-space: nowrap; } @@ -296,7 +296,7 @@ button { .hero-grid { display: grid; - grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.95fr); + grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--space-7); align-items: center; } @@ -351,41 +351,20 @@ button { position: relative; } -.bezel-outer { - background: rgba(15, 118, 110, 0.05); - border: 1px solid var(--line); - padding: 6px; - border-radius: var(--radius-md); -} - .hero-frame { - border-radius: calc(var(--radius-md) - 4px); - overflow: hidden; + margin: 0; border: 1px solid var(--line); - box-shadow: 0 16px 40px -12px rgba(0, 0, 0, 0.08); background: #ffffff; } .hero-frame img { width: 100%; - aspect-ratio: 4/3; + aspect-ratio: 5/4; object-fit: cover; display: block; } -.hero-stat-floating { - position: absolute; - bottom: -14px; - left: 16px; - background: var(--surface-raised); - border: 1px solid var(--line); - border-radius: var(--radius-sm); - padding: 8px 14px; - box-shadow: 0 8px 24px -4px rgba(0, 0, 0, 0.08); - display: flex; - align-items: baseline; - gap: var(--space-2); -} +.hero-frame figcaption { padding: var(--space-3) var(--space-4); border-top: 1px solid var(--line); color: var(--ink-muted); font-size: var(--step--1); line-height: 1.55; } /* ── 투명 정찰제 실시간 견적 산정 섹션 ── */ .calculator-section { @@ -393,10 +372,10 @@ button { border-top: 1px solid var(--line); } -.section-head { - text-align: center; - max-width: 680px; - margin-inline: auto; +.calc-section .section-head { + text-align: left; + max-width: 48rem; + margin-inline: 0; margin-bottom: var(--space-6); } @@ -463,7 +442,7 @@ button { font-weight: 600; font-size: var(--step--1); text-align: center; - transition: all var(--dur-quick); + transition: background-color var(--dur-quick), border-color var(--dur-quick), color var(--dur-quick); white-space: normal; word-break: keep-all; } @@ -513,7 +492,7 @@ button { font-size: var(--step--1); color: var(--ink-muted); cursor: pointer; - transition: all var(--dur-quick); + transition: background-color var(--dur-quick), border-color var(--dur-quick), color var(--dur-quick); } .addon-label:has(input:checked) { @@ -850,7 +829,7 @@ button { font-weight: 600; background: var(--surface); cursor: pointer; - transition: all var(--dur-quick); + transition: border-color var(--dur-quick), color var(--dur-quick); } .action-btn:hover { @@ -864,10 +843,13 @@ button { inset: 0; margin: auto; width: min(90vw, 560px); + max-height: calc(100dvh - (var(--space-4) * 2)); background: #ffffff; border: 1px solid var(--line); border-radius: var(--radius-md); padding: var(--space-5); + overflow: auto; + overscroll-behavior: contain; box-shadow: 0 24px 64px rgba(0, 0, 0, 0.15); outline: none; } @@ -923,3 +905,75 @@ button { font-size: 11px; } } + +html:has(dialog[open]) { + overflow: hidden; +} + +/* 접근성·초광폭 프리플라이트: 컨트롤의 독립성과 실제 표면 여백을 같은 토큰으로 유지한다. */ +:where(a, button, input, select, textarea):focus-visible { + outline: 3px solid var(--accent); + outline-offset: 2px; +} + +.btn-primary, +.btn-outline, +.calc-submit, +.type-btn, +.addon-label, +.action-btn, +.filter-tab, +.mode-btn, +.head-actions .btn, +input:not([type="checkbox"]), +select, +textarea { + min-height: var(--control-block); +} + +.btn-primary, +.btn-outline, +.calc-submit, +.type-btn, +.addon-label, +.action-btn, +.filter-tab, +.mode-btn, +.head-actions .btn { + padding-inline: var(--control-pad-inline); +} + +.form-label + input, +.form-label + select, +.form-label + textarea { + padding-inline: var(--control-pad-inline); +} + +.demo-notice { + max-width: 58ch; + margin-top: var(--space-4); + padding: var(--space-3) var(--space-4); + border-left: 3px solid var(--accent); + background: var(--accent-light); + color: var(--ink-muted); + font-size: var(--step--1); + line-height: 1.55; + word-break: keep-all; +} + +@media (max-width: 600px) { + .head-actions .client-only-btn { display: none; } + .hero-ctas { align-items: stretch; } + .hero-ctas .btn-primary { width: 100%; } + .hero-title { font-size: clamp(1.65rem, 7.8vw, 2.15rem); } + .hero-trust { align-items: flex-start; } +} + +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { + animation-duration: 1ms !important; + animation-iteration-count: 1 !important; + scroll-behavior: auto !important; + transition-duration: 1ms !important; + } +} diff --git a/apps/site/public/work/cheongon-care/styles/tokens.css b/apps/site/public/work/cheongon-care/styles/tokens.css index 51a8924..6f8fedc 100644 --- a/apps/site/public/work/cheongon-care/styles/tokens.css +++ b/apps/site/public/work/cheongon-care/styles/tokens.css @@ -1,7 +1,7 @@ /* ========================================================================== 청온 케어 (CHEONG-ON CARE) — 디자인 토큰 SSOT 프리셋: ledger-console + swiss-minimal - 컨셉: 임상 수준의 위생 프로토콜과 정직한 정찰제 — 공간의 숨결을 되돌리는 케어 + 컨셉: 현장 검수 절차와 정직한 정찰제 — 공간의 상태를 기록하는 케어 단일 강조색: 에메랄드 틸 (#0D9488) ========================================================================== */ @@ -42,8 +42,8 @@ --line-inverse: #334155; /* 단일 강조색 (에메랄드 틸) */ - --accent: #0d9488; - --accent-hover: #0f766e; + --accent: #0f766e; + --accent-hover: #115e59; --accent-light: #f0fdfa; --accent-surface: #ccfbf1; --accent-ink: #ffffff; @@ -63,8 +63,10 @@ --space-8: clamp(4.5rem, 3rem + 6vw, 9rem); /* 컨테이너 및 패딩 — 전체 쇼케이스 절대 통일 SSOT */ - --container: 1120px; + --container: clamp(70rem, 62vw, 85rem); --pad-inline: clamp(1.25rem, 1rem + 2.5vw, 4rem); + --control-block: 2.75rem; + --control-pad-inline: 0.875rem; /* 모션 */ --dur-quick: 180ms; diff --git a/apps/site/public/work/dure-enrollment/design.md b/apps/site/public/work/dure-enrollment/design.md new file mode 100644 index 0000000..682acbf --- /dev/null +++ b/apps/site/public/work/dure-enrollment/design.md @@ -0,0 +1,24 @@ +# 두레대학 수강신청 디자인 기록 + +## 브리프 + +- 무엇을: 과목 목록과 내 시간표를 한 작업면에서 비교하며 신청하는 화면. +- 누구에게: 과목명·요일·학점·여석과 신청 결과를 대조하는 학생. +- 제약: 과목·정원 데이터, 신청 계산, 취소·실행취소, 단축키, 인쇄와 모바일 하단 내비를 보존한다. + +## 판단 기준 + +| 축 | 질문 | 적용 | +| --- | --- | --- | +| Warde · 정보 전달 | 필터 뒤의 과목 목록과 시간표가 한 작업 흐름으로 읽히는가 | 공통 작업면과 한 단계 낮춘 중복 테두리 | +| Ruder · 비교 변수 | 과목명·시간·학점·여석을 같은 시선 흐름에서 비교하는가 | 행 메타와 우측 학점·여석의 정렬, tabular figures | +| Albers · 상태 맥락 | 관심·신청·여석 부족 상태가 텍스트와 색으로 함께 구분되는가 | 상태 텍스트를 남기고 색은 상태 보조로만 사용 | + +Warde, Ruder, Albers는 정보 전달·비교 변수·상태 맥락을 검토하는 참고 질문이며 인과나 성능 법칙이 아니다. + +## 역할 토큰과 검증 + +- `--workspace-radius`, `--workspace-rule`, `--workspace-body-size`, `--workspace-meta-size`가 작업면과 정보 위계를 관리한다. +- `verify-final` 18개 묶음은 16개가 즉시 통과했다. 전체 묶음의 invariant·visual 검사는 Gaon·Dure를 대상으로 하며, 나머지 2개는 수정 뒤 release 독립 재실행에서 ALL PASS·ALL MATCH였다. +- root는 28개 모바일, 21개 데스크톱, 7개 하위 경로와 30개 앱 상태를 직접 검토해 수용했다. stress 112건은 hard failure 0이며, 가로 넘침 4건은 targeted fix 뒤 390px 재측정에서 0이다. +- 이 기록은 렌더·계약 범위의 현재 결과다. 모든 폭·키보드 경로·인쇄 등 개별 기능을 완전 재실행했다는 뜻이 아니며, 참여자 과업 효과도 미측정이다. diff --git a/apps/site/public/work/dure-enrollment/index.html b/apps/site/public/work/dure-enrollment/index.html index d2c3a22..20673b3 100644 --- a/apps/site/public/work/dure-enrollment/index.html +++ b/apps/site/public/work/dure-enrollment/index.html @@ -17,7 +17,7 @@ @@ -35,7 +35,7 @@ rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&family=IBM+Plex+Sans+KR:wght@400;500;600&family=Noto+Serif+KR:wght@500;600&display=swap" /> - +

        2026학년도 1학기 과목

        -

        과목을 누르면 강의계획과 신청 버튼이 열립니다. 신청하면 시간표에 얹힙니다.

        +

        과목을 누르면 강의계획과 신청 버튼이 열립니다. 선택한 과목은 시간표에서 확인할 수 있습니다.

        +

        이 페이지의 과목·정원·이수 현황은 예시입니다. 선택한 과목은 새로고침하면 초기화됩니다.

        @@ -59,20 +59,21 @@

        두 가지 읽기 방식

        -

        같은 문장이
        다른 속도로 읽힌다.

        +

        같은 문장, 서로 다른 결.

        +

        크기·행간·폭을 맞췄습니다. 서체마다 글자가 보이는 크기는 다를 수 있습니다.

        -

        본문

        -

        Pretendard · 작고 긴 문장에 필요한 명료한 골격

        +

        Pretendard

        +

        본문용 산세리프

        아침 안개가 걷히기 전에 도랑물 소리가 먼저 들렸다. 글자는 종이 위에서 소리를 내지 않지만, 잘 짜인 활자는 소리 내어 읽게 만든다.

        -

        제목

        -

        마루 부리 · 표제에서 멈춤과 여백을 만드는 결

        +

        MaruBuri

        +

        명조 계열 세리프

        아침 안개가 걷히기 전에 도랑물 소리가 먼저 들렸다. 글자는 종이 위에서 소리를 내지 않지만, 잘 짜인 활자는 소리 내어 읽게 만든다.

        @@ -86,10 +87,11 @@

        조판 시험대

        읽는 호흡을
        직접 맞춰 보세요.

        -

        크기는 문장의 밀도를, 자간은 낱글자 사이의 공기를, 행간은 다음 줄로 넘어가는 속도를 바꿉니다. 하나씩 움직여 같은 문장이 어떻게 달라지는지 비교해 보세요.

        +

        크기·자간·행간을 바꾸며 문장 폭, 줄바꿈, 글자 형태의 차이가 어떻게 보이는지 비교해 보세요.

        +
        17px
        0em
        1.8
        @@ -97,6 +99,7 @@

        마루 부리 · 17px · 자간 0em · 행간 1.8

        +

        아래 문단은 역사 사실을 설명하는 글이 아닌 조판 견본글입니다.

        활자의 역사는 글자를 찍는 기계의 역사가 아니라, 글자를 읽는 눈의 역사였다. 활자소의 식자공들은 하루에 만 글자를 짜면서 어느 글꼴이 눈을 덜 아프게 하는지 알고 있었다. 그 지식은 문서로 남지 않았고 손끝으로만 전해졌다. 이 미리보기는 그 판단을 눈으로 비교할 수 있게 옮긴 것입니다. 자간을 0에서 5로 바꾸면 문단의 호흡과 줄 길이가 어떻게 달라지는지 확인할 수 있습니다.
        @@ -147,20 +150,22 @@ typeStatus.textContent = typeMessages[kind]; })); const sample = document.getElementById("bench-sample"); - const ctl = { size: document.getElementById("ctl-size"), tracking: document.getElementById("ctl-tracking"), leading: document.getElementById("ctl-leading") }; + const ctl = { font: document.getElementById("ctl-font"), size: document.getElementById("ctl-size"), tracking: document.getElementById("ctl-tracking"), leading: document.getElementById("ctl-leading") }; const out = { size: document.getElementById("out-size"), tracking: document.getElementById("out-tracking"), leading: document.getElementById("out-leading") }; - const defaults = { size: 17, tracking: 0, leading: 1.8 }; + const defaults = { font: "display", size: 17, tracking: 0, leading: 1.8 }; + const fontNames = { display: "마루 부리", body: "Pretendard" }; function apply() { + sample.style.fontFamily = ctl.font.value === "display" ? "var(--font-display)" : "var(--font-body)"; sample.style.fontSize = ctl.size.value + "px"; sample.style.letterSpacing = ctl.tracking.value / 100 + "em"; sample.style.lineHeight = ctl.leading.value; out.size.textContent = ctl.size.value + "px"; out.tracking.textContent = ctl.tracking.value / 100 + "em"; out.leading.textContent = Number(ctl.leading.value).toFixed(1); - document.getElementById("bench-caption").textContent = `마루 부리 · ${ctl.size.value}px · 자간 ${ctl.tracking.value / 100}em · 행간 ${Number(ctl.leading.value).toFixed(1)}`; + document.getElementById("bench-caption").textContent = `${fontNames[ctl.font.value]} · ${ctl.size.value}px · 자간 ${ctl.tracking.value / 100}em · 행간 ${Number(ctl.leading.value).toFixed(1)}`; } - Object.values(ctl).forEach((input) => input.addEventListener("input", apply)); - document.getElementById("ctl-reset").addEventListener("click", () => { ctl.size.value = defaults.size; ctl.tracking.value = defaults.tracking; ctl.leading.value = defaults.leading; apply(); }); + Object.values(ctl).forEach((input) => { input.addEventListener("input", apply); input.addEventListener("change", apply); }); + document.getElementById("ctl-reset").addEventListener("click", () => { ctl.font.value = defaults.font; ctl.size.value = defaults.size; ctl.tracking.value = defaults.tracking; ctl.leading.value = defaults.leading; apply(); }); apply(); diff --git a/apps/site/public/work/font-foundry/styles/fonts.css b/apps/site/public/work/font-foundry/styles/fonts.css new file mode 100644 index 0000000..f5234d6 --- /dev/null +++ b/apps/site/public/work/font-foundry/styles/fonts.css @@ -0,0 +1,15 @@ +@font-face { + font-family: "MaruBuri"; + src: url("../assets/fonts/MaruBuri-Regular.woff2") format("woff2"); + font-style: normal; + font-weight: 400; + font-display: swap; +} + +@font-face { + font-family: "MaruBuri"; + src: url("../assets/fonts/MaruBuri-SemiBold.woff2") format("woff2"); + font-style: normal; + font-weight: 600; + font-display: swap; +} diff --git a/apps/site/public/work/font-foundry/styles/main.css b/apps/site/public/work/font-foundry/styles/main.css index efd97d1..adffb99 100644 --- a/apps/site/public/work/font-foundry/styles/main.css +++ b/apps/site/public/work/font-foundry/styles/main.css @@ -1,4 +1,4 @@ -@import url("./tokens.css?v=3"); +@import url("./tokens.css?v=20260912all"); *, *::before, *::after { box-sizing: border-box; } * { margin: 0; } @@ -19,36 +19,41 @@ a { color: inherit; } .site-head { position: sticky; z-index: 10; top: 0; border-bottom: 1px solid var(--line); background: color-mix(in srgb, var(--surface) 94%, transparent); backdrop-filter: blur(6px); } .head-inner { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-4); min-block-size: 4.25rem; } .wordmark { font-family: var(--font-display); font-size: var(--step-1); font-weight: 600; text-decoration: none; } -.nav { display: flex; gap: clamp(var(--space-3), 2vw, var(--space-5)); font-size: var(--step--1); } +.nav { display: flex; flex-wrap: wrap; gap: clamp(var(--space-3), 2vw, var(--space-5)); font-size: var(--step--1); } .nav a { padding-block: var(--space-2); color: var(--ink-muted); text-decoration: none; } .nav a:hover { color: var(--accent); } -.hero { padding-block: clamp(var(--space-6), 7vw, var(--space-8)) var(--space-7); } -.hero-rail { width: min(100% - 2 * var(--pad-wide), var(--container-wide)); margin-inline: auto; } -.hero-intro { display: grid; grid-template-columns: minmax(0, 7fr) minmax(17rem, 3fr); gap: var(--space-6) clamp(var(--space-5), 7vw, var(--space-8)); align-items: end; } -.hero h1 { margin-top: var(--space-3); font-size: clamp(2.5rem, 1.3rem + 4.2vw, 5rem); max-inline-size: 10ch; } -.hero-note { max-inline-size: 27rem; padding-bottom: var(--space-2); } +.hero { padding-block: clamp(var(--space-5), 5vw, var(--space-7)) var(--space-7); } +.hero-rail { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: clamp(var(--space-5), 5vw, var(--space-8)); width: min(100% - 2 * var(--pad-wide), var(--container-wide)); margin-inline: auto; align-items: stretch; } +.hero-rail > *, .hero-intro > * { min-inline-size: 0; } +.hero-intro { display: flex; flex-direction: column; justify-content: space-between; gap: var(--space-6); min-block-size: clamp(32rem, 52vw, 44rem); padding: clamp(var(--space-5), 4vw, var(--space-7)); border: 1px solid var(--line); background: var(--surface-raised); } +.hero h1 { margin-top: var(--space-3); font-size: clamp(2.5rem, 1.6rem + 3vw, 3.75rem); max-inline-size: 10ch; } +.hero-note { max-inline-size: 29rem; } .text-link { display: inline-flex; gap: var(--space-2); margin-top: var(--space-4); color: var(--accent); font-weight: 600; text-decoration-thickness: 1px; text-underline-offset: 0.25em; } -.specimen-stage { margin-top: clamp(var(--space-6), 8vw, var(--space-8)); color: var(--accent); } -.stage-label { color: var(--ink-muted); } -.hero-specimen { min-inline-size: 0; margin-top: var(--space-4); font-family: var(--font-body); font-size: clamp(6rem, 17.5vw, 16.25rem); font-weight: 650; letter-spacing: -0.09em; line-height: 0.82; text-wrap: nowrap; } +.specimen-stage { display: flex; flex-direction: column; justify-content: space-between; min-inline-size: 0; min-block-size: clamp(32rem, 52vw, 44rem); padding: clamp(var(--space-5), 4vw, var(--space-7)); background: var(--accent); color: var(--stage-ink); } +.stage-label { color: var(--stage-ink); } +.hero-specimen { min-inline-size: 0; margin-block: var(--space-5); font-family: var(--font-body); font-size: clamp(6rem, 11vw, 11.25rem); font-weight: 650; letter-spacing: -0.09em; line-height: 0.82; overflow-wrap: anywhere; white-space: normal; } .specimen-stage[data-kind="title"] .hero-specimen { font-family: var(--font-display); font-weight: 600; letter-spacing: -0.11em; } -.baseline { block-size: 1px; margin-top: var(--space-3); background: var(--accent); } +.baseline { block-size: 1px; margin-top: var(--space-3); background: color-mix(in srgb, var(--stage-ink) 75%, transparent); } .stage-footer { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); padding-top: var(--space-3); } -.type-switch { display: flex; gap: var(--space-2); } +.type-switch { display: flex; flex-wrap: wrap; gap: var(--space-2); } .type-choice, .btn-reset { min-block-size: 2.75rem; border: 1px solid var(--line); border-radius: var(--radius); background: transparent; color: var(--ink); cursor: pointer; font: inherit; padding-inline: 0.9rem; } -.type-choice[aria-pressed="true"] { border-color: var(--accent); background: var(--accent); color: var(--accent-ink); } -.type-status { color: var(--ink-muted); font-size: var(--step--1); text-align: end; } +.type-choice { border-color: color-mix(in srgb, var(--stage-ink) 72%, transparent); color: var(--stage-ink); } +.type-choice[aria-pressed="true"] { border-color: var(--stage-ink); background: var(--stage-ink); color: var(--accent); } +.type-choice:focus-visible { outline-color: var(--stage-ink); } +.type-status { color: var(--stage-ink); font-size: var(--step--1); text-align: end; } .section { padding-block: var(--space-8); } +.section[id] { scroll-margin-block-start: 5rem; } .band { border-block: 1px solid var(--line); background: var(--surface-raised); } .section-head { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: var(--space-5); align-items: baseline; } -.comparison { margin-top: var(--space-7); border-top: 1px solid var(--line); } -.typeface { display: grid; grid-template-columns: minmax(10rem, 3fr) minmax(0, 7fr); gap: var(--space-5) var(--space-7); padding-block: var(--space-6); border-bottom: 1px solid var(--line); } +.comparison-note { max-inline-size: 42rem; margin-top: var(--space-5); color: var(--ink-muted); } +.comparison { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-6); margin-top: var(--space-6); border-top: 1px solid var(--line); } +.typeface { min-inline-size: 0; padding-block: var(--space-6); border-bottom: 1px solid var(--line); } .typeface-head .muted { margin-top: var(--space-2); font-size: var(--step--1); } -.specimen { max-inline-size: 42rem; } -.specimen-body { font-family: var(--font-body); font-size: 1.15rem; line-height: 1.9; } -.specimen-display { font-family: var(--font-display); font-size: clamp(1.7rem, 1.2rem + 2.3vw, 3.25rem); line-height: 1.48; } +.specimen { margin-top: var(--space-5); inline-size: 100%; font-size: 1.375rem; line-height: 1.8; } +.specimen-body { font-family: var(--font-body); } +.specimen-display { font-family: var(--font-display); } .bench-heading { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 4fr); gap: var(--space-6); align-items: end; } .bench-lead { max-inline-size: 28rem; } @@ -58,10 +63,13 @@ a { color: inherit; } .control-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); } .control label, .control output { color: var(--ink-muted); font-size: var(--step--1); } .control output, .order-price { font-variant-numeric: tabular-nums; } -input[type="range"] { inline-size: 100%; accent-color: var(--accent); } +input[type="range"], select { inline-size: 100%; accent-color: var(--accent); } +select { min-block-size: 2.75rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); color: var(--ink); font: inherit; padding-inline: var(--space-3); } .btn-reset { justify-self: start; margin-top: var(--space-2); } -.btn-reset:hover, .type-choice:hover { border-color: var(--accent); } +.btn-reset:hover { border-color: var(--accent); } +.type-choice:hover { border-color: var(--stage-ink); } .bench-caption { margin-bottom: var(--space-3); } +.bench-disclaimer { margin-bottom: var(--space-3); color: var(--ink-muted); font-size: var(--step--1); } .bench-sample { max-inline-size: 42rem; border: 1px solid var(--line); background: var(--surface); padding: clamp(var(--space-4), 3vw, var(--space-6)); font-family: var(--font-display); font-size: 1.0625rem; line-height: 1.8; } .case-grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--space-6) var(--space-7); align-items: start; } @@ -85,23 +93,31 @@ input[type="range"] { inline-size: 100%; accent-color: var(--accent); } .foot-inner { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-3) var(--space-5); } @media (max-width: 900px) { - .hero-intro, .section-head, .bench-heading, .bench, .case-grid, .order-grid { grid-template-columns: 1fr; } + .hero-rail, .section-head, .comparison, .bench-heading, .bench, .case-grid, .order-grid { grid-template-columns: 1fr; } + .hero-intro, .specimen-stage { min-block-size: 0; } .hero-intro, .bench-heading { gap: var(--space-4); } .hero-note { max-inline-size: 34rem; } - .typeface { grid-template-columns: 1fr; gap: var(--space-3); } .bench { gap: var(--space-5); } .case-photo { max-inline-size: 30rem; } } @media (max-width: 560px) { .head-inner { display: grid; gap: 0; min-block-size: 0; padding-block: var(--space-3); } - .nav { justify-content: space-between; gap: var(--space-2); max-inline-size: 100%; margin-top: var(--space-1); overflow-x: auto; } + .nav { justify-content: space-between; gap: var(--space-2); max-inline-size: 100%; margin-top: var(--space-1); } .nav a { flex: 0 0 auto; padding-block: var(--space-1); } - .hero { padding-block: var(--space-6); } + .hero { padding-block: var(--space-5); } + .hero-rail { gap: var(--space-4); } + .hero-intro, .specimen-stage { padding: var(--space-4); } + .hero-intro :where(p, h1), .stage-label, .type-status { overflow-wrap: anywhere; } .hero h1 { font-size: clamp(2.5rem, 11vw, 4rem); overflow-wrap: anywhere; word-break: normal; } .hero-specimen { font-size: min(30vw, 9.5rem); letter-spacing: -0.12em; } + .bench-heading > * { min-inline-size: 0; } + .bench-heading h2 { overflow-wrap: anywhere; } + .order-row > * { min-inline-size: 0; max-inline-size: 100%; } + .order-price { white-space: normal; overflow-wrap: anywhere; } .stage-footer, .order-row { align-items: flex-start; flex-direction: column; } .type-status { text-align: start; } .section { padding-block: var(--space-7); } + .section[id] { scroll-margin-block-start: calc(7rem + 1rem); } } @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } diff --git a/apps/site/public/work/font-foundry/styles/tokens.css b/apps/site/public/work/font-foundry/styles/tokens.css index d958822..c63a644 100644 --- a/apps/site/public/work/font-foundry/styles/tokens.css +++ b/apps/site/public/work/font-foundry/styles/tokens.css @@ -16,6 +16,7 @@ --line: #d9d1bf; --accent: #a63d2f; --accent-ink: #f5f1e8; + --stage-ink: #fffaf1; --accent-hover: #8a3225; --space-1: 0.25rem; --space-2: 0.5rem; diff --git a/apps/site/public/work/form-architecture/assets/fonts/LICENSE.html b/apps/site/public/work/form-architecture/assets/fonts/LICENSE.html new file mode 100644 index 0000000..571387d --- /dev/null +++ b/apps/site/public/work/form-architecture/assets/fonts/LICENSE.html @@ -0,0 +1,169 @@ +네이버 나눔글꼴 라이선스안내 : 고객센터
        빈줄

            + + + +
            +
            +
            +
            +
            +

            네이버 나눔글꼴의 지적 재산권은 네이버와 네이버 문화재단에 있습니다.

            +

            ​

            +

            네이버 나눔글꼴은 개인 및 기업 사용자를 포함한 모든 사용자에게 무료로 제공되며 글꼴 자체를 유료로 판매하는 것을 제외한 상업적인 사용이 가능합니다.

            +

            ​

            +

            네이버 나눔글꼴은 본 저작권 안내와 라이선스 전문을 포함해서 다른 소프트웨어와 번들하거나 재배포 또는 판매가 가능하고 자유롭게 수정, 재배포하실 수 있습니다.

            +

            ​

            +

            네이버 나눔글꼴 라이선스 전문을 포함하기 어려울 경우, 나눔글꼴의 출처 표기를 권장합니다.

            +

            예) 이 페이지에는 네이버에서 제공한 나눔글꼴이 적용되어 있습니다.

            +

            ​

            +

            네이버 나눔글꼴을 사용한 인쇄물, 광고물(온라인 포함)의 이미지는 나눔글꼴 프로모션을 위해 활용될 수 있습니다.

            +

            ​

            +

            이를 원치 않는 사용자는 언제든지 당사에 요청하실 수 있습니다.

            +

            ​

            +

            정확한 사용 조건은 아래 네이버 나눔글꼴 라이선스 전문을 참고하시기 바랍니다.

            +

            ​

            +

            네이버 마루 부리 글꼴도 나눔 글꼴과 같은 오픈라이센스 폰트로 동일한 저작권 규정을 적용받습니다.

            +

            ​

            +

            ※ 참고해 주세요!

            +

            - 나눔글꼴 라이선스 전문의 한글은 이용자의 이해를 돕기 위해 영문 원본을 번역해 서비스하고 있으며, 법적 효력은 영문에 한합니다.

            +

            ​

            +

            1. 라이선스

            +

            Copyright (c) 2010, NAVER Corporation (https://www.navercorp.com/) with Reserved Font Name Nanum, Naver Nanum, NanumGothic, Naver NanumGothic, NanumMyeongjo, Naver NanumMyeongjo, NanumBrush, Naver NanumBrush, NanumPen, Naver NanumPen, Naver NanumGothicEco, NanumGothicEco, Naver NanumMyeongjoEco, NanumMyeongjoEco, Naver NanumGothicLight, NanumGothicLight, NanumBarunGothic, Naver NanumBarunGothic, NanumSquareRound, NanumBarunPen, MaruBuri, NanumSquareNeo

            +

            ​

            +

            This Font Software is licensed under the SIL Open Font License, Version 1.1.

            +

            ​

            +

            This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL

            +

            ​

            +

            SIL OPEN FONT LICENSE

            +

            Version 1.1 - 26 February 2007

            +

            ​

            +

            ‘나눔, 네이버 나눔, 나눔고딕, 네이버 나눔고딕, 나눔명조, 네이버 나눔명조, 나눔손글씨, 네이버 나눔손글씨, 나눔펜, 네이버 나눔펜, 네이버 나눔고딕에코, 나눔고딕에코, 네이버 나눔명조에코, 나눔명조에코, 네이버 나눔고딕라이트, 나눔고딕라이트, 나눔바른고딕, 네이버나눔바른고딕, 나눔스퀘어라운드, 나눔바른펜, 마루 부리, 나눔스퀘어네오’ 폰트명에 대해 NAVER(https://www.navercorp.com/)가 저작권을 소유하고 있습니다.

            +

            ​

            +

            본 폰트 소프트웨어는 SIL 오픈 폰트 라이선스 버전 1.1에 따라 라이선스 취득을 하였습니다.

            +

            ​

            +

            본 라이선스는 하단에 복사되었고 http://scripts.sil.org/OFL의 FAQ 란에서도 열람 가능합니다.

            +

            ​

            +

            SIL 오픈 폰트 라이선스

            +

            버전 1.1 (2007년 2월 26일)

            +

            ​

            +

            [DEFINITIONS (정의)]

            +

            ""Font Software"" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.

            +

            ​

            +

            ""Reserved Font Name"" refers to any names specified as such after the copyright statement(s).

            +

            ​

            +

            ""Original Version"" refers to the collection of Font Software components as distributed by the Copyright Holder(s).

            +

            ​

            +

            ""Modified Version"" refers to any derivative made by adding to, deleting, or substituting in part or in whole any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.‘

            +

            ​

            +

            ""Author"" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.

            +

            ​

            +

            ‘폰트 소프트웨어’는 본 라이선스에 입거해 저작권자가 배포하고 명확하게 같은 표시가 된 파일들의 집합을 뜻하며, 여기에는 소스 파일, 빌드 스크립트와 문서가 이에 포함됩니다.

            +

            ​

            +

            ‘저작권이 있는 폰트명’은 저작권 정책에 따라서 지정된 이름을 말합니다.

            +

            ​

            +

            ‘원본’은 저작권자가 배포한 폰트 소프트웨어 구성요소를 의미합니다.

            +

            ​

            +

            ‘수정본’은 포맷의 변경이나 폰트 소프트웨어를 새로운 환경에 포팅 시켜, 원본의 일부 혹은 전체에 추가, 삭제 대체해 만든 파생 저작물을 의미합니다.

            +

            ​

            +

            ‘저자’는 폰트 소프트웨어에 기여한 디자이너, 엔지니어, 프로그래머, 기술 전문가 등을 의미합니다.

            +

            ​

            +

            2. PREAMBLE (전문)

            +

            The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.

            +

            ​

            +

            The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works.

            +

            ​

            +

            The fonts and derivatives, however, cannot be released under any other type of license.

            +

            ​

            +

            The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives.

            +

            ​

            +

            본 폰트 라이선스를 오픈하는 것은(이하 OFL)는 전 세계 폰트 개발 프로젝트를 지원하고 학계와 언어 관련 학계의 폰트 개발을 위한 연구를 지지하기 위해서인 동시에, 폰트 제휴를 통해 폰트가 공유되고 개선될 수 있는 자유롭게 개방된 환경을 만들기 위해서입니다.

            +

            ​

            +

            OFL은 라이선스를 취득한 폰트가 그 자체로 판매되지 않는 한 자유롭게 사용, 연구, 수정, 재배포 하는 것을 허가합니다.

            +

            ​

            +

            수정된 폰트를 포함한 폰트는 저작권 명이 사용되지 않는 한 기타 소프트웨어와 함께 묶이거나 삽입, 재배포 할 수 있습니다.

            +

            ​

            +

            단 폰트와 수정된 폰트는 기타 다른 라이선스에 포함되어 배포될 수는 없습니다.

            +

            ​

            +

            이 라이선스 하에 있기 위한 폰트에 대한 요구사항은 본 폰트나 수정본을 사용하여 제작된 어떠한 문서에도 적용되지 않습니다.

            +

            ​

            +

            3. PERMISSION & CONDITIONS (허가 및 조건)

            +

            Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:

            +

            ​

            +

            본 폰트 소프트웨어를 사용하도록 허가받은 개인/기업/단체 누구라도 다음 명시된 조건에 따라 폰트 소프트웨어의 수정 혹은 수정되지 않은 복사본을 무료로 사용, 연구, 복사, 통합, 삽입, 수정, 재배포할 수 있도록 허가합니다.

            +

            ​

            +

            1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.

            +

            ​

            +

            원본이나 수정본의 폰트 소프트웨어 혹은 개별 구성요소인 폰트 자체가 판매되어서는 안됩니다.

            +

            ​

            +

            2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license.

            +

            ​

            +

            These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.

            +

            ​

            +

            본 폰트 소프트웨어의 원본 혹은 수정본은 상기 저작권 안내와 본 라이선스에 대한 내용을 포함하는 경우에는 다른 소프트웨어와 함께 묶이거나 재배포 혹은 판매가 가능합니다.

            +

            ​

            +

            이는 독립 텍스트 파일과 가독성이 있는 헤더 혹은 유저가 용이하게 열람 가능한 이상 텍스트 파일 혹은 이진 파일 내 기계가 읽을 수 있는 메타데이터 형태를 모두 의미합니다.

            +

            ​

            +

            3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder.

            +

            ​

            +

            This restriction only applies to the primary font name as presented to the users.

            +

            ​

            +

            본 폰트 소프트웨어의 어떠한 수정본도 동일한 저작권자가 명시적 허가서를 부여하지 않는 한 저작권이 있는 폰트명을 사용해서는 안 됩니다.

            +

            ​

            +

            본 제한 사항은 유저들에게 제공된 기존 폰트명을 뜻합니다.

            +

            ​

            +

            4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.

            +

            ​

            +

            본 폰트 소프트웨어의 저작권자 혹은 저자의 이름은 그들의 명시적 서면 허가가 있거나 또는 그들의 공헌을 인정하기 위한 경우를 제외하고는 수정본에 대한 사용을 유도, 추천 혹은 광고하기 위한 목적으로 사용할 수 없습니다.

            +

            ​

            +

            5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed any other license.

            +

            ​

            +

            The requirement for fonts to remain under this license does not apply to any document created using the Font Software.

            +

            ​

            +

            본 폰트 소프트웨어는 전체나 부분, 혹은 수정 여부에 상관없이 본 라이선스 하에 배포가 되어야 하며 기타 다른 라이선스 하에서는 배포를 할 수 없습니다.

            +

            ​

            +

            폰트에 대한 요구 조건은 이 라이선스 하에서만 유효하며 이 라이선스 하에 있기 위한 폰트에 대한 요구사항은 본 폰트 소프트웨어를 사용해 제작한 어떠한 문서에도 적용되지 않습니다.

            +

            ​

            +

            4. TERMINATION (계약의 종료)

            +

            This license becomes null and void if any of the above conditions are not met.

            +

            ​

            +

            본 라이선스는 상기 조건 중 일부라도 부합되지 않으면 무효가 될 수 있습니다.

            +

            ​

            +

            5. DISCLAIMER (면책조항)

            +

            THE FONT SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT.

            +

            ​

            +

            IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.

            +

            ​

            +

            본 폰트 소프트웨어는 저작권, 특허권, 상표권 및 기타 권리의 비침해성과 특정 목적에의 적합성 포함한 명시적, 묵시적인 어떠한 종류의 보증 없이 “있는 그대로” 제공됩니다.

            +

            ​

            +

            어떠한 경우에도 저작권자는 본 폰트 소프트웨어의 사용 또는 이의 사용 불가, 그밖에 폰트 소프트웨어의 취급과 관련하여 발생하는 모든 계약, 불법행위 혹은 다른 일로 하여금 발생하는 일반적, 특수적, 간접적, 부차적 혹은 필연적 손해를 포함하는 소송, 손해, 혹은 기타 책임에 대한 의무를 가지지 않습니다.

            + +
            +
            +
            + +
            +
            만족도 평가
          \ No newline at end of file diff --git a/apps/site/public/work/form-architecture/assets/fonts/MaruBuri-Regular.woff2 b/apps/site/public/work/form-architecture/assets/fonts/MaruBuri-Regular.woff2 new file mode 100644 index 0000000..3bc205f Binary files /dev/null and b/apps/site/public/work/form-architecture/assets/fonts/MaruBuri-Regular.woff2 differ diff --git a/apps/site/public/work/form-architecture/assets/fonts/MaruBuri-SemiBold.woff2 b/apps/site/public/work/form-architecture/assets/fonts/MaruBuri-SemiBold.woff2 new file mode 100644 index 0000000..be593a5 Binary files /dev/null and b/apps/site/public/work/form-architecture/assets/fonts/MaruBuri-SemiBold.woff2 differ diff --git a/apps/site/public/work/form-architecture/assets/fonts/SOURCES.md b/apps/site/public/work/form-architecture/assets/fonts/SOURCES.md new file mode 100644 index 0000000..66d2c89 --- /dev/null +++ b/apps/site/public/work/form-architecture/assets/fonts/SOURCES.md @@ -0,0 +1,13 @@ +# MaruBuri source record + +Downloaded 2026-09-12 from the official NAVER Hangeul static host. The files are retained unchanged: no conversion or subsetting was performed. + +| File | Official URL | HTTP content type | Size | SHA-256 | +| --- | --- | --- | --- | --- | +| `MaruBuri-Regular.woff2` | https://hangeul.pstatic.net/hangeul_static/webfont/MaruBuri/MaruBuri-Regular.woff2 | `font/woff2` | 433776 bytes | `4CF1341CF2F23FB3E263712DFDE1D8F25EEDCC328B696A2E5A2C8ADD55E5C17B` | +| `MaruBuri-SemiBold.woff2` | https://hangeul.pstatic.net/hangeul_static/webfont/MaruBuri/MaruBuri-SemiBold.woff2 | `font/woff2` | 466108 bytes | `7AEF4862FA3219B0A7DEB6746E27116A38C4069F4424EB51EDF103B29795F5C2` | + +- Official stylesheet checked: https://hangeul.pstatic.net/hangeul_static/css/maru-buri.css +- Official NAVER license page saved verbatim as `LICENSE.html`: https://help.naver.com/service/11029/contents/18088?lang=ko&osType=PC +- `LICENSE.html` SHA-256: `8538F7921744D5E040F603BC301465EFBD038F1054D0754B7508DE3286452EC3` +- The saved official page includes the NAVER copyright notice and the SIL Open Font License 1.1 text for MaruBuri. diff --git a/apps/site/public/work/form-architecture/design.md b/apps/site/public/work/form-architecture/design.md index 1decf4c..8ce5b34 100644 --- a/apps/site/public/work/form-architecture/design.md +++ b/apps/site/public/work/form-architecture/design.md @@ -41,3 +41,10 @@ - `prefers-reduced-motion`과 효과 제거 상태에서도 콘텐츠가 같은 순서로 읽히는지 점검한다. - 200% 텍스트 확대에서 본문·CTA가 사라지지 않는지 점검한다. - 실행 결과와 화면 캡처는 `outputs/design-expertise-20260912/form/`에 남긴다. + +## 2026-09-12 전체 쇼케이스 점검 + +- 기존 흑백 사진·도면 구도, 앵커와 긴 모바일 라벨의 줄바꿈 규칙을 보존했다. 로컬 MaruBuri 파일을 함께 제공하되 현재 Pretendard 단일 패밀리 본문 계약은 바꾸지 않았다. +- `verify-final` 18개 묶음은 16개가 즉시 통과했다. 전체 묶음의 invariant·visual 검사는 Gaon·Dure를 대상으로 하며, 나머지 2개는 수정 뒤 release 독립 재실행에서 ALL PASS·ALL MATCH였다. +- root는 28개 모바일, 21개 데스크톱, 7개 하위 경로와 30개 앱 상태를 직접 검토해 수용했다. stress 112건은 hard failure 0이며, 가로 넘침 4건은 targeted fix 뒤 390px 재측정에서 0이다. +- 이 기록은 렌더·계약 범위의 현재 결과다. 모든 폭·키보드 경로·인쇄 등 개별 기능을 완전 재실행했다는 뜻이 아니며, 참여자 과업 효과도 미측정이다. diff --git a/apps/site/public/work/form-architecture/index.html b/apps/site/public/work/form-architecture/index.html index 2aaab07..36bb38a 100644 --- a/apps/site/public/work/form-architecture/index.html +++ b/apps/site/public/work/form-architecture/index.html @@ -10,7 +10,8 @@ - + + diff --git a/apps/site/public/work/form-architecture/styles/fonts.css b/apps/site/public/work/form-architecture/styles/fonts.css new file mode 100644 index 0000000..f5234d6 --- /dev/null +++ b/apps/site/public/work/form-architecture/styles/fonts.css @@ -0,0 +1,15 @@ +@font-face { + font-family: "MaruBuri"; + src: url("../assets/fonts/MaruBuri-Regular.woff2") format("woff2"); + font-style: normal; + font-weight: 400; + font-display: swap; +} + +@font-face { + font-family: "MaruBuri"; + src: url("../assets/fonts/MaruBuri-SemiBold.woff2") format("woff2"); + font-style: normal; + font-weight: 600; + font-display: swap; +} diff --git a/apps/site/public/work/form-architecture/styles/main.css b/apps/site/public/work/form-architecture/styles/main.css index 43ea20e..49f49c4 100644 --- a/apps/site/public/work/form-architecture/styles/main.css +++ b/apps/site/public/work/form-architecture/styles/main.css @@ -1,4 +1,4 @@ -@import url("./tokens.css?v=3"); +@import url("./tokens.css?v=20260912all"); *, *::before, *::after { box-sizing: border-box; } * { margin: 0; } diff --git a/apps/site/public/work/gaon-lms/design.md b/apps/site/public/work/gaon-lms/design.md new file mode 100644 index 0000000..071f163 --- /dev/null +++ b/apps/site/public/work/gaon-lms/design.md @@ -0,0 +1,24 @@ +# 가온 학적부 디자인 기록 + +## 브리프 + +- 무엇을: 학원 강사가 수업·출석·과제·상담을 기록으로 확인하는 학적부형 관리 화면. +- 누구에게: 행과 상태를 빠르게 대조하고 다음 업무를 정해야 하는 강사. +- 제약: 예시 데이터와 기존 계산·상태·모바일 내비·대화상자·인쇄 흐름을 보존한다. + +## 판단 기준 + +| 축 | 질문 | 적용 | +| --- | --- | --- | +| Warde · 정보 전달 | 다음 확인 대상이 수치보다 먼저 읽히는가 | 공통 정렬선과 가는 구분선의 요약 기록 밴드, 15px 표 본문 | +| Ruder · 비교 변수 | 같은 종류의 값이 같은 열과 숫자 폭에서 비교되는가 | 표 숫자에 tabular figures, 수치 열 오른쪽 정렬 | +| Albers · 상태 맥락 | 상태색이 주변의 중립 기록면에서 구분되는가 | 상태는 텍스트와 함께 유지하고 배경색은 보조로 사용 | + +Warde, Ruder, Albers는 정보 전달·비교 변수·상태 맥락을 검토하는 참고 질문이며 인과나 성능 법칙이 아니다. + +## 역할 토큰과 검증 + +- `--record-radius`, `--record-rule`, `--record-body-size`, `--record-meta-size`가 기록면·구분선·본문·보조정보 역할을 고정한다. +- `verify-final` 18개 묶음은 16개가 즉시 통과했다. 전체 묶음의 invariant·visual 검사는 Gaon·Dure를 대상으로 하며, 나머지 2개는 수정 뒤 release 독립 재실행에서 ALL PASS·ALL MATCH였다. +- root는 28개 모바일, 21개 데스크톱, 7개 하위 경로와 30개 앱 상태를 직접 검토해 수용했다. stress 112건은 hard failure 0이며, 가로 넘침 4건은 targeted fix 뒤 390px 재측정에서 0이다. +- 이 기록은 렌더·계약 범위의 현재 결과다. 모든 폭·키보드 경로·인쇄 등 개별 기능을 완전 재실행했다는 뜻이 아니며, 참여자 과업 효과도 미측정이다. diff --git a/apps/site/public/work/gaon-lms/index.html b/apps/site/public/work/gaon-lms/index.html index 1c64797..f1632b3 100644 --- a/apps/site/public/work/gaon-lms/index.html +++ b/apps/site/public/work/gaon-lms/index.html @@ -9,15 +9,15 @@ - + - + @@ -35,7 +35,7 @@ rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&family=Noto+Serif+KR:wght@500;600&display=swap" /> - +

          이번 주, 열두 명 중 열 명

          3월 9일 월요일 오전 기준. 명단 12명 중 재학 10명, 주간 출석은 지난 주(3/2–3/6) 결산입니다.

          +

          표시된 수강생·수업·상담 기록은 예시입니다. 이 화면에서 바꾼 내용은 새로고침하면 초기화됩니다.

          @@ -217,6 +218,7 @@ 결석 +
          @@ -229,6 +231,7 @@
          요일별 출석 결산
          요일출석지각결석출석률
          합계462292%
          +
          @@ -550,7 +553,7 @@ -

          다운로드 링크를 만들지 않는다 — 이 데모에는 파일이 없다. 배부 상태만 기록한다.

          +

          배부 여부와 열람 현황을 확인하는 목록입니다. 원본 파일은 이 화면에서 제공하지 않습니다.

          @@ -798,7 +801,7 @@ - +
          -

          쇼케이스용 가상 브랜드 · 가격과 매장 정보는 화면 동작 확인용 예시

          +

          가상 브랜드 안내 · 가격과 매장 정보는 실제 판매 정보가 아닙니다.

          @@ -71,7 +71,7 @@

          서울 도심 눌림 버거

          -

          눌러 굽고,
          바로 건넨다.

          +

          눌러 굽고,
          바로 건넨다.

          얇게 눌러 가장자리는 바삭하게. 주문 뒤 조립하고 포장해, 퇴근길 한 상자로 건넵니다.

          @@ -124,10 +124,10 @@

          오늘 고를 메뉴

          - +

          - 모든 가격은 조합기 동작을 보여 주기 위한 예시입니다. 실제 판매와 주문은 이루어지지 않습니다. + 표시된 메뉴와 가격은 브랜드 콘셉트를 설명하기 위한 값입니다. 이 페이지에서는 실제 판매와 주문을 제공하지 않습니다.

          @@ -162,9 +162,17 @@
          @@ -453,9 +459,9 @@ diff --git a/apps/site/public/work/griddle-club/og.png b/apps/site/public/work/griddle-club/og.png index afa513c..2ff453c 100644 Binary files a/apps/site/public/work/griddle-club/og.png and b/apps/site/public/work/griddle-club/og.png differ diff --git a/apps/site/public/work/griddle-club/scripts/franchise.js b/apps/site/public/work/griddle-club/scripts/franchise.js index c5118dc..3118bc7 100644 --- a/apps/site/public/work/griddle-club/scripts/franchise.js +++ b/apps/site/public/work/griddle-club/scripts/franchise.js @@ -105,7 +105,7 @@ clearRadioError("areaKind", "area-kind-error"); if (getInputValue("demoName").length < 2) { - invalid.push(setFieldError("demo-name", "demo-name-error", "예시 호칭을 두 글자 이상 입력해 주세요.")); + invalid.push(setFieldError("demo-name", "demo-name-error", "확인용 호칭을 두 글자 이상 입력해 주세요.")); } if (!getSelectValue("region")) { invalid.push(setFieldError("region", "region-error", "희망 지역을 골라 주세요.")); @@ -240,14 +240,14 @@ if (!(consent instanceof HTMLInputElement) || !consent.checked) { consent?.setAttribute("aria-invalid", "true"); consent?.setAttribute("aria-describedby", "demo-consent-error"); - if (consentError) consentError.textContent = "문의 체험 안내를 확인해 주세요."; + if (consentError) consentError.textContent = "개인정보를 입력하지 않았는지 확인해 주세요."; consent?.focus(); return; } if (submitButton instanceof HTMLButtonElement) { submitButton.disabled = true; - submitButton.textContent = "화면 상태 확인 중"; + submitButton.textContent = "입력한 조건 확인 중"; } if (submitState) submitState.textContent = ""; @@ -258,7 +258,7 @@ submitButton.textContent = "다시 시도하기"; } if (submitState) { - submitState.textContent = "지금은 문의 준비 상태를 바꾸지 못했어요. 입력 내용은 화면에 그대로 두었습니다."; + submitState.textContent = "지금은 입력한 조건을 확인할 수 없어요. 입력한 값은 그대로 두었습니다."; } return; } @@ -271,7 +271,7 @@ } if (submitButton instanceof HTMLButtonElement) { submitButton.disabled = false; - submitButton.textContent = "문의 준비 마치기"; + submitButton.textContent = "입력한 조건 확인하기"; } }, 450); }); diff --git a/apps/site/public/work/griddle-club/scripts/site.js b/apps/site/public/work/griddle-club/scripts/site.js index fc6ef0e..0efcecb 100644 --- a/apps/site/public/work/griddle-club/scripts/site.js +++ b/apps/site/public/work/griddle-club/scripts/site.js @@ -61,13 +61,10 @@ const summaryStoreState = document.querySelector("#summary-store-state"); const summaryAllergens = document.querySelector("#summary-allergens"); const summaryTotal = document.querySelector("#summary-total"); - const saveButton = document.querySelector("#save-builder"); - const saveStatus = document.querySelector("#save-status"); - const stores = { - seongsu: { label: "성수 예시점", state: "영업 중 예시", available: true }, - yeonnam: { label: "연남 예시점", state: "오늘 영업 종료 예시", available: false }, - mullae: { label: "문래 예시점", state: "오늘은 쉬어요", available: false }, + seongsu: { label: "성수점", state: "영업 중" }, + yeonnam: { label: "연남점", state: "오늘 영업 종료" }, + mullae: { label: "문래점", state: "오늘 휴무" }, }; const fieldValue = (name) => { @@ -134,16 +131,6 @@ if (summaryAllergens) summaryAllergens.textContent = allergens.join(", "); if (summaryTotal) summaryTotal.textContent = formatWon(builderPrice({ flavor, patty, cheese, serving })); - if (saveButton) { - saveButton.disabled = soldOut || !store.available; - if (soldOut) saveButton.textContent = "오늘 품절 예시"; - else if (!store.available) saveButton.textContent = "다른 매장을 골라 주세요"; - else saveButton.textContent = "선택 내용 저장"; - } - if (saveStatus) { - saveStatus.textContent = ""; - saveStatus.classList.remove("is-error"); - } }; builder?.addEventListener("change", updateBuilder); @@ -169,20 +156,6 @@ button.addEventListener("click", () => applyPreset(button.dataset.preset || "double")); }); - saveButton?.addEventListener("click", () => { - if (!builder || !saveStatus) return; - const snapshot = Object.fromEntries(new FormData(builder).entries()); - try { - if (fixture === "save-fail") throw new Error("fixture"); - sessionStorage.setItem("griddle-club-demo-selection", JSON.stringify(snapshot)); - saveStatus.classList.remove("is-error"); - saveStatus.textContent = "이 기기의 현재 탭에 선택 내용을 남겼어요. 실제 주문으로 전송되지 않습니다."; - } catch { - saveStatus.classList.add("is-error"); - saveStatus.textContent = "선택 내용을 남기지 못했어요. 고른 내용은 화면에 그대로 두었습니다."; - } - }); - const storeCards = [...document.querySelectorAll("[data-store]")]; const mapPins = [...document.querySelectorAll("[data-map-store]")]; const storeSearch = document.querySelector("#store-search"); diff --git a/apps/site/public/work/griddle-club/styles/franchise.css b/apps/site/public/work/griddle-club/styles/franchise.css index eb17fa5..726aa9a 100644 --- a/apps/site/public/work/griddle-club/styles/franchise.css +++ b/apps/site/public/work/griddle-club/styles/franchise.css @@ -17,7 +17,7 @@ } .franchise-hero-copy .section-kicker { - color: #8ea5ff; + color: var(--blue-soft); } .franchise-hero h1 { @@ -62,7 +62,7 @@ max-width: 560px; margin-top: 52px; padding: 18px 20px; - border-left: 3px solid #8ea5ff; + border-left: 3px solid var(--blue-soft); background: #2b2926; } @@ -299,9 +299,9 @@ .franchise-timeline li { display: grid; - grid-template-columns: 56px 1fr auto; + grid-template-columns: 4.5rem minmax(0, 1fr) minmax(9rem, auto); align-items: center; - gap: 28px; + gap: 1.5rem; min-height: 124px; padding: 22px 0; border-bottom: 1px solid var(--line); @@ -325,10 +325,13 @@ } .franchise-timeline small { + justify-self: end; + min-width: 8rem; padding: 6px 9px; border: 1px solid var(--line); font-size: 10px; font-weight: 700; + text-align: center; } .cost-section { @@ -337,7 +340,7 @@ } .cost-section .section-kicker { - color: #8ea5ff; + color: var(--blue-soft); } .cost-head { @@ -355,6 +358,7 @@ .unknown-cost { padding: 22px; border: 1px solid #625f5a; + border-left: 3px solid var(--blue-soft); background: #2a2825; } @@ -366,7 +370,7 @@ .unknown-cost strong { display: block; margin-top: 3px; - color: #8ea5ff; + color: var(--blue-soft); font-size: 25px; } @@ -390,8 +394,10 @@ .cost-table th, .cost-table td { - padding: 17px 14px; + padding: 1.125rem 1rem; border-bottom: 1px solid #4f4c47; + font-size: 0.8125rem; + line-height: 1.55; text-align: left; } @@ -410,7 +416,7 @@ } .cost-table td:nth-child(3) { - color: #8ea5ff; + color: var(--blue-soft); font-family: var(--font-mono); font-weight: 600; } @@ -813,6 +819,12 @@ grid-template-columns: 1.2fr 0.8fr 1.4fr; } +.cost-table th:nth-child(3), +.cost-table td:nth-child(3) { + font-variant-numeric: tabular-nums; + text-align: right; +} + @media (max-width: 960px) { .franchise-hero { grid-template-columns: 0.95fr 1.05fr; @@ -977,3 +989,38 @@ gap: 3px; } } + +/* 공개 메인과 같은 초광폭 상한: 사진이 내용보다 먼저 커지지 않는다. */ +@media (min-width: 120rem) { + .franchise-hero { + width: min(100%, var(--hero-wide)); + min-height: clamp(43rem, 48vw, 54rem); + grid-template-columns: minmax(0, 1fr) minmax(42rem, 1.14fr); + margin-inline: auto; + border-inline: 1px solid var(--ink-soft); + } + + .franchise-hero-copy { + width: min(100%, var(--copy-wide)); + justify-self: end; + padding: clamp(5.5rem, 6vw, 8rem) clamp(4rem, 5vw, 6rem); + } + + .franchise-hero h1 { + max-width: 12ch; + font-size: clamp(4.25rem, 3.2rem + 2.2vw, 5.5rem); + } + + .franchise-hero-media { + width: min(100%, var(--media-wide)); + min-height: clamp(43rem, 48vw, 54rem); + justify-self: end; + } + + .fact-rail .wrap, + .model-section .wrap, + .site-fit-section .wrap, + .franchise-process .wrap { + max-width: var(--workbench-wide); + } +} diff --git a/apps/site/public/work/griddle-club/styles/site.css b/apps/site/public/work/griddle-club/styles/site.css index afba3e4..b3b1605 100644 --- a/apps/site/public/work/griddle-club/styles/site.css +++ b/apps/site/public/work/griddle-club/styles/site.css @@ -240,6 +240,17 @@ fieldset { line-height: 0.98; } +/* 초광폭에서 바깥 여백을 늘려도 카피 칼럼의 안쪽 폭이 사라지지 않게 한다. */ +@media (min-width: 120rem) { + .hero { + grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); + } + + .hero-copy { + max-width: none; + } +} + .hero-lead { max-width: 520px; margin-top: 30px; @@ -373,8 +384,9 @@ fieldset { .hero-order button { justify-self: start; - margin-top: 12px; - padding: 0 0 3px; + min-height: 44px; + margin: 8px -8px -4px; + padding: 8px 8px 7px; border: 0; border-bottom: 1px solid white; background: transparent; @@ -501,7 +513,6 @@ fieldset { } .menu-photo, -.ingredient-stack, .menu-poster { aspect-ratio: 4 / 3; position: relative; @@ -512,6 +523,7 @@ fieldset { width: 100%; height: 100%; object-fit: cover; + object-position: center center; } .menu-number { @@ -527,57 +539,17 @@ fieldset { font-size: 12px; } -.ingredient-stack { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 4px; - background: var(--steel); -} - -.ingredient-stack span { - width: 62%; - height: 9%; - display: block; - border-radius: 45% 45% 15% 15%; - background: var(--ink); -} - -.ingredient-stack .bun { - height: 19%; - background: #d89643; -} - -.ingredient-stack .bun.bottom { - height: 11%; - border-radius: 10% 10% 35% 35%; -} - -.ingredient-stack .pickle { - height: 4%; - background: #4e6726; -} - -.ingredient-stack .cheese { - width: 67%; - height: 5%; - background: var(--cheese); - transform: rotate(-2deg); -} - -.ingredient-stack .patty { - height: 11%; - border-radius: 30%; - background: #4a2118; -} - -.ingredient-stack b { +.menu-image-note { position: absolute; - top: 14px; - left: 14px; + right: 10px; + bottom: 10px; + padding: 5px 7px; + background: rgb(255 253 248 / 94%); + color: var(--ink); font-family: var(--font-mono); - font-size: 12px; + font-size: 10px; + font-weight: 600; + line-height: 1.2; } .menu-poster { @@ -697,7 +669,7 @@ fieldset { } .builder-section > .wrap > .section-head .section-kicker { - color: #8ea5ff; + color: var(--blue-soft); } .builder-summary .section-kicker { @@ -724,6 +696,10 @@ fieldset { border-bottom: 1px solid #625f5a; } +.builder-form fieldset + fieldset { + margin-top: 16px; +} + .builder-form legend { width: 100%; margin-bottom: 18px; @@ -733,7 +709,7 @@ fieldset { .builder-form legend span { margin-right: 12px; - color: #8ea5ff; + color: var(--blue-soft); font-family: var(--font-mono); font-size: 11px; } @@ -776,7 +752,7 @@ fieldset { } .choice-row input:checked + span { - border-color: #8ea5ff; + border-color: var(--blue-soft); background: var(--blue); color: white; } @@ -786,7 +762,7 @@ fieldset { } .choice-row input:focus-visible + span { - outline: 3px solid #8ea5ff; + outline: 3px solid var(--blue-soft); outline-offset: 3px; } @@ -992,18 +968,6 @@ fieldset { background: transparent; } -.save-status { - min-height: 23px; - margin-top: 10px; - color: var(--success); - font-size: 11px; - font-weight: 700; -} - -.save-status.is-error { - color: var(--danger); -} - .process-section { padding-block: 0; background: var(--steel); @@ -1097,7 +1061,7 @@ fieldset { .search-box input { width: 100%; min-height: 50px; - padding: 8px 0; + padding: 8px 12px; border: 0; border-radius: 0; background: transparent; @@ -1109,7 +1073,15 @@ fieldset { outline: 0; } +.search-box:focus-within { + outline: 3px solid var(--focus); + outline-offset: 4px; +} + .search-box button { + min-width: 44px; + min-height: 44px; + padding-inline: 10px; border: 0; background: transparent; font-size: 12px; @@ -1255,11 +1227,12 @@ fieldset { } .map-pin { - width: 46px; - height: 46px; + width: 52px; + height: 52px; position: absolute; display: grid; place-items: center; + padding-inline: 8px; border: 3px solid white; border-radius: 50%; background: var(--ink); @@ -1269,8 +1242,8 @@ fieldset { .map-pin span { position: absolute; - top: 50px; - padding: 4px 7px; + top: 56px; + padding: 5px 9px; background: white; color: var(--ink); font-size: 10px; @@ -1779,6 +1752,69 @@ fieldset { } } +@media (min-width: 821px) { + .hero { + grid-template-rows: minmax(0, 1fr) auto; + align-items: stretch; + } + + .hero-copy { + grid-column: 1; + grid-row: 1 / span 2; + } + + .hero-media { + grid-column: 2; + grid-row: 1; + min-height: 0; + } + + .hero-order { + position: static; + grid-column: 2; + grid-row: 2; + width: auto; + min-height: 8.75rem; + margin: 0; + box-shadow: none; + } +} + +.builder-form legend, +.field-label, +.select-grid label { + line-height: 1.45; +} + +.choice-row label > span small, +.menu-foot small { + font-variant-numeric: tabular-nums; +} + +@media (max-width: 820px) { + .hero-order { + position: static; + width: auto; + margin: 0; + box-shadow: none; + } +} + +@media (max-width: 620px) { + .hero-order { + display: grid; + } + + .service-row { + grid-template-columns: minmax(0, 1fr); + } + + .service-row p { + min-width: 0; + overflow-wrap: anywhere; + } +} + @media print { .truth-bar, .site-head, @@ -1805,3 +1841,107 @@ fieldset { border: 1px solid #777; } } + +/* ── 2026-08-30: 초광폭은 확장이 아니라 독립된 구성 상태다 ─────────── */ +@media (min-width: 120rem) { + .site-head .wrap, + .service-strip .wrap, + .section > .wrap, + .site-foot .wrap { + max-width: var(--workbench-wide); + } + + .hero { + width: min(100%, var(--hero-wide)); + min-height: clamp(43rem, 48vw, 54rem); + grid-template-columns: minmax(0, 1fr) minmax(42rem, 1.14fr); + margin-inline: auto; + border-inline: 1px solid var(--line); + } + + .hero-copy { + width: min(100%, var(--copy-wide)); + max-width: none; + justify-self: end; + padding: clamp(5.5rem, 6vw, 8rem) clamp(4rem, 5vw, 6rem); + } + + .hero h1 { + max-width: none; + font-size: clamp(4.5rem, 3.6rem + 1.5vw, 5.25rem); + white-space: nowrap; + } + + .hero h1 br { + display: none; + } + + .hero-wide-space { + display: inline; + } + + .hero-lead { + max-width: 38rem; + } + + .hero-media { + width: min(100%, var(--media-wide)); + min-height: clamp(43rem, 48vw, 54rem); + justify-self: end; + } + + .hero-media img { + object-position: 52% center; + } + + .hero-order { + right: clamp(1.5rem, 3vw, 3.5rem); + width: min(21rem, calc(100% - 3rem)); + } + + .menu-grid, + .builder-layout, + .store-layout { + max-width: var(--workbench-wide); + margin-inline: auto; + } + + .builder-layout { + grid-template-columns: minmax(0, 1fr) minmax(27rem, 34rem); + } + + .process-grid, + .franchise-callout { + width: min(100%, var(--stage-wide)); + margin-inline: auto; + border-inline: 1px solid var(--line); + } + + .process-grid { + /* .wrap's content cap must not silently win over this named wide stage. */ + grid-template-columns: minmax(0, 0.98fr) minmax(0, 1.02fr); + } + + .process-section > .process-grid { + max-width: var(--stage-wide); + } + + .process-copy { + /* Reset both inherited viewport-derived side paddings: leaving the left + value in place leaves a 12px text column at a 2560px viewport. */ + width: 100%; + max-width: none; + justify-self: stretch; + padding-inline: clamp(4rem, 5vw, 6rem); + } + + .process-media, + .franchise-image { + min-height: clamp(42rem, 43vw, 52rem); + } + + .franchise-copy { + max-width: 43rem; + padding-inline: clamp(4rem, 5vw, 6rem); + } +} diff --git a/apps/site/public/work/griddle-club/styles/tokens.css b/apps/site/public/work/griddle-club/styles/tokens.css index d3f157b..f35af66 100644 --- a/apps/site/public/work/griddle-club/styles/tokens.css +++ b/apps/site/public/work/griddle-club/styles/tokens.css @@ -9,6 +9,7 @@ --line-strong: #8a8379; --blue: #2147e7; --blue-dark: #1533ac; + --blue-soft: #8ea5ff; --blue-pale: #dce4ff; --steel: #d9dcda; --cheese: #ffc642; @@ -18,6 +19,12 @@ --font-sans: "Pretendard Variable", Pretendard, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; --font-mono: "IBM Plex Mono", "SFMono-Regular", Consolas, monospace; --wrap: 1180px; + /* 초광폭에서도 히어로와 후속 정보 표면은 같은 폭을 쓰지 않는다. */ + --hero-wide: 2160px; + --stage-wide: 1680px; + --workbench-wide: 1480px; + --copy-wide: 900px; + --media-wide: 1120px; --gutter: clamp(18px, 4vw, 52px); --section: clamp(76px, 10vw, 144px); --space-1: 4px; @@ -41,3 +48,15 @@ --section: 72px; } } + +@media (min-width: 120rem) { + :root { + --wrap: 1320px; + } +} + +@media (min-width: 150rem) { + :root { + --wrap: 1400px; + } +} diff --git a/apps/site/public/work/hannam-jari/admin/index.html b/apps/site/public/work/hannam-jari/admin/index.html index 6315ee8..e6f5704 100644 --- a/apps/site/public/work/hannam-jari/admin/index.html +++ b/apps/site/public/work/hannam-jari/admin/index.html @@ -4,28 +4,28 @@ - + - - + + - + - 한남자리 관리 데모 — 매물 검수 + 한남자리 운영 안내 — 매물 확인 - - - + + + -
          쇼케이스 · 가상 브랜드 · 모든 사무소, 매물, 고객과 기록은 합성 예시입니다
          +
          안내 · 예시 자료 · 사무소, 매물, 고객과 기록은 실제 정보가 아니며 광고·연락·저장은 연결되지 않습니다
          @@ -55,7 +55,7 @@
          - +
          @@ -67,13 +67,13 @@
          -
          쇼케이스 · 가상 브랜드자료 기준 2026.08.29
          +
          예시 자료 · 가상 브랜드자료 기준 2026.08.29

          매물 검수 대기열

          게시 전에 매물 사실, 표시 항목, AI 근거와 변경 이력을 한 자리에서 확인합니다.

          - - + +
          @@ -84,48 +84,48 @@
          - + - +
          -

          현재 대기열

          6개 예시
          +

          현재 대기열

          6건
          차단확인
          - + - - + + - - + + - + - - + + - - + + - - + +
          쇼케이스용 예시 매물 검수 대기열예시 매물 확인 대기열
          매물거래예시 조건마지막 확인표시 검수AI 검토담당
          매매연립주택38억 원전용 118.42㎡2026.08.272일 전 · 모의2개 차단검토 전김김유진매매연립주택38억 원전용 118.42㎡2026.08.272일 전 · 예시2개 확인 필요검토 전김김유진
          전세공동주택전세 22억전용 142.80㎡2026.08.263일 전 · 모의데모 통과수정 승인박박소연전세공동주택전세 22억전용 142.80㎡2026.08.263일 전 · 예시안내 확인수정 확인박박소연
          월세다세대주택5억 · 월 1,200만전용 140.84㎡2026.08.1118일 전 · 오래됨다시 확인오래됨김김유진
          매매단독주택상담 종료공개 목록 제외2026.08.281일 전 · 모의게시 안 함종료박박소연매매단독주택상담 종료공개 목록 제외2026.08.281일 전 · 예시공개 안 함종료박박소연
          전세공동주택조건 작성 중면적 입력됨확인 전모의 서류 없음5개 차단실행 전최최민서전세공동주택조건 작성 중면적 입력됨확인 전참고 자료 없음5개 확인 필요분석 전최최민서
          매매공동주택41억 원전용 151.20㎡2026.08.254일 전 · 모의동의 대기실행 실패최최민서매매공동주택41억 원전용 151.20㎡2026.08.254일 전 · 예시동의 대기분석 확인 필요최최민서
          @@ -135,7 +135,7 @@

          대기열을 불러오는 중입니다.

          @@ -143,8 +143,8 @@
          -
          역할에 따라 달라지는 행동

          권한 방어선

          버튼을 숨기는 데서 끝내지 않고 게시 시점에 역할, 게이트와 객체 버전을 다시 확인하는 모델입니다.

          +
          역할에 따라 달라지는 행동

          권한 기준

          게시 전에는 역할, 확인 항목과 최신 자료를 다시 검토합니다.

          사무소 관리자

          사무소 연결, 역할, 모든 게시 관리

          감사 로그 수정 불가
          공인중개사

          법정 검수, AI 승인, 게시와 중단

          역할 관리자 변경 불가
          중개보조 계정

          초안, 문의 정리, 일정 등록

          검수 승인과 게시 불가
          콘텐츠 편집자

          설명, 이미지, 미리보기

          가격, 법정 필드와 고객 정보 수정 불가
          -

          데모 설정 원칙

          실제 연락, 저장 서버, 광고 채널과 등록정보 연결을 비활성 상태로 유지합니다.

          +

          예시 자료 안내

          실제 연락, 저장, 광고 등록과 연결하지 않습니다.

          -
          PUBLIC_REAL_AD

          실제 광고를 게시할 수 없습니다.

          +
          실제 광고 안내

          실제 광고를 게시할 수 없습니다.

          -

          이 화면은 가상 사무소와 합성 예시 매물로 만든 쇼케이스입니다. 아래 항목은 더미값으로 채워 통과시키지 않습니다.

          +

          이 화면의 사무소와 매물은 예시 자료입니다. 실제 광고에 필요한 항목은 임의의 값으로 채우지 않습니다.

          1. 실제 사무소 명칭연결 안 됨
          2. 실제 사무소 소재지연결 안 됨
          3. 실제 연락처연결 안 됨
          4. 실제 등록번호연결 안 됨
          5. 개업공인중개사 성명연결 안 됨
          6. 실제 중개의뢰 관계없음
          7. 실제 거래 가능 상태확인 불가
          -

          쇼케이스 미리보기 채널은 데모 고지와 생성 이미지 출처를 갖춰 별도로 열 수 있습니다.

          +

          공개 안내에는 예시 자료 표시와 생성 이미지 출처를 함께 둡니다.

          @@ -280,8 +280,8 @@
          -
          SHOWCASE

          미리보기 채널은 열 수 있습니다.

          -

          상시 데모 고지, 개별 예시 배지, 생성 이미지 출처, 연락 기능 비활성, 실제 주소와 등록번호 없음, AI 데모 표시를 확인했습니다.

          공개 상세 보기
          +
          공개 안내

          예시 자료는 공개 화면에서 볼 수 있습니다.

          +

          예시 자료 표시, 개별 예시 매물 표기, 생성 이미지 출처, 실제 연락 기능 없음, 실제 주소와 등록번호 없음, AI 결과는 참고용이라는 안내를 확인했습니다.

          공개 상세 보기
          diff --git a/apps/site/public/work/hannam-jari/design.md b/apps/site/public/work/hannam-jari/design.md new file mode 100644 index 0000000..048effb --- /dev/null +++ b/apps/site/public/work/hannam-jari/design.md @@ -0,0 +1,24 @@ +# 한남자리 디자인 기록 + +## 브리프 + +- 무엇을: 다섯 조건으로 예시 주거 후보를 비교하고 공개 전 확인 책임을 분리해 보여 주는 브리핑과 운영 화면. +- 누구에게: 조건을 정리하는 이용자와 검수 상태를 확인하는 운영 담당자. +- 제약: 가상 매물·AI 참고·생성 이미지·미전송 안내와 기존 선택·검수·이력·대화상자 동작을 보존한다. + +## 판단 기준 + +| 축 | 질문 | 적용 | +| --- | --- | --- | +| Warde · 정보 전달 | 다섯 조건의 라벨·입력값·결과 행동이 한 번에 읽히는가 | 13px 이상 라벨, 16px 입력, 결과 행동을 같은 조건판에 유지 | +| Ruder · 비교 변수 | 후보 조건의 라벨과 값을 섞지 않고 비교하는가 | 조건 행의 라벨·값·보조 메모를 세 단계로 분리 | +| Albers · 상태 맥락 | 가상 자료·AI 참고·중개사 확인의 책임이 구분되는가 | 상태 텍스트와 색조를 함께 사용하고 검수판의 간격·정렬을 통일 | + +Warde, Ruder, Albers는 정보 전달·비교 변수·상태 맥락을 검토하는 참고 질문이며 인과나 성능 법칙이 아니다. + +## 역할 토큰과 검증 + +- `--brief-label-size`, `--brief-input-size`, `--brief-panel-radius`, `--brief-rule`, `--admin-body-size`, `--admin-meta-size`가 공개·운영 표면의 역할을 관리한다. +- `verify-final` 18개 묶음은 16개가 즉시 통과했다. 전체 묶음의 invariant·visual 검사는 Gaon·Dure를 대상으로 하며, 나머지 2개는 수정 뒤 release 독립 재실행에서 ALL PASS·ALL MATCH였다. +- root는 28개 모바일, 21개 데스크톱, 7개 하위 경로와 30개 앱 상태를 직접 검토해 수용했다. stress 112건은 hard failure 0이며, 가로 넘침 4건은 targeted fix 뒤 390px 재측정에서 0이다. +- 이 기록은 렌더·계약 범위의 현재 결과다. 모든 폭·키보드 경로·인쇄 등 개별 기능을 완전 재실행했다는 뜻이 아니며, 참여자 과업 효과도 미측정이다. diff --git a/apps/site/public/work/hannam-jari/index.html b/apps/site/public/work/hannam-jari/index.html index ee391f9..7a2a823 100644 --- a/apps/site/public/work/hannam-jari/index.html +++ b/apps/site/public/work/hannam-jari/index.html @@ -4,7 +4,7 @@ - + @@ -15,28 +15,27 @@ 한남자리 — 내 기준에 맞는 집부터 - - - + + + -
          디자인 쇼케이스 · 가상 브랜드 · 상담은 접수되지 않습니다
          +
          안내 · 예시 자료 · 입력 내용은 전송되지 않으며 상담은 접수되지 않습니다
          @@ -45,7 +44,7 @@

          한남 생활권 맞춤 중개

          한남에서, 내 기준에 맞는 집부터.

          -

          예산과 면적, 입주 계획을 먼저 정리합니다. AI가 후보를 비교하고 공인중개사가 다시 확인합니다.

          +

          예산과 면적, 입주 계획을 먼저 정리합니다. 입력한 기준을 후보와 대조하고, 계약 전에는 공인중개사가 다시 확인합니다.

          매물 보기 @@ -73,8 +72,8 @@ -
          -

          입력은 전송되지 않으며, 저장을 선택하면 이 브라우저에만 보관됩니다.

          +
          +

          입력은 전송되지 않으며, 임시 보관을 선택하면 지금 사용 중인 기기에만 남습니다.

          @@ -82,11 +81,11 @@

          내 조건 브리핑

          맞는 이유와
          조정할 지점을 나눕니다.

          -

          화면에 입력한 값과 후보 정보를 이 브라우저에서 대조합니다.

          +

          입력한 기준과 후보 정보를 같은 항목으로 비교합니다.

          -
          예시 AI 브리핑 · 모의 조건 비교 · 공인중개사 확인 전아직 분석하지 않았습니다
          +
          안내용 조건 비교 · 공인중개사 확인 전아직 분석하지 않았습니다

          내 조건을 먼저 알려 주세요.

          분석을 실행하면 세 후보 가운데 조건과 가까운 집을 고르고, 이유를 세 묶음으로 정리합니다.

          @@ -195,19 +194,19 @@
        • 02
          후보 비교

          서로 다른 집의 차이를 같은 기준으로 대조합니다.

        • 03
          권리·현장 확인

          서류와 현장에서 확인한 뒤 최종 판단합니다.

        • - +
          한남자리개인 주거 브리핑 데스크
          -

          한남자리는 가상 브랜드이며 등록 공인중개사무소나 거래 서비스를 제공하지 않습니다.

          - +

          한남자리는 예시 자료로 구성한 서비스 화면입니다. 등록 공인중개사무소나 거래 서비스를 제공하지 않습니다.

          +
          -
          상담 순서 살펴보기

          중개사에게 무엇을 넘길까요?

          +
          상담 전 확인 항목

          중개사와 무엇을 먼저 확인할까요?

          연락처를 받거나 입력 내용을 저장하지 않습니다.

          정원형 연립주택을 기준으로 준비할 항목을 골라 보세요.

          @@ -220,6 +219,6 @@
          - + diff --git a/apps/site/public/work/hannam-jari/og.png b/apps/site/public/work/hannam-jari/og.png index 2d59703..b635e63 100644 Binary files a/apps/site/public/work/hannam-jari/og.png and b/apps/site/public/work/hannam-jari/og.png differ diff --git a/apps/site/public/work/hannam-jari/scripts/admin.js b/apps/site/public/work/hannam-jari/scripts/admin.js index c322a6e..236e26e 100644 --- a/apps/site/public/work/hannam-jari/scripts/admin.js +++ b/apps/site/public/work/hannam-jari/scripts/admin.js @@ -22,7 +22,7 @@ }, "DEMO-HJ-102": { title: "한강 가까운 복층 주거", - status: "쇼케이스 공개", + status: "예시 공개", statusClass: "status-pass", trade: "전세", type: "공동주택", @@ -32,7 +32,7 @@ moveIn: "2026.11.30 이후 협의", image: "../assets/hannam-evening-640.webp", imageAlt: "서울 언덕길의 석재 주거 건물 연출 이미지", - blockers: "데모 통과", + blockers: "안내 확인", ai: "수정 후 승인" }, "DEMO-HJ-103": { @@ -57,7 +57,7 @@ trade: "매매", type: "단독주택", price: "상담 종료", - area: "예시 공개 종료", + area: "목록에서 제외", rooms: "공개 목록 제외", moveIn: "해당 없음", image: "../assets/hannam-evening-640.webp", @@ -162,7 +162,7 @@ if (!inspector) return; inspector.classList.add("is-open"); workbench?.classList.remove("is-inspector-closed"); - $("[data-inspector-id]", inspector).textContent = `${id} · 예시 매물`; + $("[data-inspector-id]", inspector).textContent = `자료번호 ${id.replace("DEMO-HJ-", "")} · 예시 매물`; $("[data-inspector-title]", inspector).textContent = detail.title; const status = $("[data-inspector-status]", inspector); status.textContent = detail.status; @@ -180,7 +180,7 @@ if (basicGrid) { const pairs = [ ["거래 형태", detail.trade], - ["예시 가격", detail.price], + ["표시 가격", detail.price], ["유형", detail.type], ["전용 면적", detail.area], ["방과 욕실", detail.rooms], @@ -199,7 +199,7 @@ updateInspectorBackdrop(); if (focus) $("[data-close-inspector]", inspector)?.focus(); - announce(`${detail.title} 조사관을 열었습니다. ${detail.status} 상태입니다.`); + announce(`${detail.title} 상세 정보를 열었습니다. ${detail.status} 상태입니다.`); }; const closeInspector = ({ restoreFocus = false } = {}) => { @@ -216,7 +216,7 @@ if (restoreFocus && previousId) { $(`[data-queue-row][data-id="${previousId}"] [data-select-row]`)?.focus(); } - announce("조사관과 선택 행을 함께 닫았습니다."); + announce("선택한 매물 정보를 닫았습니다."); }; const activateTab = (name, focus = false) => { @@ -258,7 +258,7 @@ const updateResultCount = () => { const visible = getRows().filter((row) => !row.classList.contains("is-hidden")); const result = $("[data-result-count]"); - if (result) result.textContent = `${visible.length}개 예시`; + if (result) result.textContent = `${visible.length}건`; const empty = $("[data-queue-empty]"); if (state.mode === "normal") empty.hidden = visible.length !== 0; return visible.length; @@ -276,7 +276,7 @@ const emptyTitle = $("[data-empty-title]"); const emptyCopy = $("[data-empty-copy]"); if (count === 0 && state.mode === "normal") { - emptyTitle.textContent = "현재 조건에 맞는 예시가 없습니다."; + emptyTitle.textContent = "현재 조건에 맞는 항목이 없습니다."; emptyCopy.textContent = "검색어와 필터를 초기화하면 전체 대기열을 다시 볼 수 있습니다."; } }; @@ -320,9 +320,9 @@ if (mode === "empty") { const empty = $("[data-queue-empty]"); empty.hidden = false; - $("[data-empty-title]").textContent = "아직 접수된 예시 매물이 없습니다."; - $("[data-empty-copy]").textContent = "새 예시 초안을 만들거나 다른 상태를 시연할 수 있습니다."; - announce("빈 대기열 상태를 시연합니다."); + $("[data-empty-title]").textContent = "아직 표시할 항목이 없습니다."; + $("[data-empty-copy]").textContent = "검색어와 필터를 초기화하면 전체 목록을 다시 볼 수 있습니다."; + announce("현재 표시할 항목이 없습니다."); return; } @@ -333,8 +333,8 @@ } if (mode === "save-error") { - showBanner("저장 경로를 확인할 수 없습니다.", "입력은 화면에 남지만 저장 성공으로 표시하지 않습니다. 수정 시연을 누르면 실패 처리를 확인할 수 있습니다.", "error"); - announce("저장 실패 상태를 시연합니다."); + showBanner("지금은 변경 내용을 보관할 수 없습니다.", "입력은 화면에 남지만 완료로 표시하지 않습니다.", "error"); + announce("저장할 수 없는 상태입니다."); return; } @@ -347,25 +347,25 @@ status.textContent = "자료 오래됨"; status.className = "status-badge status-warn"; } - announce("자료 오래됨 상태를 시연합니다."); + announce("자료가 오래되어 다시 확인이 필요합니다."); return; } if (mode === "conflict") { - showBanner("다른 예시 담당자가 먼저 수정했습니다.", "현재 버전 7과 서버 예시 버전 8의 차이를 확인한 뒤 다시 저장해야 합니다.", "error"); - announce("버전 충돌 상태를 시연합니다."); + showBanner("다른 담당자가 먼저 수정했습니다.", "현재 내용과 최신 자료의 차이를 확인한 뒤 다시 저장해야 합니다.", "error"); + announce("최신 자료와 차이가 있어 다시 확인이 필요합니다."); return; } if (mode === "permission") { document.body.classList.add("is-permission-limited"); $$('[data-review-ai], [data-simulate-save], [data-new-draft]').forEach((button) => button.disabled = true); - showBanner("중개보조 예시 권한으로 보는 중입니다.", "초안과 일정은 정리할 수 있지만 법정 검수 승인, AI 최종 승인과 게시를 할 수 없습니다.", "info"); - announce("권한 제한 상태를 시연합니다."); + showBanner("중개보조 권한으로 보는 중입니다.", "초안과 일정은 정리할 수 있지만 법정 검수 승인, AI 최종 승인과 게시를 할 수 없습니다.", "info"); + announce("현재 권한으로는 승인과 게시를 할 수 없습니다."); return; } - announce("정상 데모 상태로 돌아왔습니다."); + announce("기본 목록을 다시 보여 줍니다."); }; const openDialog = (dialog) => { @@ -380,11 +380,11 @@ const simulateSave = () => { if (state.mode === "permission") { - announce("현재 예시 권한으로는 매물 정보를 수정할 수 없습니다."); + announce("현재 권한으로는 매물 정보를 수정할 수 없습니다."); return; } if (state.mode === "conflict") { - showBanner("버전 충돌로 저장하지 않았습니다.", "서버 예시 버전 8을 다시 불러오거나 현재 수정을 별도 초안으로 남겨야 합니다.", "error"); + showBanner("최신 자료와 차이가 있어 저장하지 않았습니다.", "최신 내용을 다시 확인하거나 현재 수정을 별도 초안으로 남겨야 합니다.", "error"); announce("버전 충돌로 저장하지 않았습니다."); return; } @@ -393,12 +393,12 @@ announce("저장에 실패했습니다. 성공으로 처리하지 않았습니다."); return; } - announce("수정 시연을 마쳤습니다. 서버가 없는 데모라 실제 저장하지 않았습니다."); + announce("변경 내용을 확인했습니다. 실제로 저장되거나 전송되지는 않습니다."); }; const createDraft = () => { if (state.mode === "permission") { - announce("현재 예시 권한으로는 새 초안을 만들 수 없습니다."); + announce("현재 권한으로는 새 초안을 만들 수 없습니다."); return; } if (state.draftCreated) { @@ -407,7 +407,7 @@ } state.draftCreated = true; listingDetails["DEMO-HJ-NEW"] = { - title: "제목 없는 새 예시 초안", + title: "제목 없는 새 항목", status: "초안", statusClass: "status-demo", trade: "미선택", @@ -427,15 +427,15 @@ row.dataset.id = "DEMO-HJ-NEW"; row.dataset.status = "draft"; row.dataset.updated = new Date().toISOString(); - row.dataset.title = "제목 없는 새 예시 초안"; + row.dataset.title = "제목 없는 새 항목"; row.setAttribute("aria-selected", "false"); row.innerHTML = ` - - 미선택유형 미선택입력 전면적 입력 전방금데모 초안입력 대기실행 전김김유진`; + + 미선택유형 미선택입력 전면적 입력 전방금새 항목입력 대기분석 전김김유진`; queueBody.prepend(row); applyFilters(); openInspector("DEMO-HJ-NEW", true); - announce("새 예시 초안을 만들었습니다. 외부 서버에는 저장하지 않았습니다."); + announce("새 항목을 만들었습니다. 실제로 저장되거나 전송되지는 않습니다."); }; const handleRowSelection = (button) => { @@ -523,7 +523,7 @@ $("[data-review-ai]")?.addEventListener("click", (event) => { if (state.mode === "permission") { - announce("현재 예시 권한으로는 AI 결과를 승인할 수 없습니다."); + announce("현재 권한으로는 AI 결과를 승인할 수 없습니다."); return; } event.currentTarget.textContent = "수정 후 승인됨"; @@ -533,20 +533,20 @@ badge.textContent = "수정 후 승인"; badge.className = "status-badge status-pass"; } - announce("AI 참고 분석을 수정 후 승인 상태로 바꿨습니다. 데모 외부에는 게시하지 않았습니다."); + announce("AI 참고 결과를 수정 후 확인 상태로 바꿨습니다. 실제 광고에는 사용되지 않습니다."); }); $$('[data-claim-action]').forEach((button) => button.addEventListener("click", () => { button.textContent = button.dataset.claimAction === "edit" ? "수정 반영" : "확인됨"; button.disabled = true; - announce("주장 검토 상태를 데모 안에서만 바꿨습니다."); + announce("표시 문구의 검토 상태를 이 화면에서만 바꿨습니다."); })); $("[data-reschedule]")?.addEventListener("click", (event) => { const card = event.currentTarget.closest(".appointment-card"); const time = $("div > strong", card); time.textContent = time.textContent.includes("3:30") ? "오후 5:00~5:30" : "오후 3:30~4:00"; - announce("예시 상담 시간을 바꿨습니다. 외부 알림은 보내지 않았습니다."); + announce("안내용 상담 시간을 바꿨습니다. 알림은 전송되지 않았습니다."); }); $("[data-simulate-log-failure]")?.addEventListener("click", () => { diff --git a/apps/site/public/work/hannam-jari/scripts/landing.js b/apps/site/public/work/hannam-jari/scripts/landing.js index 877c8b1..0a88dcc 100644 --- a/apps/site/public/work/hannam-jari/scripts/landing.js +++ b/apps/site/public/work/hannam-jari/scripts/landing.js @@ -386,7 +386,7 @@ state.selectedId = best.id; renderSelection(); $("#briefing")?.scrollIntoView({ behavior: window.matchMedia("(prefers-reduced-motion: reduce)").matches ? "auto" : "smooth" }); - announce(`${best.name}을 가장 가까운 후보로 골라 세 묶음의 브리핑을 만들었습니다.`); + announce(`${best.name}을 가장 가까운 후보로 골랐습니다. 맞는 점, 조정할 점, 확인할 점을 정리했습니다.`); }; const markConditionsChanged = () => { @@ -400,9 +400,9 @@ if (!form.reportValidity()) return; try { window.localStorage.setItem(STORAGE_KEY, JSON.stringify(readConditions())); - announce("현재 조건을 이 브라우저에 저장했습니다."); + announce("현재 조건을 지금 사용 중인 기기에 임시 보관했습니다."); } catch { - announce("브라우저 저장소를 사용할 수 없어 조건을 저장하지 않았습니다."); + announce("지금 사용 중인 기기에 조건을 보관할 수 없습니다."); } }; diff --git a/apps/site/public/work/hannam-jari/styles/admin.css b/apps/site/public/work/hannam-jari/styles/admin.css index a9a0985..89ddc92 100644 --- a/apps/site/public/work/hannam-jari/styles/admin.css +++ b/apps/site/public/work/hannam-jari/styles/admin.css @@ -1,5 +1,5 @@ .admin-body { - min-width: 20rem; + min-width: 0; color: #1c1c1a; background: #f3f4f3; } @@ -237,7 +237,7 @@ display: inline-flex; align-items: center; gap: 0.55rem; - padding: 0.42rem 0.6rem; + padding: 0.42rem 0.7rem; } .topbar-actions .icon-button { @@ -390,10 +390,10 @@ gap: 0.5rem; align-items: center; margin-bottom: 0.75rem; - padding: 0.7rem; + padding: 0.875rem; background: #fff; - border: 1px solid #dedfdd; - border-radius: 0.5rem; + border: 1px solid var(--brief-rule); + border-radius: var(--brief-panel-radius); } .search-field { @@ -412,6 +412,7 @@ width: 100%; min-height: 2.75rem; min-width: 0; + padding-inline: 0.5rem; color: #222320; background: transparent; border: 0; @@ -419,6 +420,11 @@ font-size: 0.72rem; } +.search-field:focus-within { + border-color: var(--focus); + box-shadow: 0 0 0 2px color-mix(in srgb, var(--focus) 32%, transparent); +} + .queue-toolbar select { min-height: 2.75rem; padding: 0.42rem 1.8rem 0.42rem 0.65rem; @@ -459,7 +465,8 @@ .settings-proof { background: #fff; border: 1px solid #dedfdd; - border-radius: 0.55rem; + border-radius: var(--brief-panel-radius); + box-shadow: none; } .queue-panel { @@ -522,7 +529,11 @@ } .table-scroll { + min-width: 0; + max-width: 100%; overflow: auto; + overscroll-behavior-inline: contain; + scrollbar-gutter: stable both-edges; scrollbar-width: thin; } @@ -535,9 +546,9 @@ .queue-table th, .queue-table td { - padding: 0.7rem 0.6rem; + padding: 0.8rem 0.875rem; border-bottom: 1px solid #ecedea; - font-size: 0.66rem; + font-size: var(--admin-body-size); text-align: left; vertical-align: middle; } @@ -548,7 +559,7 @@ top: 0; color: #777973; background: #fafbfa; - font-size: 0.58rem; + font-size: var(--admin-meta-size); font-weight: 730; } @@ -605,7 +616,7 @@ .queue-table td > strong + small { margin-top: 0.13rem; color: #62665f; - font-size: 0.57rem; + font-size: var(--admin-meta-size); } .row-title { @@ -822,6 +833,13 @@ to { opacity: 1; } } +@media (prefers-reduced-motion: reduce) { + .queue-loading > span { + animation: none; + opacity: 0.72; + } +} + .queue-empty > span { display: grid; width: 3rem; @@ -1087,7 +1105,7 @@ .text-button { min-width: 2.75rem; min-height: 2.75rem; - padding: 0.4rem; + padding: 0.5rem; color: #6f5420; background: transparent; border: 0; @@ -1510,23 +1528,26 @@ .claim-review article { margin-bottom: 0.5rem; - padding: 0.65rem; + padding: 0.75rem; background: #fafbfa; - border: 1px solid #e1e2df; + border: 1px solid var(--brief-rule); border-left-width: 3px; - border-radius: 0.35rem; + border-radius: var(--brief-panel-radius); } .claim-review article.is-fact { border-left-color: #3d7c5d; + background: var(--review-fact-bg); } .claim-review article.is-unknown { border-left-color: #b1832d; + background: var(--review-unknown-bg); } .claim-review article.is-edited { border-left-color: #9d3f34; + background: var(--review-edited-bg); } .claim-review header { @@ -1791,9 +1812,15 @@ } .admin-dialog { + position: fixed; + inset: 0; + box-sizing: border-box; width: min(35rem, calc(100% - 2rem)); max-height: calc(100dvh - 2rem); + margin: auto; padding: 0; + overflow: auto; + overscroll-behavior: contain; color: #20211f; background: #fff; border: 0; @@ -1801,6 +1828,10 @@ box-shadow: 0 1.5rem 5rem rgba(20, 20, 19, 0.28); } +html:has(.admin-dialog[open]) { + overflow: hidden; +} + .admin-dialog::backdrop { background: rgba(20, 20, 19, 0.62); backdrop-filter: blur(2px); @@ -1923,6 +1954,13 @@ font-size: 0.65rem; } +@media (min-width: 120rem) { + .admin-content { + max-width: 122rem; + padding: 2rem; + } +} + @media (max-width: 92rem) { .admin-workbench { grid-template-columns: minmax(35rem, 1fr) 23rem; @@ -1977,6 +2015,33 @@ } } +/* 짧은 가로 화면은 조사관을 덮는 시트로 다뤄야 한다. + 미디어·부제까지 고정하면 scroll 영역이 0px로 수축해 핵심 검토 내용이 전부 사라진다. */ +@media (max-width: 76rem) and (max-height: 40rem) { + .inspector { + top: 0; + max-height: 100dvh; + } + + .inspector-header { + padding: 0.65rem 0.8rem; + } + + .inspector-header small, + .inspector-media { + display: none; + } + + .inspector-tabs button { + min-height: 2.25rem; + padding-block: 0.45rem; + } + + .inspector-actions { + padding: 0.5rem; + } +} + @media (max-width: 64rem) { .admin-shell { grid-template-columns: 13.5rem minmax(0, 1fr); @@ -2034,11 +2099,29 @@ } .admin-topbar { + min-width: 0; + gap: 0.5rem; padding: 0 0.8rem; } .breadcrumb { margin-right: auto; + min-width: 0; + overflow-wrap: anywhere; + } + + .topbar-actions { + min-width: 0; + flex: 0 0 auto; + } + + .account-button { + display: grid; + width: 2.75rem; + min-width: 0; + flex: 0 0 2.75rem; + place-items: center; + padding: 0; } .icon-button kbd, @@ -2087,7 +2170,7 @@ @media (max-width: 34rem) { .demo-strip { min-height: 2.3rem; - padding-inline: 0.5rem; + padding-inline: 0.75rem; } .admin-sidebar, @@ -2141,6 +2224,29 @@ } } +/* 이 규칙은 좁은 폭 보정 뒤에 둬야 한다. 그렇지 않으면 34rem 보정의 top 값이 + 짧은 화면 시트보다 뒤에 적용되어 스크롤 영역이 다시 0px가 된다. */ +@media (max-width: 76rem) and (max-height: 40rem) { + .inspector { + top: 0; + max-height: 100dvh; + } + + .channel-gates { + grid-template-columns: repeat(2, minmax(0, 1fr)); + padding: 0.35rem; + gap: 0.35rem; + } + + .channel-gate { + padding: 0.35rem 0.4rem; + } + + .channel-gate small { + display: none; + } +} + /* 작은 운영 문구도 본문 대비 기준을 넘도록 중립색을 한 단계 진하게 쓴다. */ .admin-main small, .admin-main dt, diff --git a/apps/site/public/work/hannam-jari/styles/landing.css b/apps/site/public/work/hannam-jari/styles/landing.css index c82ce0b..3b011ba 100644 --- a/apps/site/public/work/hannam-jari/styles/landing.css +++ b/apps/site/public/work/hannam-jari/styles/landing.css @@ -100,12 +100,6 @@ body { color: var(--slate-deep); } -.site-nav .nav-admin { - padding: 0 0.95rem; - color: var(--sheet); - background: var(--charcoal); -} - .menu-button { display: none; width: 2.75rem; @@ -165,6 +159,7 @@ body { .brief-hero { display: grid; + min-width: 0; width: min(100%, 96rem); margin: 0 auto; padding: 3rem 2rem 0; @@ -292,12 +287,14 @@ body { grid-area: dock; display: grid; grid-template-columns: minmax(10rem, 1.15fr) repeat(5, minmax(7.5rem, 0.8fr)) minmax(10rem, 1fr); - gap: 0.8rem 1rem; + min-width: 0; + gap: 1rem; align-items: end; margin: -5.5rem 2.5rem 0; padding: 1.35rem 1.5rem 1rem; background: var(--sheet); border-top: 3px solid var(--charcoal); + border-bottom: 1px solid var(--brief-rule); box-shadow: 0 6px 0 var(--paper-shadow), 0 1.4rem 3rem rgba(44, 45, 40, 0.1); } @@ -312,34 +309,35 @@ body { .dock-heading span { color: var(--slate-deep); - font-size: 0.62rem; + font-size: var(--brief-label-size); font-weight: 760; } .dock-heading strong { margin-top: 0.2rem; - font-size: 0.8rem; + font-size: 0.9375rem; } .dock-field > span:first-child { display: block; margin-bottom: 0.3rem; color: #646963; - font-size: 0.61rem; + font-size: var(--brief-label-size); font-weight: 710; } .dock-field input, .dock-field select { width: 100%; - min-height: 2.75rem; - padding: 0.55rem 0.4rem; + min-height: 3rem; + padding: 0.55rem 0.5rem; color: var(--charcoal); background: transparent; border: 0; border-bottom: 1px solid #90948e; border-radius: 0; - font-size: 0.78rem; + font-size: var(--brief-input-size); + font-variant-numeric: tabular-nums; font-weight: 710; } @@ -373,7 +371,7 @@ body { .save-button { min-height: 2.75rem; - padding: 0.35rem; + padding: 0.5rem; color: #555b56; background: transparent; border: 0; @@ -409,6 +407,17 @@ body { gap: clamp(3rem, 7vw, 7rem); } +/* 1920px 이상에서는 비교·서류 표면만 조금 넓혀 여백이 본문을 압도하지 않게 한다. */ +@media (min-width: 120rem) { + .brief-hero { + width: min(100%, 104rem); + } + + .briefing-section { + width: min(100% - 4rem, 100rem); + } +} + .briefing-heading { align-self: center; } @@ -537,25 +546,34 @@ body { .compare-heading { display: grid; + min-width: 0; align-items: end; - grid-template-columns: minmax(28rem, 1fr) minmax(17rem, 0.5fr) auto; + grid-template-columns: minmax(0, 1fr) minmax(0, 0.5fr) minmax(0, auto); gap: 3rem; margin-bottom: 3.5rem; } .compare-heading > p { + min-width: 0; margin: 0 0 0.45rem; color: #5a605b; font-size: 0.8rem; } +.compare-heading h2 { + overflow-wrap: anywhere; + word-break: normal; +} + .unit-switches { display: flex; + min-width: 0; gap: 0.6rem; } .unit-switches > div { display: flex; + min-width: 0; border: 1px solid var(--hairline); } @@ -1035,8 +1053,9 @@ body { .handoff-section { display: grid; + min-width: 0; align-items: center; - grid-template-columns: minmax(24rem, 0.8fr) minmax(28rem, 1fr) auto; + grid-template-columns: minmax(0, 0.8fr) minmax(0, 1fr) minmax(0, auto); gap: clamp(3rem, 7vw, 7rem); padding: clamp(6rem, 9vw, 9rem) max(2rem, calc((100% - 92rem) / 2)); color: var(--sheet); @@ -1047,6 +1066,18 @@ body { color: #bec7cc; } +.handoff-section > header, +.handoff-steps, +.handoff-cta { + min-width: 0; +} + +.handoff-section h2, +.handoff-steps p, +.handoff-cta { + overflow-wrap: anywhere; +} + .handoff-steps { margin: 0; padding: 0; @@ -1122,9 +1153,15 @@ body { } .consult-dialog { + position: fixed; + inset: 0; + box-sizing: border-box; width: min(36rem, calc(100% - 2rem)); max-height: calc(100svh - 2rem); + margin: auto; padding: 0; + overflow: auto; + overscroll-behavior: contain; color: var(--charcoal); background: var(--sheet); border: 1px solid var(--charcoal); @@ -1132,6 +1169,10 @@ body { box-shadow: 0 2rem 5rem rgba(0, 0, 0, 0.28); } +html:has(.consult-dialog[open]) { + overflow: hidden; +} + .consult-dialog::backdrop { background: rgba(18, 19, 17, 0.72); } @@ -1298,12 +1339,16 @@ body { z-index: 90; top: 6.5rem; right: 0; + bottom: 0; left: 0; display: none; align-items: stretch; flex-direction: column; gap: 0; + max-height: calc(100dvh - 6.5rem); padding: 0.75rem 1.25rem 1.25rem; + overflow-y: auto; + overscroll-behavior: contain; background: var(--sheet); border-bottom: 1px solid var(--hairline); } @@ -1312,8 +1357,7 @@ body { display: flex; } - .site-nav a, - .site-nav .nav-admin { + .site-nav a { min-height: 3rem; padding: 0 0.5rem; color: var(--charcoal); @@ -1324,15 +1368,15 @@ body { .brief-hero { padding: 0; grid-template-areas: "masthead" "scene" "dock"; - grid-template-columns: 1fr; + grid-template-columns: minmax(0, 1fr); } .masthead { - padding: 5rem max(1.25rem, calc((100% - 44rem) / 2)) 4rem; + padding: 5rem max(1.25rem, calc((100% - 44rem) / 2)) var(--space-10); } .hero-scene { - height: min(70vw, 40rem); + height: min(70vw, 38rem); min-height: 32rem; } @@ -1371,7 +1415,7 @@ body { } .compare-heading { - grid-template-columns: 1fr auto; + grid-template-columns: minmax(0, 1fr) minmax(0, auto); } .compare-heading > p { @@ -1439,7 +1483,7 @@ body { } .handoff-section { - grid-template-columns: 1fr; + grid-template-columns: minmax(0, 1fr); } .handoff-cta { @@ -1456,6 +1500,7 @@ body { } @media (max-width: 40rem) { + .handoff-cta { width: 100%; min-width: 0; } .demo-strip { font-size: 0.62rem; } @@ -1576,7 +1621,7 @@ body { } .compare-heading { - grid-template-columns: 1fr; + grid-template-columns: minmax(0, 1fr); gap: 1.5rem; margin-bottom: 2.5rem; } diff --git a/apps/site/public/work/hannam-jari/styles/tokens.css b/apps/site/public/work/hannam-jari/styles/tokens.css index 176eca7..12cc8ae 100644 --- a/apps/site/public/work/hannam-jari/styles/tokens.css +++ b/apps/site/public/work/hannam-jari/styles/tokens.css @@ -51,6 +51,15 @@ --radius-md: 0.75rem; --radius-lg: 1.25rem; --transition: 180ms cubic-bezier(0.22, 1, 0.36, 1); + --brief-label-size: 0.8125rem; + --brief-input-size: 1rem; + --brief-panel-radius: 0.5rem; + --brief-rule: var(--line-light); + --admin-body-size: 0.8125rem; + --admin-meta-size: 0.75rem; + --review-fact-bg: #f2f8f4; + --review-unknown-bg: #fff8e8; + --review-edited-bg: #fdf0ed; } *, diff --git a/apps/site/public/work/hyang-incense/assets/fonts/LICENSE.html b/apps/site/public/work/hyang-incense/assets/fonts/LICENSE.html new file mode 100644 index 0000000..571387d --- /dev/null +++ b/apps/site/public/work/hyang-incense/assets/fonts/LICENSE.html @@ -0,0 +1,169 @@ +네이버 나눔글꼴 라이선스안내 : 고객센터
          빈줄

              + + + +
              +
              +
              +
              +
              +

              네이버 나눔글꼴의 지적 재산권은 네이버와 네이버 문화재단에 있습니다.

              +

              ​

              +

              네이버 나눔글꼴은 개인 및 기업 사용자를 포함한 모든 사용자에게 무료로 제공되며 글꼴 자체를 유료로 판매하는 것을 제외한 상업적인 사용이 가능합니다.

              +

              ​

              +

              네이버 나눔글꼴은 본 저작권 안내와 라이선스 전문을 포함해서 다른 소프트웨어와 번들하거나 재배포 또는 판매가 가능하고 자유롭게 수정, 재배포하실 수 있습니다.

              +

              ​

              +

              네이버 나눔글꼴 라이선스 전문을 포함하기 어려울 경우, 나눔글꼴의 출처 표기를 권장합니다.

              +

              예) 이 페이지에는 네이버에서 제공한 나눔글꼴이 적용되어 있습니다.

              +

              ​

              +

              네이버 나눔글꼴을 사용한 인쇄물, 광고물(온라인 포함)의 이미지는 나눔글꼴 프로모션을 위해 활용될 수 있습니다.

              +

              ​

              +

              이를 원치 않는 사용자는 언제든지 당사에 요청하실 수 있습니다.

              +

              ​

              +

              정확한 사용 조건은 아래 네이버 나눔글꼴 라이선스 전문을 참고하시기 바랍니다.

              +

              ​

              +

              네이버 마루 부리 글꼴도 나눔 글꼴과 같은 오픈라이센스 폰트로 동일한 저작권 규정을 적용받습니다.

              +

              ​

              +

              ※ 참고해 주세요!

              +

              - 나눔글꼴 라이선스 전문의 한글은 이용자의 이해를 돕기 위해 영문 원본을 번역해 서비스하고 있으며, 법적 효력은 영문에 한합니다.

              +

              ​

              +

              1. 라이선스

              +

              Copyright (c) 2010, NAVER Corporation (https://www.navercorp.com/) with Reserved Font Name Nanum, Naver Nanum, NanumGothic, Naver NanumGothic, NanumMyeongjo, Naver NanumMyeongjo, NanumBrush, Naver NanumBrush, NanumPen, Naver NanumPen, Naver NanumGothicEco, NanumGothicEco, Naver NanumMyeongjoEco, NanumMyeongjoEco, Naver NanumGothicLight, NanumGothicLight, NanumBarunGothic, Naver NanumBarunGothic, NanumSquareRound, NanumBarunPen, MaruBuri, NanumSquareNeo

              +

              ​

              +

              This Font Software is licensed under the SIL Open Font License, Version 1.1.

              +

              ​

              +

              This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL

              +

              ​

              +

              SIL OPEN FONT LICENSE

              +

              Version 1.1 - 26 February 2007

              +

              ​

              +

              ‘나눔, 네이버 나눔, 나눔고딕, 네이버 나눔고딕, 나눔명조, 네이버 나눔명조, 나눔손글씨, 네이버 나눔손글씨, 나눔펜, 네이버 나눔펜, 네이버 나눔고딕에코, 나눔고딕에코, 네이버 나눔명조에코, 나눔명조에코, 네이버 나눔고딕라이트, 나눔고딕라이트, 나눔바른고딕, 네이버나눔바른고딕, 나눔스퀘어라운드, 나눔바른펜, 마루 부리, 나눔스퀘어네오’ 폰트명에 대해 NAVER(https://www.navercorp.com/)가 저작권을 소유하고 있습니다.

              +

              ​

              +

              본 폰트 소프트웨어는 SIL 오픈 폰트 라이선스 버전 1.1에 따라 라이선스 취득을 하였습니다.

              +

              ​

              +

              본 라이선스는 하단에 복사되었고 http://scripts.sil.org/OFL의 FAQ 란에서도 열람 가능합니다.

              +

              ​

              +

              SIL 오픈 폰트 라이선스

              +

              버전 1.1 (2007년 2월 26일)

              +

              ​

              +

              [DEFINITIONS (정의)]

              +

              ""Font Software"" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.

              +

              ​

              +

              ""Reserved Font Name"" refers to any names specified as such after the copyright statement(s).

              +

              ​

              +

              ""Original Version"" refers to the collection of Font Software components as distributed by the Copyright Holder(s).

              +

              ​

              +

              ""Modified Version"" refers to any derivative made by adding to, deleting, or substituting in part or in whole any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.‘

              +

              ​

              +

              ""Author"" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.

              +

              ​

              +

              ‘폰트 소프트웨어’는 본 라이선스에 입거해 저작권자가 배포하고 명확하게 같은 표시가 된 파일들의 집합을 뜻하며, 여기에는 소스 파일, 빌드 스크립트와 문서가 이에 포함됩니다.

              +

              ​

              +

              ‘저작권이 있는 폰트명’은 저작권 정책에 따라서 지정된 이름을 말합니다.

              +

              ​

              +

              ‘원본’은 저작권자가 배포한 폰트 소프트웨어 구성요소를 의미합니다.

              +

              ​

              +

              ‘수정본’은 포맷의 변경이나 폰트 소프트웨어를 새로운 환경에 포팅 시켜, 원본의 일부 혹은 전체에 추가, 삭제 대체해 만든 파생 저작물을 의미합니다.

              +

              ​

              +

              ‘저자’는 폰트 소프트웨어에 기여한 디자이너, 엔지니어, 프로그래머, 기술 전문가 등을 의미합니다.

              +

              ​

              +

              2. PREAMBLE (전문)

              +

              The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.

              +

              ​

              +

              The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works.

              +

              ​

              +

              The fonts and derivatives, however, cannot be released under any other type of license.

              +

              ​

              +

              The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives.

              +

              ​

              +

              본 폰트 라이선스를 오픈하는 것은(이하 OFL)는 전 세계 폰트 개발 프로젝트를 지원하고 학계와 언어 관련 학계의 폰트 개발을 위한 연구를 지지하기 위해서인 동시에, 폰트 제휴를 통해 폰트가 공유되고 개선될 수 있는 자유롭게 개방된 환경을 만들기 위해서입니다.

              +

              ​

              +

              OFL은 라이선스를 취득한 폰트가 그 자체로 판매되지 않는 한 자유롭게 사용, 연구, 수정, 재배포 하는 것을 허가합니다.

              +

              ​

              +

              수정된 폰트를 포함한 폰트는 저작권 명이 사용되지 않는 한 기타 소프트웨어와 함께 묶이거나 삽입, 재배포 할 수 있습니다.

              +

              ​

              +

              단 폰트와 수정된 폰트는 기타 다른 라이선스에 포함되어 배포될 수는 없습니다.

              +

              ​

              +

              이 라이선스 하에 있기 위한 폰트에 대한 요구사항은 본 폰트나 수정본을 사용하여 제작된 어떠한 문서에도 적용되지 않습니다.

              +

              ​

              +

              3. PERMISSION & CONDITIONS (허가 및 조건)

              +

              Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:

              +

              ​

              +

              본 폰트 소프트웨어를 사용하도록 허가받은 개인/기업/단체 누구라도 다음 명시된 조건에 따라 폰트 소프트웨어의 수정 혹은 수정되지 않은 복사본을 무료로 사용, 연구, 복사, 통합, 삽입, 수정, 재배포할 수 있도록 허가합니다.

              +

              ​

              +

              1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.

              +

              ​

              +

              원본이나 수정본의 폰트 소프트웨어 혹은 개별 구성요소인 폰트 자체가 판매되어서는 안됩니다.

              +

              ​

              +

              2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license.

              +

              ​

              +

              These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.

              +

              ​

              +

              본 폰트 소프트웨어의 원본 혹은 수정본은 상기 저작권 안내와 본 라이선스에 대한 내용을 포함하는 경우에는 다른 소프트웨어와 함께 묶이거나 재배포 혹은 판매가 가능합니다.

              +

              ​

              +

              이는 독립 텍스트 파일과 가독성이 있는 헤더 혹은 유저가 용이하게 열람 가능한 이상 텍스트 파일 혹은 이진 파일 내 기계가 읽을 수 있는 메타데이터 형태를 모두 의미합니다.

              +

              ​

              +

              3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder.

              +

              ​

              +

              This restriction only applies to the primary font name as presented to the users.

              +

              ​

              +

              본 폰트 소프트웨어의 어떠한 수정본도 동일한 저작권자가 명시적 허가서를 부여하지 않는 한 저작권이 있는 폰트명을 사용해서는 안 됩니다.

              +

              ​

              +

              본 제한 사항은 유저들에게 제공된 기존 폰트명을 뜻합니다.

              +

              ​

              +

              4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.

              +

              ​

              +

              본 폰트 소프트웨어의 저작권자 혹은 저자의 이름은 그들의 명시적 서면 허가가 있거나 또는 그들의 공헌을 인정하기 위한 경우를 제외하고는 수정본에 대한 사용을 유도, 추천 혹은 광고하기 위한 목적으로 사용할 수 없습니다.

              +

              ​

              +

              5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed any other license.

              +

              ​

              +

              The requirement for fonts to remain under this license does not apply to any document created using the Font Software.

              +

              ​

              +

              본 폰트 소프트웨어는 전체나 부분, 혹은 수정 여부에 상관없이 본 라이선스 하에 배포가 되어야 하며 기타 다른 라이선스 하에서는 배포를 할 수 없습니다.

              +

              ​

              +

              폰트에 대한 요구 조건은 이 라이선스 하에서만 유효하며 이 라이선스 하에 있기 위한 폰트에 대한 요구사항은 본 폰트 소프트웨어를 사용해 제작한 어떠한 문서에도 적용되지 않습니다.

              +

              ​

              +

              4. TERMINATION (계약의 종료)

              +

              This license becomes null and void if any of the above conditions are not met.

              +

              ​

              +

              본 라이선스는 상기 조건 중 일부라도 부합되지 않으면 무효가 될 수 있습니다.

              +

              ​

              +

              5. DISCLAIMER (면책조항)

              +

              THE FONT SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT.

              +

              ​

              +

              IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.

              +

              ​

              +

              본 폰트 소프트웨어는 저작권, 특허권, 상표권 및 기타 권리의 비침해성과 특정 목적에의 적합성 포함한 명시적, 묵시적인 어떠한 종류의 보증 없이 “있는 그대로” 제공됩니다.

              +

              ​

              +

              어떠한 경우에도 저작권자는 본 폰트 소프트웨어의 사용 또는 이의 사용 불가, 그밖에 폰트 소프트웨어의 취급과 관련하여 발생하는 모든 계약, 불법행위 혹은 다른 일로 하여금 발생하는 일반적, 특수적, 간접적, 부차적 혹은 필연적 손해를 포함하는 소송, 손해, 혹은 기타 책임에 대한 의무를 가지지 않습니다.

              + +
              +
              +
              + +
              +
              만족도 평가
            \ No newline at end of file diff --git a/apps/site/public/work/hyang-incense/assets/fonts/MaruBuri-Regular.woff2 b/apps/site/public/work/hyang-incense/assets/fonts/MaruBuri-Regular.woff2 new file mode 100644 index 0000000..3bc205f Binary files /dev/null and b/apps/site/public/work/hyang-incense/assets/fonts/MaruBuri-Regular.woff2 differ diff --git a/apps/site/public/work/hyang-incense/assets/fonts/MaruBuri-SemiBold.woff2 b/apps/site/public/work/hyang-incense/assets/fonts/MaruBuri-SemiBold.woff2 new file mode 100644 index 0000000..be593a5 Binary files /dev/null and b/apps/site/public/work/hyang-incense/assets/fonts/MaruBuri-SemiBold.woff2 differ diff --git a/apps/site/public/work/hyang-incense/assets/fonts/SOURCES.md b/apps/site/public/work/hyang-incense/assets/fonts/SOURCES.md new file mode 100644 index 0000000..66d2c89 --- /dev/null +++ b/apps/site/public/work/hyang-incense/assets/fonts/SOURCES.md @@ -0,0 +1,13 @@ +# MaruBuri source record + +Downloaded 2026-09-12 from the official NAVER Hangeul static host. The files are retained unchanged: no conversion or subsetting was performed. + +| File | Official URL | HTTP content type | Size | SHA-256 | +| --- | --- | --- | --- | --- | +| `MaruBuri-Regular.woff2` | https://hangeul.pstatic.net/hangeul_static/webfont/MaruBuri/MaruBuri-Regular.woff2 | `font/woff2` | 433776 bytes | `4CF1341CF2F23FB3E263712DFDE1D8F25EEDCC328B696A2E5A2C8ADD55E5C17B` | +| `MaruBuri-SemiBold.woff2` | https://hangeul.pstatic.net/hangeul_static/webfont/MaruBuri/MaruBuri-SemiBold.woff2 | `font/woff2` | 466108 bytes | `7AEF4862FA3219B0A7DEB6746E27116A38C4069F4424EB51EDF103B29795F5C2` | + +- Official stylesheet checked: https://hangeul.pstatic.net/hangeul_static/css/maru-buri.css +- Official NAVER license page saved verbatim as `LICENSE.html`: https://help.naver.com/service/11029/contents/18088?lang=ko&osType=PC +- `LICENSE.html` SHA-256: `8538F7921744D5E040F603BC301465EFBD038F1054D0754B7508DE3286452EC3` +- The saved official page includes the NAVER copyright notice and the SIL Open Font License 1.1 text for MaruBuri. diff --git a/apps/site/public/work/hyang-incense/design.md b/apps/site/public/work/hyang-incense/design.md new file mode 100644 index 0000000..b4f7475 --- /dev/null +++ b/apps/site/public/work/hyang-incense/design.md @@ -0,0 +1,17 @@ +# 향연 + +연기 세로 사진과 주변 여백을 유지한다. 히어로 사진의 이중 액자를 제거해 사진면과 기록면을 직접 맞대고, 숙성 장부와 아카이브 목록은 라벨·값이 같은 기준선에서 읽히게 조정한다. 본문은 17px 이상과 42rem 이하의 폭을 쓴다. + +| 판단 축 | 적용 | 한계 | +| --- | --- | --- | +| 구도 | Hofmann의 면과 여백 관계를 참고해 사진 주위의 불필요한 액자 여백을 줄였다. | 이 참고가 모든 전시형 페이지의 최적 해법은 아니다. | +| 타입 | Ruder를 참고해 장부의 라벨·값과 본문의 역할을 분리했다. | 읽기 속도나 이해도 향상을 주장하지 않는다. | +| 색 | Albers를 참고해 따뜻한 바탕과 적갈색 동작색의 역할 경계를 유지했다. | 대비 수치는 브라우저 검증으로 재확인한다. | + +토큰은 `--surface`, `--ink`, `--accent`, `--step-0`, `--space-*`를 사용한다. 로컬 MaruBuri 400/600은 `styles/fonts.css`, Pretendard는 기존 CDN을 유지한다. 가상 기록·예시 가격·기존 앵커는 바꾸지 않았다. + +## 2026-09-12 현재 검증 기록 + +- `verify-final` 18개 묶음은 16개가 즉시 통과했다. 전체 묶음의 invariant·visual 검사는 Gaon·Dure를 대상으로 하며, 나머지 2개는 수정 뒤 release 독립 재실행에서 ALL PASS·ALL MATCH였다. +- root는 28개 모바일, 21개 데스크톱, 7개 하위 경로와 30개 앱 상태를 직접 검토해 수용했다. stress 112건은 hard failure 0이며, 가로 넘침 4건은 targeted fix 뒤 390px 재측정에서 0이다. +- 이 기록은 렌더·계약 범위의 현재 결과다. 모든 폭·키보드 경로·인쇄 등 개별 기능을 완전 재실행했다는 뜻이 아니며, 참여자 과업 효과도 미측정이다. diff --git a/apps/site/public/work/hyang-incense/index.html b/apps/site/public/work/hyang-incense/index.html index 2efa651..f2e7258 100644 --- a/apps/site/public/work/hyang-incense/index.html +++ b/apps/site/public/work/hyang-incense/index.html @@ -16,13 +16,13 @@ - +
            -
            -

            자연 침향 · 백단 · 서울 삼청동

            +

            가상 향 아카이브 · 기록 형식 예시

            연기는 흩어지고
            향기만 머뭅니다

            - 향연은 향을 판매하기 전에 기록부터 남깁니다. 어느 해에 들인 나무인지, - 수지가 몇이었는지, 연소에 몇 분이 걸렸는지. 향은 사라지는 것이니 - 남는 것은 문서뿐입니다. + 향연은 향의 산지·숙성·연소 정보를 어떻게 기록할 수 있는지 보여 주는 + 가상 아카이브입니다. 아래 상품·가격·방문 정보는 판매나 예약을 위한 + 정보가 아니라 기록 형식의 예시입니다.

            @@ -74,15 +70,11 @@ loading="eager" fetchpriority="high" /> -
            침향 한 줄기 · 삼청동 아카이브룸
            +
            침향 연출 이미지 · 가상 아카이브
            -
            @@ -103,31 +95,26 @@ 얻을 수 없고, 자연에서 쓰러진 나무에서만 길어 올립니다.

            - 향연은 인공접종 목재를 다루지 않습니다. 매입 단계에서 수지 함량을 - 측정해 기록하고, 그 기록이 통과하지 못한 나무는 아카이브에 들어오지 - 않습니다. + 이 섹션은 산지·수지 함량·숙성 상태를 함께 기록하는 방식을 설명합니다. + 특정 목재의 매입 기준이나 실제 아카이브 운영 정책을 뜻하지 않습니다.

            -
            -

            숙성 장부

            +

            숙성 기록 예시

            - 들여온 해와 수지 함량, 지금 상태입니다. 향은 재고가 아니라 연도입니다 — - 같은 나무가 다시 들어오지 않습니다. + 들여온 해와 수지 함량, 상태를 한 줄에서 읽는 기록 형식입니다. 아래 + 연도·산지·수지 함량은 실제 측정이나 재고를 뜻하지 않습니다.

            @@ -142,85 +129,80 @@ - + - + - +
            - 숙성 장부 — 입목 연도, 산지, 수지 함량, 현재 상태 + 숙성 기록 예시 — 입목 연도, 산지, 수지 함량, 상태
            2001년 베트남 카호아 64.2%열매 · 매진 임박열매 · 상태 예시
            2012년 인도네시아 리아우 51.8%침향 절편 · 소량침향 절편 · 상태 예시
            2024년 캄보디아 프놈펜 인근 47.3%숙성 중 · 비매품숙성 중 · 상태 예시

            - 수지 함량: 에탄올 용출법 실측. 열매(초험)는 기증용으로만 남겨둡니다. + 수지 함량과 상태 표기는 기록 형식을 설명하기 위한 예시 값입니다.

            -
            -

            지금 만질 수 있는 것

            +

            기록으로 살펴보는 구성

            1. 자연 침향 절편

              2001년 입목 · 수지 64.2% · 10g

              -

              180,000원

              +

              예시 180,000원

            2. 백단 침 향

              인도 마이소르 노목 · 20g · 연소 45분

              -

              42,000원

              +

              예시 42,000원

            3. 침향 인엽

              리아우산 · 2012년 입목 · 3g

              -

              96,000원

              +

              예시 96,000원

            - 모든 물건은 삼청동 아카이브룸에서 직접 내어드립니다. 향을 맡아 보고 - 정하시면 됩니다 — 예약제이며 회당 한 분만 들어갑니다. + 이 목록은 상품명·단위·가격을 기록하는 방식을 보여 줍니다. 실제 상품 판매, + 향 시향, 예약 또는 방문을 제공하지 않습니다.

            -
            -

            삼청동, 예약제

            +

            방문 정보 예시

            - 서울 종로구 삼청로 00길 00
            - 경복궁역 5번 출구에서 도보 6분 + 가상 아카이브 안내
            + 실제 장소와 방문 경로를 제공하지 않습니다.
            -
            예약
            +
            방문 시간 예시
            화–토 · 11:00, 14:00, 16:00 회당 50분
            -
            문의
            -
            archive@hyang.kr
            +
            예약
            +
            실제 예약 및 문의를 받지 않습니다.
            @@ -229,18 +211,5 @@
            - diff --git a/apps/site/public/work/hyang-incense/styles/fonts.css b/apps/site/public/work/hyang-incense/styles/fonts.css new file mode 100644 index 0000000..f5234d6 --- /dev/null +++ b/apps/site/public/work/hyang-incense/styles/fonts.css @@ -0,0 +1,15 @@ +@font-face { + font-family: "MaruBuri"; + src: url("../assets/fonts/MaruBuri-Regular.woff2") format("woff2"); + font-style: normal; + font-weight: 400; + font-display: swap; +} + +@font-face { + font-family: "MaruBuri"; + src: url("../assets/fonts/MaruBuri-SemiBold.woff2") format("woff2"); + font-style: normal; + font-weight: 600; + font-display: swap; +} diff --git a/apps/site/public/work/hyang-incense/styles/main.css b/apps/site/public/work/hyang-incense/styles/main.css index bc5bc41..89c11c0 100644 --- a/apps/site/public/work/hyang-incense/styles/main.css +++ b/apps/site/public/work/hyang-incense/styles/main.css @@ -1,4 +1,4 @@ -@import url("./tokens.css"); +@import url("./tokens.css?v=20260912all"); /* ========================================================================== 향연 — quiet-luxury. 밝은 편집면 위의 기록. @@ -138,6 +138,7 @@ a { } .nav { display: flex; + flex-wrap: wrap; gap: clamp(var(--space-3), 2vw, var(--space-5)); font-size: var(--step--1); } @@ -157,13 +158,26 @@ a { /* ── 히어로 ───────────────────────────────────────────────────────────── */ .hero { - padding-block: var(--space-8) var(--space-7); + display: grid; + align-items: center; + min-block-size: min(46rem, calc(100svh - 4rem)); + padding-block: var(--space-6); + border-bottom: 1px solid var(--line); } .hero-grid { display: grid; - grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); - gap: var(--space-7) var(--space-6); - align-items: start; + grid-template-columns: minmax(0, 1fr) minmax(16rem, 28rem); + gap: clamp(var(--space-5), 6vw, var(--space-8)); + align-items: center; +} +.hero-grid > *, +.two > *, +.visit-grid > * { + min-width: 0; +} +.hero-text { + max-width: 38rem; + padding-block: var(--space-4); } .hero-kicker { font-size: var(--step--1); @@ -172,7 +186,7 @@ a { margin-bottom: var(--space-5); } .lead { - max-width: 30em; + max-width: 42rem; } .hero-text .lead { margin-top: var(--space-5); @@ -181,7 +195,9 @@ a { margin-top: var(--space-6); } .btn { - display: inline-block; + display: inline-flex; + align-items: center; + min-height: 44px; border: 1px solid var(--ink); color: var(--ink); text-decoration: none; @@ -196,22 +212,24 @@ a { } .hero-photo { - position: relative; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-2); - justify-content: end; + width: min(100%, 28rem); + justify-self: end; align-items: start; } .hero-photo img { display: block; width: 100%; + aspect-ratio: 3 / 4; height: auto; + object-fit: cover; border-radius: var(--radius); } .hero-photo figcaption { font-size: var(--step--1); - color: var(--ink-faint); + color: var(--ink-muted); letter-spacing: 0.06em; } @@ -220,6 +238,12 @@ a { .section { padding-block: var(--space-8); } +.section[id] { + scroll-margin-top: 6rem; +} +#aging .wrap { + width: min(100% - 2 * var(--pad-inline), var(--container-wide)); +} .band { background: var(--surface-raised); border-block: 1px solid var(--line); @@ -247,6 +271,9 @@ a { .two-text p + p { margin-top: var(--space-4); } +.two-text p { + max-width: 42rem; +} .two-text .muted { margin-top: var(--space-4); } @@ -254,7 +281,7 @@ a { /* ── 숙성 장부 ────────────────────────────────────────────────────────── */ .aging-head { - max-width: 36em; + max-width: 42rem; margin-bottom: var(--space-5); } .aging-head p { @@ -305,8 +332,8 @@ tbody th { border-top: 1px solid var(--line); } .item { - display: flex; - justify-content: space-between; + display: grid; + grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: var(--space-4); padding-block: var(--space-4); @@ -323,11 +350,12 @@ tbody th { .item-price { font-family: var(--font-display); font-size: var(--step-1); + font-variant-numeric: tabular-nums; white-space: nowrap; } .collection-note { margin-top: var(--space-4); - max-width: 34em; + max-width: 42rem; } /* ── 방문 ─────────────────────────────────────────────────────────────── */ @@ -368,23 +396,9 @@ tbody th { /* ── 등장 모션 — 다른 페이지보다 느리다 ──────────────────────────────── */ .reveal { - opacity: 0; - translate: 0 16px; - transition: opacity var(--dur-normal) var(--ease-soft), - translate var(--dur-normal) var(--ease-soft); - transition-delay: var(--delay, 0ms); -} -.reveal.is-in { opacity: 1; translate: 0 0; } -@media (prefers-reduced-motion: reduce) { - .reveal { - opacity: 1; - translate: 0 0; - transition: none; - } -} /* ── 반응형 ───────────────────────────────────────────────────────────── */ @@ -397,6 +411,7 @@ tbody th { .hero-photo { max-width: 24rem; justify-content: start; + justify-self: start; } .visit-grid { grid-template-columns: 1fr; @@ -405,6 +420,7 @@ tbody th { display: none; } .hero { + min-block-size: auto; padding-block: var(--space-6); } } @@ -416,11 +432,13 @@ tbody th { } .nav { width: 100%; - justify-content: space-between; + justify-content: flex-start; } .item { - flex-direction: column; - align-items: flex-start; + grid-template-columns: 1fr; gap: var(--space-1); } + .item-price { + white-space: normal; + } } diff --git a/apps/site/public/work/hyang-incense/styles/tokens.css b/apps/site/public/work/hyang-incense/styles/tokens.css index 46e0be8..68b185d 100644 --- a/apps/site/public/work/hyang-incense/styles/tokens.css +++ b/apps/site/public/work/hyang-incense/styles/tokens.css @@ -28,7 +28,7 @@ --surface-raised: #efe9dc; --ink: #2b2724; --ink-muted: #6d655c; - --ink-faint: #9a9083; + --ink-faint: #746c60; --line: #ddd4c3; --accent: #7c3b24; /* 적갈 — 링크와 핵심 동작만 */ --accent-hover: #5f2c1a; @@ -44,8 +44,10 @@ --radius: 2px; - --container: 1040px; - --pad-inline: clamp(1.25rem, 1rem + 2.5vw, 4rem); + /* 향의 문장은 좁게, 장부와 실물 기록은 넓게 둔다. */ + --container: 1160px; + --container-wide: 1440px; + --pad-inline: clamp(1.25rem, 1rem + 2.5vw, 4.5rem); --dur-quick: 160ms; --dur-normal: 560ms; /* 느린 페이지 — 등장도 느리게 */ diff --git a/apps/site/public/work/lumina-optics/design.md b/apps/site/public/work/lumina-optics/design.md new file mode 100644 index 0000000..784afcd --- /dev/null +++ b/apps/site/public/work/lumina-optics/design.md @@ -0,0 +1,27 @@ +# Lumina Optics design.md + +## 브리프 + +- 무엇을: IOR와 분산을 조작하는 가상 광학 시험대. +- 누구에게: 광선 모델의 조건과 결과물을 함께 읽으려는 방문자. +- 제약: WebGL/정적 폴백, 기존 슬라이더와 가상·측정 아님 표기를 유지한다. + +## 결정표 + +| 축 | 관찰과 적용 범위 | 결정·역할 토큰 | 기각 조건 | +|---|---|---|---| +| 구도 | 기준 1440 화면에서 큰 프리즘이 제목과 조작을 폴드 아래로 밀었다. | 제목·한계 설명을 상단에 두고 `9:4` 캔버스/제어 프레임을 배치한다. `--container`, `--space-4`, `--space-6`. | 캔버스가 제어보다 큰 면적을 차지해 둘 중 하나가 첫 화면에서 사라지면 재조정한다. | +| 타입 | 제목은 모델의 의미, 모노는 조건과 조작값을 읽게 해야 한다. | `--step-3` 제목, `--step--1` 시험대 원장과 제어 보조문을 유지한다. | 실제 긴 라벨이 320px 또는 200% 확대에서 제어를 밀면 폭·간격을 수정한다. | +| 색 | 스펙트럼만 광학 결과를 나타내며 UI 색은 보조여야 한다. | `--surface`, `--surface-raised`, `--accent-stroke`을 프레임·포커스·입력에만 쓴다. | UI 색이 캔버스의 분산 광선보다 먼저 읽히면 채도를 줄인다. | + +## 근거와 경계 + +[art-direction.md](../../../../../packages/skill/references/art-direction.md)의 Hofmann 관련 구도·군집 관찰을 제목/작업면 분리에만 적용했다. [typography.md](../../../../../packages/skill/references/typography.md)의 Ruder 관련 실제 카피·수치 proof 범위를 타입 계층에만 적용했다. [visual-design-lineage.md](../../../../../packages/skill/references/visual-design-lineage.md)의 Albers 관련 색 맥락은 캔버스와 UI 표면의 대비 확인에만 적용했다. 이 세 자료는 성능·이해도 법칙으로 사용하지 않는다. + +[trustworthy-showcases.md](../../../../../packages/skill/references/trustworthy-showcases.md)의 진실 범위에 따라 모델·사양·곡선의 illustrative 표기를 가까운 공통 표면에 유지한다. 캔버스 안에는 텍스트를 굽지 않는다. + +## 2026-09-12 현재 검증 기록 + +- `verify-final` 18개 묶음은 16개가 즉시 통과했다. 전체 묶음의 invariant·visual 검사는 Gaon·Dure를 대상으로 하며, 나머지 2개는 수정 뒤 release 독립 재실행에서 ALL PASS·ALL MATCH였다. +- root는 28개 모바일, 21개 데스크톱, 7개 하위 경로와 30개 앱 상태를 직접 검토해 수용했다. stress 112건은 hard failure 0이며, 가로 넘침 4건은 targeted fix 뒤 390px 재측정에서 0이다. +- 이 기록은 렌더·계약 범위의 현재 결과다. 모든 폭·키보드 경로·인쇄 등 개별 기능을 완전 재실행했다는 뜻이 아니며, 참여자 과업 효과도 미측정이다. diff --git a/apps/site/public/work/lumina-optics/index.html b/apps/site/public/work/lumina-optics/index.html index 99356f0..9d9f910 100644 --- a/apps/site/public/work/lumina-optics/index.html +++ b/apps/site/public/work/lumina-optics/index.html @@ -3,15 +3,15 @@ - Lumina Optics · Refraction Bench + Lumina Optics · Interactive Optical Study - + @@ -22,7 +22,7 @@ rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Sans+KR:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" /> - +
            -
            -
            - - A glass prism on a dark optical breadboard splitting one collimated beam into a spectrum -
            -
            +
            -

            Refraction bench · WebGL

            +

            Interactive optical study

            One beam,
            bent honestly

            - No photograph on this screen is doing the work — the prism is - being refracted right now, per frame, on your GPU. Drag it. Change - the index. The spectrum you see is the same arithmetic lens - designers use, minus the glasses. + Move the prism to compare how refractive index and dispersion + redirect one beam. This view illustrates an optical model; it is + not a measured photograph, a product specification, or a lab result.

            -
            +
            +
            +
            +
            + + Illustrative glass prism on a dark optical surface splitting one collimated beam into a spectrum +
            +
            +
            +
            -
            Cutaway of a precision lens: a stack of glass elements in a metal barrel, edge-lit so each surface shows a refraction line -
            L-85 cutaway · 7 elements in 6 groups
            +
            L-85 concept cutaway · illustrative element layout
            -

            Glass decides
            before software does

            +

            Glass sets
            the light path

            - A lens is a chain of refractions, and every surface answers before - any firmware runs. Our L-85 uses two low-dispersion elements to - keep the spectrum you just dragged from fanning out across the - frame — dispersion corrected in glass, not in a profile. + A lens is a chain of refractions: every surface bends the path + before an image is made. The L-85 concept uses low-dispersion + elements to explain why a design can keep colours from spreading + across the frame.

            - The cutaway above is a physical section, milled for measurement. - Element count and spacing are measured from it, not from the - drawing. + The cutaway is a constructed reference image. Its element count + and spacing are illustrative, not a measurement of a commercial lens.

            -
            -

            MTF, not adjectives

            +

            MTF, read with conditions

            - “Tack sharp” is not a specification. Contrast transfer at given - line pairs per millimetre is. These curves are measured on an - optical bench at full aperture — sagittal and meridional, out to - the corner. + Contrast transfer at stated line pairs per millimetre gives a + clearer comparison than a slogan. These curves illustrate the + labels a measured chart needs; they are not optical-bench results.

            • 10 lp/mm · sagittal
            • @@ -146,7 +152,7 @@
            - + @@ -166,76 +172,62 @@ image field (mm) corner 21.6 - - - - -
            L-85 · f/1.8 · infinity focus · bench-measured 2026-07
            +
            L-85 concept · f/1.8 · infinity focus · illustrative curve
            -
            -

            Specification

            +

            Reference specification

            - + - + - - - - - - + + + + + +
            L-85 specification — item, value, conditionL-85 concept specification — illustrative item, value, and condition
            ItemValueIllustrative value Condition
            Focal length85 mmnominal · ±1.5% at infinity
            Aperturef/1.8 – f/169-blade · near-circular
            Elements7 in 62 LD · measured from cutaway
            Close focus0.62 m1:7.2 magnification
            FilterØ 62 mmbrass, front-threaded
            Weight438 gwithout caps, with hood
            Focal length85 mmconcept reference
            Aperturef/1.8 – f/16concept reference
            Elements7 in 6illustrative layout
            Close focus0.62 millustrative configuration
            FilterØ 62 mmillustrative configuration
            Weight438 gillustrative configuration
            -
            -

            Bench visits

            +

            About this study

            - We measure loaner samples for free and publish the curves — - manufacturers welcome or not. Bench time and MTF requests: + This is a concept page for reading an optical model. It does not + schedule sample loans, measurements, or MTF requests.

            - bench@lumina.optics + Return to the light study
            -

            lumina optics

            -

            measurements reproducible on request · bench cal. 2026-06

            +

            lumina optics · optical study

            +

            illustrative model · no commercial measurement service

            빈줄

                + + + +
                +
                +
                +
                +
                +

                네이버 나눔글꼴의 지적 재산권은 네이버와 네이버 문화재단에 있습니다.

                +

                ​

                +

                네이버 나눔글꼴은 개인 및 기업 사용자를 포함한 모든 사용자에게 무료로 제공되며 글꼴 자체를 유료로 판매하는 것을 제외한 상업적인 사용이 가능합니다.

                +

                ​

                +

                네이버 나눔글꼴은 본 저작권 안내와 라이선스 전문을 포함해서 다른 소프트웨어와 번들하거나 재배포 또는 판매가 가능하고 자유롭게 수정, 재배포하실 수 있습니다.

                +

                ​

                +

                네이버 나눔글꼴 라이선스 전문을 포함하기 어려울 경우, 나눔글꼴의 출처 표기를 권장합니다.

                +

                예) 이 페이지에는 네이버에서 제공한 나눔글꼴이 적용되어 있습니다.

                +

                ​

                +

                네이버 나눔글꼴을 사용한 인쇄물, 광고물(온라인 포함)의 이미지는 나눔글꼴 프로모션을 위해 활용될 수 있습니다.

                +

                ​

                +

                이를 원치 않는 사용자는 언제든지 당사에 요청하실 수 있습니다.

                +

                ​

                +

                정확한 사용 조건은 아래 네이버 나눔글꼴 라이선스 전문을 참고하시기 바랍니다.

                +

                ​

                +

                네이버 마루 부리 글꼴도 나눔 글꼴과 같은 오픈라이센스 폰트로 동일한 저작권 규정을 적용받습니다.

                +

                ​

                +

                ※ 참고해 주세요!

                +

                - 나눔글꼴 라이선스 전문의 한글은 이용자의 이해를 돕기 위해 영문 원본을 번역해 서비스하고 있으며, 법적 효력은 영문에 한합니다.

                +

                ​

                +

                1. 라이선스

                +

                Copyright (c) 2010, NAVER Corporation (https://www.navercorp.com/) with Reserved Font Name Nanum, Naver Nanum, NanumGothic, Naver NanumGothic, NanumMyeongjo, Naver NanumMyeongjo, NanumBrush, Naver NanumBrush, NanumPen, Naver NanumPen, Naver NanumGothicEco, NanumGothicEco, Naver NanumMyeongjoEco, NanumMyeongjoEco, Naver NanumGothicLight, NanumGothicLight, NanumBarunGothic, Naver NanumBarunGothic, NanumSquareRound, NanumBarunPen, MaruBuri, NanumSquareNeo

                +

                ​

                +

                This Font Software is licensed under the SIL Open Font License, Version 1.1.

                +

                ​

                +

                This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL

                +

                ​

                +

                SIL OPEN FONT LICENSE

                +

                Version 1.1 - 26 February 2007

                +

                ​

                +

                ‘나눔, 네이버 나눔, 나눔고딕, 네이버 나눔고딕, 나눔명조, 네이버 나눔명조, 나눔손글씨, 네이버 나눔손글씨, 나눔펜, 네이버 나눔펜, 네이버 나눔고딕에코, 나눔고딕에코, 네이버 나눔명조에코, 나눔명조에코, 네이버 나눔고딕라이트, 나눔고딕라이트, 나눔바른고딕, 네이버나눔바른고딕, 나눔스퀘어라운드, 나눔바른펜, 마루 부리, 나눔스퀘어네오’ 폰트명에 대해 NAVER(https://www.navercorp.com/)가 저작권을 소유하고 있습니다.

                +

                ​

                +

                본 폰트 소프트웨어는 SIL 오픈 폰트 라이선스 버전 1.1에 따라 라이선스 취득을 하였습니다.

                +

                ​

                +

                본 라이선스는 하단에 복사되었고 http://scripts.sil.org/OFL의 FAQ 란에서도 열람 가능합니다.

                +

                ​

                +

                SIL 오픈 폰트 라이선스

                +

                버전 1.1 (2007년 2월 26일)

                +

                ​

                +

                [DEFINITIONS (정의)]

                +

                ""Font Software"" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.

                +

                ​

                +

                ""Reserved Font Name"" refers to any names specified as such after the copyright statement(s).

                +

                ​

                +

                ""Original Version"" refers to the collection of Font Software components as distributed by the Copyright Holder(s).

                +

                ​

                +

                ""Modified Version"" refers to any derivative made by adding to, deleting, or substituting in part or in whole any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.‘

                +

                ​

                +

                ""Author"" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.

                +

                ​

                +

                ‘폰트 소프트웨어’는 본 라이선스에 입거해 저작권자가 배포하고 명확하게 같은 표시가 된 파일들의 집합을 뜻하며, 여기에는 소스 파일, 빌드 스크립트와 문서가 이에 포함됩니다.

                +

                ​

                +

                ‘저작권이 있는 폰트명’은 저작권 정책에 따라서 지정된 이름을 말합니다.

                +

                ​

                +

                ‘원본’은 저작권자가 배포한 폰트 소프트웨어 구성요소를 의미합니다.

                +

                ​

                +

                ‘수정본’은 포맷의 변경이나 폰트 소프트웨어를 새로운 환경에 포팅 시켜, 원본의 일부 혹은 전체에 추가, 삭제 대체해 만든 파생 저작물을 의미합니다.

                +

                ​

                +

                ‘저자’는 폰트 소프트웨어에 기여한 디자이너, 엔지니어, 프로그래머, 기술 전문가 등을 의미합니다.

                +

                ​

                +

                2. PREAMBLE (전문)

                +

                The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.

                +

                ​

                +

                The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works.

                +

                ​

                +

                The fonts and derivatives, however, cannot be released under any other type of license.

                +

                ​

                +

                The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives.

                +

                ​

                +

                본 폰트 라이선스를 오픈하는 것은(이하 OFL)는 전 세계 폰트 개발 프로젝트를 지원하고 학계와 언어 관련 학계의 폰트 개발을 위한 연구를 지지하기 위해서인 동시에, 폰트 제휴를 통해 폰트가 공유되고 개선될 수 있는 자유롭게 개방된 환경을 만들기 위해서입니다.

                +

                ​

                +

                OFL은 라이선스를 취득한 폰트가 그 자체로 판매되지 않는 한 자유롭게 사용, 연구, 수정, 재배포 하는 것을 허가합니다.

                +

                ​

                +

                수정된 폰트를 포함한 폰트는 저작권 명이 사용되지 않는 한 기타 소프트웨어와 함께 묶이거나 삽입, 재배포 할 수 있습니다.

                +

                ​

                +

                단 폰트와 수정된 폰트는 기타 다른 라이선스에 포함되어 배포될 수는 없습니다.

                +

                ​

                +

                이 라이선스 하에 있기 위한 폰트에 대한 요구사항은 본 폰트나 수정본을 사용하여 제작된 어떠한 문서에도 적용되지 않습니다.

                +

                ​

                +

                3. PERMISSION & CONDITIONS (허가 및 조건)

                +

                Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:

                +

                ​

                +

                본 폰트 소프트웨어를 사용하도록 허가받은 개인/기업/단체 누구라도 다음 명시된 조건에 따라 폰트 소프트웨어의 수정 혹은 수정되지 않은 복사본을 무료로 사용, 연구, 복사, 통합, 삽입, 수정, 재배포할 수 있도록 허가합니다.

                +

                ​

                +

                1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.

                +

                ​

                +

                원본이나 수정본의 폰트 소프트웨어 혹은 개별 구성요소인 폰트 자체가 판매되어서는 안됩니다.

                +

                ​

                +

                2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license.

                +

                ​

                +

                These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.

                +

                ​

                +

                본 폰트 소프트웨어의 원본 혹은 수정본은 상기 저작권 안내와 본 라이선스에 대한 내용을 포함하는 경우에는 다른 소프트웨어와 함께 묶이거나 재배포 혹은 판매가 가능합니다.

                +

                ​

                +

                이는 독립 텍스트 파일과 가독성이 있는 헤더 혹은 유저가 용이하게 열람 가능한 이상 텍스트 파일 혹은 이진 파일 내 기계가 읽을 수 있는 메타데이터 형태를 모두 의미합니다.

                +

                ​

                +

                3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder.

                +

                ​

                +

                This restriction only applies to the primary font name as presented to the users.

                +

                ​

                +

                본 폰트 소프트웨어의 어떠한 수정본도 동일한 저작권자가 명시적 허가서를 부여하지 않는 한 저작권이 있는 폰트명을 사용해서는 안 됩니다.

                +

                ​

                +

                본 제한 사항은 유저들에게 제공된 기존 폰트명을 뜻합니다.

                +

                ​

                +

                4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.

                +

                ​

                +

                본 폰트 소프트웨어의 저작권자 혹은 저자의 이름은 그들의 명시적 서면 허가가 있거나 또는 그들의 공헌을 인정하기 위한 경우를 제외하고는 수정본에 대한 사용을 유도, 추천 혹은 광고하기 위한 목적으로 사용할 수 없습니다.

                +

                ​

                +

                5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed any other license.

                +

                ​

                +

                The requirement for fonts to remain under this license does not apply to any document created using the Font Software.

                +

                ​

                +

                본 폰트 소프트웨어는 전체나 부분, 혹은 수정 여부에 상관없이 본 라이선스 하에 배포가 되어야 하며 기타 다른 라이선스 하에서는 배포를 할 수 없습니다.

                +

                ​

                +

                폰트에 대한 요구 조건은 이 라이선스 하에서만 유효하며 이 라이선스 하에 있기 위한 폰트에 대한 요구사항은 본 폰트 소프트웨어를 사용해 제작한 어떠한 문서에도 적용되지 않습니다.

                +

                ​

                +

                4. TERMINATION (계약의 종료)

                +

                This license becomes null and void if any of the above conditions are not met.

                +

                ​

                +

                본 라이선스는 상기 조건 중 일부라도 부합되지 않으면 무효가 될 수 있습니다.

                +

                ​

                +

                5. DISCLAIMER (면책조항)

                +

                THE FONT SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT.

                +

                ​

                +

                IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.

                +

                ​

                +

                본 폰트 소프트웨어는 저작권, 특허권, 상표권 및 기타 권리의 비침해성과 특정 목적에의 적합성 포함한 명시적, 묵시적인 어떠한 종류의 보증 없이 “있는 그대로” 제공됩니다.

                +

                ​

                +

                어떠한 경우에도 저작권자는 본 폰트 소프트웨어의 사용 또는 이의 사용 불가, 그밖에 폰트 소프트웨어의 취급과 관련하여 발생하는 모든 계약, 불법행위 혹은 다른 일로 하여금 발생하는 일반적, 특수적, 간접적, 부차적 혹은 필연적 손해를 포함하는 소송, 손해, 혹은 기타 책임에 대한 의무를 가지지 않습니다.

                + +
                +
                +
                + +
                +
                만족도 평가
              \ No newline at end of file diff --git a/apps/site/public/work/materia-interior/assets/fonts/MaruBuri-Regular.woff2 b/apps/site/public/work/materia-interior/assets/fonts/MaruBuri-Regular.woff2 new file mode 100644 index 0000000..3bc205f Binary files /dev/null and b/apps/site/public/work/materia-interior/assets/fonts/MaruBuri-Regular.woff2 differ diff --git a/apps/site/public/work/materia-interior/assets/fonts/MaruBuri-SemiBold.woff2 b/apps/site/public/work/materia-interior/assets/fonts/MaruBuri-SemiBold.woff2 new file mode 100644 index 0000000..be593a5 Binary files /dev/null and b/apps/site/public/work/materia-interior/assets/fonts/MaruBuri-SemiBold.woff2 differ diff --git a/apps/site/public/work/materia-interior/assets/fonts/SOURCES.md b/apps/site/public/work/materia-interior/assets/fonts/SOURCES.md new file mode 100644 index 0000000..66d2c89 --- /dev/null +++ b/apps/site/public/work/materia-interior/assets/fonts/SOURCES.md @@ -0,0 +1,13 @@ +# MaruBuri source record + +Downloaded 2026-09-12 from the official NAVER Hangeul static host. The files are retained unchanged: no conversion or subsetting was performed. + +| File | Official URL | HTTP content type | Size | SHA-256 | +| --- | --- | --- | --- | --- | +| `MaruBuri-Regular.woff2` | https://hangeul.pstatic.net/hangeul_static/webfont/MaruBuri/MaruBuri-Regular.woff2 | `font/woff2` | 433776 bytes | `4CF1341CF2F23FB3E263712DFDE1D8F25EEDCC328B696A2E5A2C8ADD55E5C17B` | +| `MaruBuri-SemiBold.woff2` | https://hangeul.pstatic.net/hangeul_static/webfont/MaruBuri/MaruBuri-SemiBold.woff2 | `font/woff2` | 466108 bytes | `7AEF4862FA3219B0A7DEB6746E27116A38C4069F4424EB51EDF103B29795F5C2` | + +- Official stylesheet checked: https://hangeul.pstatic.net/hangeul_static/css/maru-buri.css +- Official NAVER license page saved verbatim as `LICENSE.html`: https://help.naver.com/service/11029/contents/18088?lang=ko&osType=PC +- `LICENSE.html` SHA-256: `8538F7921744D5E040F603BC301465EFBD038F1054D0754B7508DE3286452EC3` +- The saved official page includes the NAVER copyright notice and the SIL Open Font License 1.1 text for MaruBuri. diff --git a/apps/site/public/work/materia-interior/design.md b/apps/site/public/work/materia-interior/design.md new file mode 100644 index 0000000..55c41c6 --- /dev/null +++ b/apps/site/public/work/materia-interior/design.md @@ -0,0 +1,17 @@ +# 마테리아 스튜디오 — 디자인 결정 기록 + +## 관찰과 방향 + +- 관찰: 기존 hero는 텍스트와 장식 프레임의 비중이 커서 공간 사진이 건축 포트폴리오의 첫 증거가 되지 못했다. +- 원리 적용 범위: 사진은 공간의 빛·재료를 먼저 보이고 제목과 짧은 설명은 같은 시작선에서 범위를 설명한다. 프로젝트 목록은 대표 사례 하나와 보조 사례 둘을 구분하며, 물성은 같은 항목 위계로 비교한다. +- 결정: hero를 5:7 사진 우세로, 대표 프로젝트를 큰 카드로 조정하고 캡션을 사진의 정렬선에 맞췄다. 브론즈·따뜻한 종이 토큰과 Day/Night, 24개 상세 갤러리·라이트박스·legacy 경로를 유지한다. +- 기각 조건: 사진 크롭이 공간의 주피사체를 잃거나 Day/Night에서 캡션·필터·상태 대비가 약해지면 크롭과 표면 조합을 다시 조정한다. + +## 토큰과 검증 + +- 타입: 로컬 `MaruBuri` 400·600은 제목·물성명, Pretendard는 본문, 모노는 메타데이터 역할을 유지한다. +- 색: `--surface #f5f3ef`, 브론즈 `--accent #76583d`, 나이트 토큰의 대비를 유지한다. +- 구도: hero 5:7, 사진 7:5, 대표 프로젝트는 넓은 화면에서 2행을 차지하며 860px 이하는 한 열이다. +- `verify-final` 18개 묶음은 16개가 즉시 통과했다. 전체 묶음의 invariant·visual 검사는 Gaon·Dure를 대상으로 하며, 나머지 2개는 수정 뒤 release 독립 재실행에서 ALL PASS·ALL MATCH였다. +- root는 28개 모바일, 21개 데스크톱, 7개 하위 경로와 30개 앱 상태를 직접 검토해 수용했다. stress 112건은 hard failure 0이며, 가로 넘침 4건은 targeted fix 뒤 390px 재측정에서 0이다. +- 이 기록은 렌더·계약 범위의 현재 결과다. 모든 폭·키보드 경로·인쇄 등 개별 기능을 완전 재실행했다는 뜻이 아니며, 참여자 과업 효과도 미측정이다. diff --git a/apps/site/public/work/materia-interior/hannam-duplex.html b/apps/site/public/work/materia-interior/hannam-duplex.html index 856f551..d542640 100644 --- a/apps/site/public/work/materia-interior/hannam-duplex.html +++ b/apps/site/public/work/materia-interior/hannam-duplex.html @@ -6,7 +6,9 @@ 한남 듀플렉스 펜트하우스 — 이동 중 - + + + +
              @@ -368,7 +400,7 @@
              - 상담 신청 + 상담 항목 보기
              @@ -392,6 +424,7 @@

              5.8m 보이드 천장고와 로만 트래버틴, 3,000년 훈증 오크가 빚어낸 침묵의 공간.

              +

              안내: 아래 프로젝트 설명·이미지·수치·갤러리는 공간 연출 예시입니다. 실제 매물·시공·상담을 제공하지 않습니다.

              @@ -426,8 +459,8 @@ 한남 듀플렉스 펜트하우스 5.8m 보이드 거실 전경과 트래버틴 벽체
              @@ -475,20 +508,20 @@
              -