feat(showcase): 신규 쇼케이스 3종 — RFS · 트웬티온스 · 새벽청과
Some checks failed
ci / build (push) Failing after 1m52s
Some checks failed
ci / build (push) Failing after 1m52s
각 워크를 서로 다른 클라이언트로 보고 0~6단계를 따로 돌았다(토큰 체계 신규 정의 = 전체 경로). 셋 모두 라이트/다크 반전을 .band-light / .band-dark 가 --band-* 를 재정의하는 규칙으로 정의해 하드 게이트 4를 통과시켰다 — 반전이 섹션마다의 기분이 아니라 두 클래스가 만드는 규칙이다. RFS — 실시간 유체 시뮬레이터 (rfs-cfd) 프리셋 darkroom-spec · 컨셉 "암실과 사양서" R1 luminary.ai · R2 teenage.engineering EP-133 · 보조 simscale.com (전부 실측) 히어로에서 브라우저가 실제로 Navier–Stokes 를 푼다. 순수 WebGL2, three.js 미사용. 이류 → 온도 소스 → 부력·설비 힘 → 발산 → 압력 Jacobi → 투영 → 파티클 전진. 격자 224×126 / 파티클 26,000 / Jacobi 22회, 좁은 화면은 절반으로 줄인다. prefers-reduced-motion 이면 시작하지 않고 그 자리에 RFS 실물 파티클 렌더가 남는다. 단위계로 세 번 실패했다: dt 를 프레임 단위로 넘겨 파티클이 0.2초 만에 소멸했고, 전부 급기구에서만 재생성해 실 한 가닥이 됐으며, 랙이 위로 뿜어 핫/콜드 아일이 갈라지지 않았다. dt 를 초로 못박고 속도를 초당 격자 셀로 통일해 해결했다. 수치는 전부 RFS 저장소 README 출처. 정확도 지표는 싣지 않았다 — 사내 검증 자료이고 현재 통과 상태가 아니다. 트웬티온스 (twentyoz-corp) 프리셋 field-record · 컨셉 "네 개의 현장" R1 samsara.com · R2 lars-mueller-publishers.com · R3 = 현행 twentyoz.kr 감사 현행 사이트 실측: 대비 실패 172개 요소(9~11px 가 3.61:1), 한글 폰트 미지정으로 한글이 시스템 기본으로 떨어짐, h1 자간 −0.06em(한글 상한의 세 배), 배경 #020202. 'Digital Genetics' 은유가 산업용 IoT 사업을 가리고 있었다. 유지한 자산은 radius 0 과 무채색·모노 기조. 첫 화면에 회사 이름 대신 현장 선택기를 뒀다 — 라디오 그룹이라 JS 0바이트이고 좌우 화살표 키가 그냥 먹는다. 파트너 19곳은 원본에 도메인 표기가 없어 나누지 않았다. 새벽청과 (saebyeok-cheonggwa) 프리셋 market-board · 컨셉 "오늘 새벽 두 시의 값" R1 natoora.com · R2 phillips.com · R3 제철 12개월 띠 커머스가 감추는 시세 변동을 히어로의 주인공으로 삼았다. 상품 사진은 아래로 내렸다. 경매 시각·경락가격·등급·당도 표시 규정을 조사해 카피의 근거로 썼다. 무화과 당도를 "—" 로 두고 값이 없는 게 아니라 표시가 허용되지 않는 품목이라고 적었다. 등락은 색이 아니라 ▲▼보합 기호가 먼저다. 표의 숫자가 예시임을 판 아래와 푸터 두 곳에 명시하고, 주소·전화는 비웠다(게이트 11). 사진 4장은 codex 내장 image_gen 생성물이며 합계 341KB. 검증: Astro 빌드 통과, verify 체인 L0~L6 10계층 전부 통과, showcase-audit 신규 3종 12/12 통과(320/390/768/1440). 성능 실측(RFS): JS 24KB · 총 704KB. 폰트만 530KB 로 예산(200KB) 초과 — 한글 웹폰트 자체가 원인이고 기존 cheongon-care 는 650KB 로 더 크다. 저장소 공통 baseline 이라 이번 판은 기록만 남기고 넘어간다. 기존 16종에서 발견된 70건(대비 미달·히어로 줄 수 초과)은 이번 범위를 넘어 design.md 에 목록만 남겼다.
This commit is contained in:
parent
123d9fc5a8
commit
4d813420dc
31 changed files with 5973 additions and 11 deletions
643
apps/site/public/work/twentyoz-corp/index.html
Normal file
643
apps/site/public/work/twentyoz-corp/index.html
Normal file
|
|
@ -0,0 +1,643 @@
|
|||
<!doctype html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
||||
<title>트웬티온스 — 네 개의 현장에서 돌아가는 소프트웨어</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="2020년 설립. 가상현실·산업용 IoT·이커머스 솔루션 전문 기업. VIVEN·EduBill·XD Hub·XD Works 네 개의 자체 제품이 강의실, 데이터센터, 공공기관, 공장 현장에서 돌아간다."
|
||||
/>
|
||||
<meta property="og:title" content="트웬티온스 — 네 개의 현장" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="회사 소개 대신 한 일을 앞에 둔다. 6년 159건, 자체 제품 4종."
|
||||
/>
|
||||
<meta property="og:type" content="website" />
|
||||
<meta name="theme-color" content="#fafaf8" />
|
||||
|
||||
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap"
|
||||
/>
|
||||
<link rel="stylesheet" href="./styles/main.css" />
|
||||
<link
|
||||
rel="icon"
|
||||
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' fill='%23111214'/%3E%3Ctext x='16' y='22' font-family='monospace' font-size='15' font-weight='700' fill='%23FAFAF8' text-anchor='middle'%3E20%3C/text%3E%3C/svg%3E"
|
||||
/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a class="skip-link" href="#main">본문으로 건너뛰기</a>
|
||||
|
||||
<header class="site-head">
|
||||
<div class="wrap head-inner">
|
||||
<a class="wordmark" href="#top">
|
||||
<span class="wordmark-badge mono" aria-hidden="true">20</span>
|
||||
<span>트웬티온스</span>
|
||||
</a>
|
||||
<nav class="nav" aria-label="주요 섹션">
|
||||
<a href="#products">제품</a>
|
||||
<a href="#ledger">한 일</a>
|
||||
<a href="#record">기록</a>
|
||||
<a href="#contact">연락</a>
|
||||
</nav>
|
||||
<p class="head-meta mono">EST. 2020</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main id="main">
|
||||
<!-- ══════════════════════════════════════════════════════════
|
||||
1 · 히어로 = 현장 선택기.
|
||||
회사 이름과 슬로건을 첫 화면에 두지 않는다 — 감수한 리스크다
|
||||
══════════════════════════════════════════════════════════ -->
|
||||
<section class="band band-light hero" id="top" aria-labelledby="heroHeading">
|
||||
<div class="wrap">
|
||||
<h1 id="heroHeading">
|
||||
네 개의 현장에서<br />
|
||||
돌아가고 있다
|
||||
</h1>
|
||||
<p class="hero-lead">
|
||||
트웬티온스는 2020년 1월에 세운 가상현실·산업용 IoT·이커머스 솔루션 회사입니다.
|
||||
어느 현장의 이야기부터 보시겠습니까.
|
||||
</p>
|
||||
|
||||
<form class="fields">
|
||||
<fieldset>
|
||||
<legend class="sr-only">현장 고르기</legend>
|
||||
|
||||
<input type="radio" name="field" id="field-edu" class="field-radio" checked />
|
||||
<input type="radio" name="field" id="field-dc" class="field-radio" />
|
||||
<input type="radio" name="field" id="field-gov" class="field-radio" />
|
||||
<input type="radio" name="field" id="field-plant" class="field-radio" />
|
||||
|
||||
<div class="field-tabs">
|
||||
<label for="field-edu">
|
||||
<span class="tab-num mono">01</span>
|
||||
<span class="tab-name">강의실과 훈련장</span>
|
||||
</label>
|
||||
<label for="field-dc">
|
||||
<span class="tab-num mono">02</span>
|
||||
<span class="tab-name">데이터센터와 발전소</span>
|
||||
</label>
|
||||
<label for="field-gov">
|
||||
<span class="tab-num mono">03</span>
|
||||
<span class="tab-name">공공기관과 대학 행정</span>
|
||||
</label>
|
||||
<label for="field-plant">
|
||||
<span class="tab-num mono">04</span>
|
||||
<span class="tab-name">공장과 설비 현장</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="field-panels">
|
||||
<article class="field-panel" data-panel="edu">
|
||||
<p class="panel-what">
|
||||
헤드셋을 쓴 학생이 실습을 하고, 강사는 그 장면을 밖에서 본다.
|
||||
캐릭터의 몸짓은 웹캠 한 대로 잡는다.
|
||||
</p>
|
||||
<dl class="panel-facts">
|
||||
<div>
|
||||
<dt>제품</dt>
|
||||
<dd><strong>VIVEN</strong> — 몰입형 VR 교육·훈련 플랫폼</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>기술</dt>
|
||||
<dd class="mono">Unity3D × WebXR × MediaPipe</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>특징</dt>
|
||||
<dd>PC VMC · Mobile VMC 모듈로 캐릭터 실시간 모션캡처</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>납품 사례</dt>
|
||||
<dd>미래기술학교 운영 (2024) · 메타버스 기반 교육 플랫폼</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>성숙도</dt>
|
||||
<dd class="mono">TRL 9 · 2021 – 현재</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</article>
|
||||
|
||||
<article class="field-panel" data-panel="dc">
|
||||
<p class="panel-what">
|
||||
설비 여섯 종류가 각자의 프로토콜로 떠드는 것을 한 엔진이 받아
|
||||
같은 시간축에 올린다. 그 위에서 운전이 자동으로 돈다.
|
||||
</p>
|
||||
<dl class="panel-facts">
|
||||
<div>
|
||||
<dt>제품</dt>
|
||||
<dd>
|
||||
<strong>XD Hub</strong> — 산업용 IoT 데이터 통합 엔진<br />
|
||||
<strong>XD Works</strong> — DCIM · FEMS 통합 운영 애플리케이션
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>기술</dt>
|
||||
<dd class="mono">
|
||||
Java Spring Boot × Netty × TimescaleDB<br />
|
||||
Spring Boot × NestJS × TypeScript
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>특징</dt>
|
||||
<dd>6종 산업 프로토콜을 단일 엔진으로 수집·전처리·전송</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>납품 사례</dt>
|
||||
<dd>
|
||||
과천 데이터 센터 · LS 일렉 청주 FEMS · 제주 폐기물 EMS ·
|
||||
비금도 EMS · 한유 AFIMS (모두 2024)
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>성숙도</dt>
|
||||
<dd class="mono">TRL 8 · 2022 – 현재</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</article>
|
||||
|
||||
<article class="field-panel" data-panel="gov">
|
||||
<p class="panel-what">
|
||||
해외 AI 서비스를 쓰고 싶은데 법인카드도 세금계산서도 안 되는 기관이 있다.
|
||||
그 사이에 들어가 원화 결제와 증빙을 대신한다.
|
||||
</p>
|
||||
<dl class="panel-facts">
|
||||
<div>
|
||||
<dt>제품</dt>
|
||||
<dd><strong>EduBill</strong> — AI SaaS 구독 대행 플랫폼</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>기술</dt>
|
||||
<dd class="mono">Next.js × TypeScript × Supabase PostgreSQL</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>쓰는 곳</dt>
|
||||
<dd>공공기관 · 대학 · 초중고 · 기업 HRD</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>납품 사례</dt>
|
||||
<dd>KDIS EAI (2024) · EduBill (2024)</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>성숙도</dt>
|
||||
<dd class="mono">TRL 8 · 2024 – 현재</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</article>
|
||||
|
||||
<article class="field-panel" data-panel="plant">
|
||||
<p class="panel-what">
|
||||
현장에서는 사무실 화면이 안 열린다. 장갑 낀 손과 밝은 햇빛,
|
||||
끊기는 통신을 전제로 다시 만든다.
|
||||
</p>
|
||||
<dl class="panel-facts">
|
||||
<div>
|
||||
<dt>성격</dt>
|
||||
<dd>고객사 설비·공정에 맞춰 짓는 현장 애플리케이션</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>납품 사례</dt>
|
||||
<dd>
|
||||
브래키츠 BSLIM · 영진EL 2.0 스마트 APP · LS 전선 부스덕트 (모두 2024)
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>기술</dt>
|
||||
<dd class="mono">Spring Boot / PostgreSQL / WebSocket · Vue3</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>가장 무거운 것</dt>
|
||||
<dd>
|
||||
ACS (Auto Control System) — Unity Engine · RFS 실시간 유체 시뮬레이션 ·
|
||||
Transformer 기반 AI (2024)
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</article>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ══════════════════════════════════════════════════════════
|
||||
2 · 회사
|
||||
══════════════════════════════════════════════════════════ -->
|
||||
<section class="band band-light section-about" id="about" aria-labelledby="aboutHeading">
|
||||
<div class="wrap split">
|
||||
<div class="split-lead">
|
||||
<h2 id="aboutHeading">여섯 해 동안 쌓인 것</h2>
|
||||
</div>
|
||||
<div class="split-body">
|
||||
<p class="lead">
|
||||
서로 다른 산업의 프로젝트 경험과 새 기술을 붙여, 고객이 다음 성장 동력을 찾도록
|
||||
돕는 것이 하는 일입니다. 에너지, 건물 자동화, 헬스케어처럼 틀리면 곤란한 영역이
|
||||
주 무대입니다.
|
||||
</p>
|
||||
<dl class="counts">
|
||||
<div>
|
||||
<dt>수행 프로젝트</dt>
|
||||
<dd class="mono">159<span>건</span></dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>고객사</dt>
|
||||
<dd class="mono">42<span>곳</span></dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>구성원</dt>
|
||||
<dd class="mono">40<span>명</span></dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>특허</dt>
|
||||
<dd class="mono">4<span>건</span></dd>
|
||||
</div>
|
||||
</dl>
|
||||
<p class="counts-note">
|
||||
위 넷은 회사가 공개한 값입니다. 아래 <a href="#ledger">한 일</a> 목록에는
|
||||
그중 공개 가능한 49건의 일부를 이름·연도·기술 스택과 함께 적었습니다.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ══════════════════════════════════════════════════════════
|
||||
3 · 제품 — 반전 밴드. 제품은 기계다
|
||||
══════════════════════════════════════════════════════════ -->
|
||||
<section class="band band-dark section-products" id="products" aria-labelledby="prodHeading">
|
||||
<div class="wrap">
|
||||
<p class="eyebrow">자체 제품</p>
|
||||
<h2 id="prodHeading">팔러 다니는 것이 아니라 계속 고치는 것</h2>
|
||||
<p class="section-lead">
|
||||
네 개 모두 특정 고객의 요구에서 시작해 제품이 됐습니다. 지금도 각자의 개발 주기가
|
||||
돌아가고 있습니다.
|
||||
</p>
|
||||
|
||||
<ol class="product-list">
|
||||
<li>
|
||||
<p class="prod-id mono">V–01</p>
|
||||
<div class="prod-body">
|
||||
<h3>VIVEN <span class="prod-kind">메타버스 플랫폼</span></h3>
|
||||
<p>
|
||||
기업과 교육기관을 위한 몰입형 VR 교육·훈련 플랫폼. PC VMC 와 Mobile VMC
|
||||
모듈로 캐릭터 실시간 모션캡처를 지원합니다.
|
||||
</p>
|
||||
<p class="prod-stack mono">Unity3D × WebXR × MediaPipe</p>
|
||||
</div>
|
||||
<dl class="prod-meta mono">
|
||||
<div><dt>규모</dt><dd>Enterprise</dd></div>
|
||||
<div><dt>주기</dt><dd>2021 –</dd></div>
|
||||
<div><dt>성숙도</dt><dd>TRL 9</dd></div>
|
||||
</dl>
|
||||
</li>
|
||||
<li>
|
||||
<p class="prod-id mono">V–02</p>
|
||||
<div class="prod-body">
|
||||
<h3>EduBill <span class="prod-kind">교육 SaaS</span></h3>
|
||||
<p>
|
||||
공공기관·대학·초중고·기업 HRD 를 위한 AI SaaS 구독 대행 플랫폼.
|
||||
해외 AI 서비스를 원화 결제와 세금계산서 발행으로 들여옵니다.
|
||||
</p>
|
||||
<p class="prod-stack mono">Next.js × TypeScript × Supabase PostgreSQL</p>
|
||||
</div>
|
||||
<dl class="prod-meta mono">
|
||||
<div><dt>규모</dt><dd>B2G · 교육</dd></div>
|
||||
<div><dt>주기</dt><dd>2024 –</dd></div>
|
||||
<div><dt>성숙도</dt><dd>TRL 8</dd></div>
|
||||
</dl>
|
||||
</li>
|
||||
<li>
|
||||
<p class="prod-id mono">V–03</p>
|
||||
<div class="prod-body">
|
||||
<h3>XD Hub <span class="prod-kind">산업용 IoT</span></h3>
|
||||
<p>
|
||||
데이터센터·제조·에너지·빌딩 도메인을 위한 산업용 IoT 데이터 통합 엔진.
|
||||
6종 산업 프로토콜을 단일 엔진으로 수집·전처리·전송합니다.
|
||||
</p>
|
||||
<p class="prod-stack mono">Java Spring Boot × Netty × TimescaleDB</p>
|
||||
</div>
|
||||
<dl class="prod-meta mono">
|
||||
<div><dt>규모</dt><dd>설비</dd></div>
|
||||
<div><dt>주기</dt><dd>2022 –</dd></div>
|
||||
<div><dt>성숙도</dt><dd>TRL 8</dd></div>
|
||||
</dl>
|
||||
</li>
|
||||
<li>
|
||||
<p class="prod-id mono">V–04</p>
|
||||
<div class="prod-body">
|
||||
<h3>XD Works <span class="prod-kind">DCIM · FEMS</span></h3>
|
||||
<p>
|
||||
XD Hub 가 모은 데이터를 받아 데이터센터 코로케이션, 빌딩, 공장, 발전소의
|
||||
운영을 자동화하는 통합 운영 애플리케이션입니다.
|
||||
</p>
|
||||
<p class="prod-stack mono">Spring Boot × NestJS × TypeScript</p>
|
||||
</div>
|
||||
<dl class="prod-meta mono">
|
||||
<div><dt>규모</dt><dd>설비 · B2B</dd></div>
|
||||
<div><dt>주기</dt><dd>2023 –</dd></div>
|
||||
<div><dt>성숙도</dt><dd>TRL 8</dd></div>
|
||||
</dl>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ══════════════════════════════════════════════════════════
|
||||
4 · 한 일 — 프로젝트 원장
|
||||
══════════════════════════════════════════════════════════ -->
|
||||
<section class="band band-light section-ledger" id="ledger" aria-labelledby="ledgerHeading">
|
||||
<div class="wrap">
|
||||
<h2 id="ledgerHeading">한 일</h2>
|
||||
<p class="section-lead">
|
||||
공개 가능한 49건 가운데 12건입니다. 회사 소개서에 쓰는 문장 대신 이름과 연도,
|
||||
그리고 무엇으로 만들었는지를 적습니다.
|
||||
</p>
|
||||
|
||||
<table class="ledger">
|
||||
<caption class="sr-only">트웬티온스 수행 프로젝트 12건 — 이름, 연도, 사용 기술</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="col-id">번호</th>
|
||||
<th scope="col">프로젝트</th>
|
||||
<th scope="col" class="col-year">연도</th>
|
||||
<th scope="col">기술</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="mono">001</td>
|
||||
<th scope="row">EduBill</th>
|
||||
<td class="mono">2024</td>
|
||||
<td class="mono">Next.js · TypeScript · Supabase PostgreSQL</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">002</td>
|
||||
<th scope="row">과천 데이터 센터</th>
|
||||
<td class="mono">2024</td>
|
||||
<td class="mono">Vue3 · Spring · PostgreSQL</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">003</td>
|
||||
<th scope="row">제주 폐기물 EMS</th>
|
||||
<td class="mono">2024</td>
|
||||
<td class="mono">Vue3 · Spring · PostgreSQL</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">004</td>
|
||||
<th scope="row">KDIS EAI</th>
|
||||
<td class="mono">2024</td>
|
||||
<td class="mono">Vue3 · Spring · PostgreSQL</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">005</td>
|
||||
<th scope="row">LS 일렉 청주 FEMS</th>
|
||||
<td class="mono">2024</td>
|
||||
<td class="mono">Vue3 · Spring · PostgreSQL</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">006</td>
|
||||
<th scope="row">LS 전선 부스덕트</th>
|
||||
<td class="mono">2024</td>
|
||||
<td class="mono">Vue3 · Spring · PostgreSQL</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">007</td>
|
||||
<th scope="row">브래키츠 BSLIM</th>
|
||||
<td class="mono">2024</td>
|
||||
<td class="mono">Spring Boot · PostgreSQL · WebSocket</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">008</td>
|
||||
<th scope="row">영진EL 2.0 스마트 APP</th>
|
||||
<td class="mono">2024</td>
|
||||
<td class="mono">Vue3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">009</td>
|
||||
<th scope="row">미래기술학교 운영</th>
|
||||
<td class="mono">2024</td>
|
||||
<td class="mono">Unity Engine · Blender · Unreal Engine</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">010</td>
|
||||
<th scope="row">한유 AFIMS</th>
|
||||
<td class="mono">2024</td>
|
||||
<td class="mono">Vue3 · Spring · PostgreSQL</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="mono">011</td>
|
||||
<th scope="row">비금도 EMS</th>
|
||||
<td class="mono">2024</td>
|
||||
<td class="mono">Vue3 · Spring · Java</td>
|
||||
</tr>
|
||||
<tr class="row-mark">
|
||||
<td class="mono">012</td>
|
||||
<th scope="row">ACS (Auto Control System)</th>
|
||||
<td class="mono">2024</td>
|
||||
<td class="mono">Unity Engine · RFS 실시간 유체 시뮬레이션 · Transformer 기반 AI</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="ledger-note">
|
||||
마지막 줄이 지금 가장 멀리 가 있는 일입니다. 데이터센터의 공기 흐름을 GPU 위에서
|
||||
실시간으로 풀어 제어를 검증합니다.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ══════════════════════════════════════════════════════════
|
||||
5 · 함께 일한 곳
|
||||
══════════════════════════════════════════════════════════ -->
|
||||
<section class="band band-light section-partners" id="partners" aria-labelledby="partnersHeading">
|
||||
<div class="wrap">
|
||||
<h2 id="partnersHeading">함께 일한 곳</h2>
|
||||
<p class="section-lead">
|
||||
대학과 대기업 설비 부문이 섞여 있습니다. 어느 쪽이든 검수 기준이 까다로운 곳입니다.
|
||||
</p>
|
||||
<ul class="partners">
|
||||
<li>LS SAUTER</li>
|
||||
<li>경희대학교</li>
|
||||
<li>SAEKI P&C</li>
|
||||
<li>KDI School</li>
|
||||
<li>COSS 사업단</li>
|
||||
<li>클라우드브릭</li>
|
||||
<li>한유</li>
|
||||
<li>게임랩</li>
|
||||
<li>METANET PLATFORM</li>
|
||||
<li>안랩</li>
|
||||
<li>강원대학교</li>
|
||||
<li>중앙대학교</li>
|
||||
<li>건국대학교</li>
|
||||
<li>한화솔루션</li>
|
||||
<li>가비아</li>
|
||||
<li>GS칼텍스</li>
|
||||
<li>SK하이닉스</li>
|
||||
<li>LG디스플레이</li>
|
||||
<li>대구한의대학교</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ══════════════════════════════════════════════════════════
|
||||
6 · 기록 — 반전 밴드
|
||||
══════════════════════════════════════════════════════════ -->
|
||||
<section class="band band-dark section-record" id="record" aria-labelledby="recordHeading">
|
||||
<div class="wrap">
|
||||
<p class="eyebrow">최근 기록</p>
|
||||
<h2 id="recordHeading">밖에서 확인된 것</h2>
|
||||
|
||||
<ol class="record-list">
|
||||
<li>
|
||||
<p class="rec-date mono">2026.02.24</p>
|
||||
<div>
|
||||
<h3>경기우수벤처기업 표창 — 경기지방중소벤처기업청장상</h3>
|
||||
<p>기술·경영·혁신 능력이 뛰어나고 사회공헌도가 높은 벤처기업으로 인정</p>
|
||||
</div>
|
||||
<p class="rec-kind">수상 · 인증</p>
|
||||
</li>
|
||||
<li>
|
||||
<p class="rec-date mono">2026.01.20</p>
|
||||
<div>
|
||||
<h3>2025 경기도 일자리 우수기업 인증</h3>
|
||||
<p>고용증가율 10% 이상, 근무환경과 복리후생 제도 개선으로 인정</p>
|
||||
</div>
|
||||
<p class="rec-kind">수상 · 인증</p>
|
||||
</li>
|
||||
<li>
|
||||
<p class="rec-date mono">2025.11.03</p>
|
||||
<div>
|
||||
<h3>건국대, 시리아·요르단 교육기관 대표단 방문</h3>
|
||||
<p>트웬티온스와 함께 개발한 메타버스 기반 교육 플랫폼 시연</p>
|
||||
</div>
|
||||
<p class="rec-kind">교육 · 협력</p>
|
||||
</li>
|
||||
<li>
|
||||
<p class="rec-date mono">2025.10.31</p>
|
||||
<div>
|
||||
<h3>중동 대표단, X-Space 에서 K-에듀테크 체험</h3>
|
||||
<p>메타버스 기반 교육 플랫폼 체험과 협력 논의</p>
|
||||
</div>
|
||||
<p class="rec-kind">교육 · 협력</p>
|
||||
</li>
|
||||
<li>
|
||||
<p class="rec-date mono">2025.08.19</p>
|
||||
<div>
|
||||
<h3>과기정통부 2025 가상융합대학원 성과공유회</h3>
|
||||
<p>서강대 개최. AI 시대 인재양성 비전 논의에 참여</p>
|
||||
</div>
|
||||
<p class="rec-kind">행사</p>
|
||||
</li>
|
||||
<li>
|
||||
<p class="rec-date mono">2025.07.04</p>
|
||||
<div>
|
||||
<h3>벤처기업 혁신성장유형 재인증</h3>
|
||||
<p>기술 중심의 비전과 디지털 혁신 노력을 인정받음</p>
|
||||
</div>
|
||||
<p class="rec-kind">수상 · 인증</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ══════════════════════════════════════════════════════════
|
||||
7 · 채용
|
||||
══════════════════════════════════════════════════════════ -->
|
||||
<section class="band band-light section-career" id="career" aria-labelledby="careerHeading">
|
||||
<div class="wrap split">
|
||||
<div class="split-lead">
|
||||
<h2 id="careerHeading">지금은 정규 공고가 닫혀 있습니다</h2>
|
||||
</div>
|
||||
<div class="split-body">
|
||||
<p class="lead">
|
||||
다섯 개 직무가 모두 마감 상태입니다. 닫힌 것을 열려 있는 것처럼 적어 두면
|
||||
지원하는 쪽의 시간을 뺏게 되므로, 상태를 그대로 적습니다.
|
||||
</p>
|
||||
<ul class="jobs">
|
||||
<li>
|
||||
<span class="job-name">시니어 소프트웨어 엔지니어</span>
|
||||
<span class="job-hint">산업용 소프트웨어 · C++ / C# / Python · PLC · HMI · SCADA</span>
|
||||
<span class="job-state mono">마감</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="job-name">DevOps 엔지니어</span>
|
||||
<span class="job-hint">컨테이너 · 오케스트레이션 · CI/CD · IaC</span>
|
||||
<span class="job-state mono">마감</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="job-name">프로덕트 매니저</span>
|
||||
<span class="job-hint">IT 서비스 기획·운영 3년 이상 · 데이터 기반 의사결정</span>
|
||||
<span class="job-state mono">마감</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="job-name">서비스 기획자</span>
|
||||
<span class="job-hint">UI/UX 기획 · 와이어프레임 · 애자일 / 스크럼</span>
|
||||
<span class="job-state mono">마감</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="job-name">UI/UX 디자이너</span>
|
||||
<span class="job-hint">Figma · 웹 / 모바일 포트폴리오 · 사용자 중심 설계</span>
|
||||
<span class="job-state mono">마감</span>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="jobs-open">
|
||||
공고와 무관하게 이야기를 시작할 수는 있습니다.
|
||||
<a href="mailto:hello@twentyoz.kr?subject=%EC%B1%84%EC%9A%A9%20%EB%AC%B8%EC%9D%98">채용 문의 보내기</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ══════════════════════════════════════════════════════════
|
||||
8 · 연락
|
||||
══════════════════════════════════════════════════════════ -->
|
||||
<section class="band band-light section-contact" id="contact" aria-labelledby="contactHeading">
|
||||
<div class="wrap split">
|
||||
<div class="split-lead">
|
||||
<h2 id="contactHeading">연락</h2>
|
||||
</div>
|
||||
<div class="split-body">
|
||||
<dl class="contact-rows">
|
||||
<div>
|
||||
<dt>주소</dt>
|
||||
<dd>경기도 화성시 동탄첨단산업1로 27, A909호<br />(영천동, 금강펜테리움 IX 타워)</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>전화</dt>
|
||||
<dd><a class="mono" href="tel:+8207043531190">070-4353-1190</a></dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>메일</dt>
|
||||
<dd><a class="mono" href="mailto:hello@twentyoz.kr">hello@twentyoz.kr</a></dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>설립</dt>
|
||||
<dd class="mono">2020년 1월</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<a class="btn" href="mailto:hello@twentyoz.kr?subject=%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%20%EB%AC%B8%EC%9D%98">
|
||||
프로젝트 문의
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer class="band band-dark site-foot">
|
||||
<div class="wrap foot-inner">
|
||||
<p class="foot-name">트웬티온스 · TWENTYOZ</p>
|
||||
<p class="foot-line">
|
||||
가상현실 · 산업용 IoT · 이커머스 솔루션 · 경기도 화성시 동탄
|
||||
</p>
|
||||
<p class="foot-fine">© 2020–2026 TWENTYOZ</p>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
BIN
apps/site/public/work/twentyoz-corp/og.png
Normal file
BIN
apps/site/public/work/twentyoz-corp/og.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
842
apps/site/public/work/twentyoz-corp/styles/main.css
Normal file
842
apps/site/public/work/twentyoz-corp/styles/main.css
Normal file
|
|
@ -0,0 +1,842 @@
|
|||
@import "./tokens.css";
|
||||
|
||||
/* ==========================================================================
|
||||
트웬티온스 — 메인 스타일시트
|
||||
|
||||
현행 사이트는 순흑 한 겹이라 무엇이 중요한지 알 수 없었다. 종이를 기본으로
|
||||
뒤집고, 반전(잉크) 밴드는 '기계'를 다루는 두 섹션(제품·기록)에만 쓴다.
|
||||
반전은 아래 두 클래스가 토큰을 재정의하는 규칙이다 — 섹션마다 기분대로가 아니다.
|
||||
========================================================================== */
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: 16px;
|
||||
scroll-behavior: smooth;
|
||||
overflow-x: hidden;
|
||||
background: var(--surface);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100dvh;
|
||||
font-family: var(--font-body);
|
||||
font-size: var(--step-0);
|
||||
line-height: var(--leading-normal);
|
||||
background: var(--surface);
|
||||
color: var(--ink);
|
||||
word-break: keep-all;
|
||||
overflow-wrap: break-word;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
img,
|
||||
svg {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
font-weight: 600;
|
||||
line-height: var(--leading-tight);
|
||||
letter-spacing: -0.015em; /* 현행 사이트의 −0.06em 은 한글 상한의 세 배였다 */
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.mono {
|
||||
font-family: var(--font-mono);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip-path: inset(50%);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
width: min(100% - 2 * var(--pad-inline), var(--container));
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
/* ── 두 체제 ────────────────────────────────────────────────────── */
|
||||
.band-light {
|
||||
--band-surface: var(--surface);
|
||||
--band-surface-2: var(--surface-2);
|
||||
--band-surface-3: var(--surface-3);
|
||||
--band-line: var(--line);
|
||||
--band-line-strong: var(--line-strong);
|
||||
--band-ink: var(--ink);
|
||||
--band-ink-muted: var(--ink-muted);
|
||||
--band-ink-faint: var(--ink-faint);
|
||||
--band-accent: var(--accent);
|
||||
--band-accent-hover: var(--accent-hover);
|
||||
--band-accent-ink: var(--accent-ink);
|
||||
--band-accent-wash: var(--accent-wash);
|
||||
}
|
||||
|
||||
.band-dark {
|
||||
--band-surface: var(--dark-surface);
|
||||
--band-surface-2: var(--dark-surface-2);
|
||||
--band-surface-3: var(--dark-surface-3);
|
||||
--band-line: var(--dark-line);
|
||||
--band-line-strong: var(--dark-line-strong);
|
||||
--band-ink: var(--dark-ink);
|
||||
--band-ink-muted: var(--dark-ink-muted);
|
||||
--band-ink-faint: var(--dark-ink-faint);
|
||||
--band-accent: var(--dark-accent);
|
||||
--band-accent-hover: var(--dark-accent-hover);
|
||||
--band-accent-ink: var(--dark-accent-ink);
|
||||
--band-accent-wash: var(--dark-accent-wash);
|
||||
}
|
||||
|
||||
.band {
|
||||
position: relative;
|
||||
background: var(--band-surface);
|
||||
color: var(--band-ink);
|
||||
}
|
||||
|
||||
.band > .wrap {
|
||||
padding-block: var(--space-8);
|
||||
}
|
||||
|
||||
/* ── 접근성 ─────────────────────────────────────────────────────── */
|
||||
.skip-link {
|
||||
position: fixed;
|
||||
top: var(--space-3);
|
||||
left: var(--space-3);
|
||||
z-index: 200;
|
||||
padding: var(--space-2) var(--space-3);
|
||||
background: var(--ink);
|
||||
color: var(--surface);
|
||||
text-decoration: none;
|
||||
transform: translateY(-250%);
|
||||
transition: transform var(--dur-quick) var(--ease);
|
||||
}
|
||||
|
||||
.skip-link:focus-visible {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
:where(a, button, input, label, [tabindex]):focus-visible {
|
||||
outline: 2px solid var(--band-accent, var(--accent));
|
||||
outline-offset: 3px;
|
||||
}
|
||||
|
||||
/* ── 헤더 ───────────────────────────────────────────────────────── */
|
||||
.site-head {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
background: var(--surface);
|
||||
border-bottom: 1px solid var(--line-strong);
|
||||
}
|
||||
|
||||
.head-inner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-3);
|
||||
min-height: 56px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.wordmark {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.wordmark-badge {
|
||||
display: inline-grid;
|
||||
place-items: center;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
background: var(--ink);
|
||||
color: var(--surface);
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.nav {
|
||||
display: flex;
|
||||
gap: clamp(var(--space-3), 2.4vw, var(--space-5));
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.nav a {
|
||||
color: var(--ink-muted);
|
||||
font-size: var(--step--1);
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
padding-block: var(--space-2);
|
||||
transition: color var(--dur-quick) var(--ease);
|
||||
}
|
||||
|
||||
.nav a:hover {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.head-meta {
|
||||
font-size: var(--step--1);
|
||||
color: var(--ink-faint);
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* ── 히어로 ─────────────────────────────────────────────────────── */
|
||||
.hero h1 {
|
||||
font-size: var(--display);
|
||||
max-width: 16ch;
|
||||
}
|
||||
|
||||
.hero-lead {
|
||||
margin-top: var(--space-4);
|
||||
max-width: var(--measure);
|
||||
font-size: var(--step-1);
|
||||
color: var(--band-ink-muted);
|
||||
line-height: var(--leading-loose);
|
||||
}
|
||||
|
||||
/* ── 현장 선택기 — JS 0바이트. 라디오 그룹이라 좌우 화살표가 그대로 먹는다 ── */
|
||||
.fields {
|
||||
margin-top: var(--space-6);
|
||||
}
|
||||
|
||||
.field-radio {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.field-tabs {
|
||||
display: grid;
|
||||
border-top: 1px solid var(--line-strong);
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
@media (min-width: 720px) {
|
||||
.field-tabs {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.field-tabs label {
|
||||
display: block;
|
||||
padding: var(--space-3) var(--space-3) var(--space-3) 0;
|
||||
border-bottom: 1px solid var(--line);
|
||||
cursor: pointer;
|
||||
color: var(--ink-muted);
|
||||
transition: color var(--dur-quick) var(--ease);
|
||||
}
|
||||
|
||||
@media (min-width: 720px) {
|
||||
.field-tabs label {
|
||||
border-bottom: 0;
|
||||
border-right: 1px solid var(--line);
|
||||
padding-right: var(--space-4);
|
||||
padding-left: var(--space-3);
|
||||
}
|
||||
.field-tabs label:first-of-type {
|
||||
padding-left: 0;
|
||||
}
|
||||
.field-tabs label:last-of-type {
|
||||
border-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.field-tabs label:hover {
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.tab-num {
|
||||
display: block;
|
||||
font-size: var(--step--1);
|
||||
color: var(--ink-faint);
|
||||
}
|
||||
|
||||
.tab-name {
|
||||
display: block;
|
||||
margin-top: var(--space-1);
|
||||
font-weight: 600;
|
||||
font-size: var(--step-0);
|
||||
}
|
||||
|
||||
/* 선택 상태 — 라디오가 진실의 원본이다 */
|
||||
#field-edu:checked ~ .field-tabs label[for="field-edu"],
|
||||
#field-dc:checked ~ .field-tabs label[for="field-dc"],
|
||||
#field-gov:checked ~ .field-tabs label[for="field-gov"],
|
||||
#field-plant:checked ~ .field-tabs label[for="field-plant"] {
|
||||
color: var(--ink);
|
||||
box-shadow: inset 0 3px 0 0 var(--accent);
|
||||
}
|
||||
|
||||
#field-edu:checked ~ .field-tabs label[for="field-edu"] .tab-num,
|
||||
#field-dc:checked ~ .field-tabs label[for="field-dc"] .tab-num,
|
||||
#field-gov:checked ~ .field-tabs label[for="field-gov"] .tab-num,
|
||||
#field-plant:checked ~ .field-tabs label[for="field-plant"] .tab-num {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.field-radio:focus-visible ~ .field-tabs label[for="field-edu"] {
|
||||
outline: 2px solid var(--accent);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.field-panel {
|
||||
display: none;
|
||||
padding-top: var(--space-5);
|
||||
}
|
||||
|
||||
#field-edu:checked ~ .field-panels [data-panel="edu"],
|
||||
#field-dc:checked ~ .field-panels [data-panel="dc"],
|
||||
#field-gov:checked ~ .field-panels [data-panel="gov"],
|
||||
#field-plant:checked ~ .field-panels [data-panel="plant"] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.panel-what {
|
||||
font-size: var(--step-1);
|
||||
max-width: var(--measure);
|
||||
line-height: var(--leading-loose);
|
||||
}
|
||||
|
||||
.panel-facts {
|
||||
margin-top: var(--space-5);
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.panel-facts > div {
|
||||
display: grid;
|
||||
gap: var(--space-1) var(--space-4);
|
||||
padding-block: var(--space-3);
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.panel-facts > div {
|
||||
grid-template-columns: 8rem 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.panel-facts dt {
|
||||
font-size: var(--step--1);
|
||||
color: var(--ink-faint);
|
||||
}
|
||||
|
||||
.panel-facts dd {
|
||||
color: var(--ink-muted);
|
||||
line-height: var(--leading-loose);
|
||||
}
|
||||
|
||||
.panel-facts strong {
|
||||
color: var(--ink);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* ── 섹션 공통 ──────────────────────────────────────────────────── */
|
||||
.eyebrow {
|
||||
font-family: var(--font-mono);
|
||||
font-size: var(--step--1);
|
||||
color: var(--band-accent);
|
||||
margin-bottom: var(--space-3);
|
||||
}
|
||||
|
||||
.band h2 {
|
||||
font-size: var(--step-3);
|
||||
max-width: 20ch;
|
||||
}
|
||||
|
||||
.section-lead,
|
||||
.lead {
|
||||
margin-top: var(--space-4);
|
||||
max-width: var(--measure);
|
||||
color: var(--band-ink-muted);
|
||||
font-size: var(--step-1);
|
||||
line-height: var(--leading-loose);
|
||||
}
|
||||
|
||||
/* ── 비대칭 2열 ─────────────────────────────────────────────────── */
|
||||
.split {
|
||||
display: grid;
|
||||
gap: var(--space-5);
|
||||
}
|
||||
|
||||
@media (min-width: 900px) {
|
||||
.split {
|
||||
grid-template-columns: 4fr 8fr;
|
||||
gap: var(--space-7);
|
||||
align-items: start;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── 수치 ───────────────────────────────────────────────────────── */
|
||||
.counts {
|
||||
margin-top: var(--space-6);
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
|
||||
border-top: 1px solid var(--band-line-strong);
|
||||
border-left: 1px solid var(--band-line);
|
||||
}
|
||||
|
||||
.counts > div {
|
||||
padding: var(--space-4);
|
||||
border-right: 1px solid var(--band-line);
|
||||
border-bottom: 1px solid var(--band-line);
|
||||
}
|
||||
|
||||
.counts dt {
|
||||
font-size: var(--step--1);
|
||||
color: var(--band-ink-faint);
|
||||
}
|
||||
|
||||
.counts dd {
|
||||
margin-top: var(--space-2);
|
||||
font-size: var(--step-3);
|
||||
line-height: 1.05;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.counts dd span {
|
||||
font-size: var(--step-0);
|
||||
color: var(--band-ink-muted);
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.counts-note {
|
||||
margin-top: var(--space-4);
|
||||
font-size: var(--step--1);
|
||||
color: var(--band-ink-faint);
|
||||
line-height: var(--leading-loose);
|
||||
max-width: var(--measure);
|
||||
}
|
||||
|
||||
.counts-note a {
|
||||
color: var(--band-accent);
|
||||
}
|
||||
|
||||
/* ── 제품 목록 ──────────────────────────────────────────────────── */
|
||||
.product-list {
|
||||
margin-top: var(--space-6);
|
||||
list-style: none;
|
||||
border-top: 1px solid var(--band-line-strong);
|
||||
}
|
||||
|
||||
.product-list li {
|
||||
display: grid;
|
||||
gap: var(--space-3);
|
||||
padding-block: var(--space-5);
|
||||
border-bottom: 1px solid var(--band-line);
|
||||
}
|
||||
|
||||
@media (min-width: 900px) {
|
||||
.product-list li {
|
||||
grid-template-columns: 4rem 1fr 11rem;
|
||||
gap: var(--space-5);
|
||||
align-items: start;
|
||||
}
|
||||
}
|
||||
|
||||
.prod-id {
|
||||
font-size: var(--step--1);
|
||||
color: var(--band-accent);
|
||||
}
|
||||
|
||||
.prod-body h3 {
|
||||
font-size: var(--step-2);
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: var(--space-3);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.prod-kind {
|
||||
font-size: var(--step--1);
|
||||
font-weight: 400;
|
||||
color: var(--band-ink-faint);
|
||||
}
|
||||
|
||||
.prod-body p {
|
||||
margin-top: var(--space-3);
|
||||
color: var(--band-ink-muted);
|
||||
max-width: 46ch;
|
||||
line-height: var(--leading-loose);
|
||||
}
|
||||
|
||||
.prod-stack {
|
||||
font-size: var(--step--1);
|
||||
color: var(--band-ink-faint);
|
||||
}
|
||||
|
||||
.prod-meta {
|
||||
font-size: var(--step--1);
|
||||
display: grid;
|
||||
gap: var(--space-2);
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
.prod-meta > div {
|
||||
display: grid;
|
||||
grid-template-columns: 4rem 1fr;
|
||||
gap: var(--space-2);
|
||||
}
|
||||
|
||||
.prod-meta dt {
|
||||
color: var(--band-ink-faint);
|
||||
}
|
||||
|
||||
.prod-meta dd {
|
||||
color: var(--band-ink-muted);
|
||||
}
|
||||
|
||||
/* ── 원장 표 ────────────────────────────────────────────────────── */
|
||||
.ledger {
|
||||
margin-top: var(--space-6);
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: var(--step--1);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.ledger th,
|
||||
.ledger td {
|
||||
padding: var(--space-3) var(--space-3) var(--space-3) 0;
|
||||
border-bottom: 1px solid var(--band-line);
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.ledger thead th {
|
||||
border-bottom: 1px solid var(--band-line-strong);
|
||||
color: var(--band-ink-faint);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.ledger tbody th {
|
||||
font-weight: 600;
|
||||
font-size: var(--step-0);
|
||||
}
|
||||
|
||||
.ledger td {
|
||||
color: var(--band-ink-muted);
|
||||
}
|
||||
|
||||
.col-id {
|
||||
width: 3.5rem;
|
||||
}
|
||||
|
||||
.col-year {
|
||||
width: 4rem;
|
||||
}
|
||||
|
||||
.row-mark th,
|
||||
.row-mark td {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.row-mark th {
|
||||
color: var(--band-accent);
|
||||
}
|
||||
|
||||
.ledger-note {
|
||||
margin-top: var(--space-4);
|
||||
padding-top: var(--space-3);
|
||||
border-top: 2px solid var(--band-accent);
|
||||
font-size: var(--step--1);
|
||||
color: var(--band-ink-muted);
|
||||
max-width: var(--measure);
|
||||
line-height: var(--leading-loose);
|
||||
}
|
||||
|
||||
/* ── 파트너 ─────────────────────────────────────────────────────── */
|
||||
.section-partners {
|
||||
background: var(--surface-2);
|
||||
}
|
||||
|
||||
.partners {
|
||||
margin-top: var(--space-6);
|
||||
list-style: none;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(min(100%, 190px), 1fr));
|
||||
border-top: 1px solid var(--band-line-strong);
|
||||
}
|
||||
|
||||
.partners li {
|
||||
padding: var(--space-3) var(--space-3) var(--space-3) 0;
|
||||
border-bottom: 1px solid var(--band-line);
|
||||
color: var(--band-ink-muted);
|
||||
font-size: var(--step--1);
|
||||
}
|
||||
|
||||
/* ── 기록 ───────────────────────────────────────────────────────── */
|
||||
.record-list {
|
||||
margin-top: var(--space-6);
|
||||
list-style: none;
|
||||
border-top: 1px solid var(--band-line-strong);
|
||||
}
|
||||
|
||||
.record-list li {
|
||||
display: grid;
|
||||
gap: var(--space-2);
|
||||
padding-block: var(--space-4);
|
||||
border-bottom: 1px solid var(--band-line);
|
||||
}
|
||||
|
||||
@media (min-width: 860px) {
|
||||
.record-list li {
|
||||
grid-template-columns: 7rem 1fr 7rem;
|
||||
gap: var(--space-4);
|
||||
align-items: baseline;
|
||||
}
|
||||
}
|
||||
|
||||
.rec-date {
|
||||
font-size: var(--step--1);
|
||||
color: var(--band-ink-faint);
|
||||
}
|
||||
|
||||
.record-list h3 {
|
||||
font-size: var(--step-1);
|
||||
}
|
||||
|
||||
.record-list div p {
|
||||
margin-top: var(--space-2);
|
||||
color: var(--band-ink-muted);
|
||||
font-size: var(--step--1);
|
||||
line-height: var(--leading-loose);
|
||||
}
|
||||
|
||||
.rec-kind {
|
||||
font-size: var(--step--1);
|
||||
color: var(--band-ink-faint);
|
||||
}
|
||||
|
||||
@media (min-width: 860px) {
|
||||
.rec-kind {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── 채용 ───────────────────────────────────────────────────────── */
|
||||
.jobs {
|
||||
margin-top: var(--space-5);
|
||||
list-style: none;
|
||||
border-top: 1px solid var(--band-line-strong);
|
||||
}
|
||||
|
||||
.jobs li {
|
||||
display: grid;
|
||||
gap: var(--space-1) var(--space-4);
|
||||
padding-block: var(--space-3);
|
||||
border-bottom: 1px solid var(--band-line);
|
||||
}
|
||||
|
||||
@media (min-width: 720px) {
|
||||
.jobs li {
|
||||
grid-template-columns: 14rem 1fr 4rem;
|
||||
align-items: baseline;
|
||||
}
|
||||
}
|
||||
|
||||
.job-name {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.job-hint {
|
||||
font-size: var(--step--1);
|
||||
color: var(--band-ink-muted);
|
||||
line-height: var(--leading-loose);
|
||||
}
|
||||
|
||||
.job-state {
|
||||
font-size: var(--step--1);
|
||||
color: var(--band-ink-faint);
|
||||
}
|
||||
|
||||
@media (min-width: 720px) {
|
||||
.job-state {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.jobs-open {
|
||||
margin-top: var(--space-4);
|
||||
font-size: var(--step--1);
|
||||
color: var(--band-ink-muted);
|
||||
line-height: var(--leading-loose);
|
||||
}
|
||||
|
||||
.jobs-open a {
|
||||
color: var(--band-accent);
|
||||
}
|
||||
|
||||
/* ── 연락 ───────────────────────────────────────────────────────── */
|
||||
.contact-rows {
|
||||
border-top: 1px solid var(--band-line-strong);
|
||||
}
|
||||
|
||||
.contact-rows > div {
|
||||
display: grid;
|
||||
gap: var(--space-1) var(--space-4);
|
||||
padding-block: var(--space-3);
|
||||
border-bottom: 1px solid var(--band-line);
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.contact-rows > div {
|
||||
grid-template-columns: 6rem 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.contact-rows dt {
|
||||
font-size: var(--step--1);
|
||||
color: var(--band-ink-faint);
|
||||
}
|
||||
|
||||
.contact-rows dd {
|
||||
color: var(--band-ink-muted);
|
||||
line-height: var(--leading-loose);
|
||||
}
|
||||
|
||||
.contact-rows a {
|
||||
color: var(--band-accent);
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
margin-top: var(--space-5);
|
||||
padding: var(--space-3) var(--space-5);
|
||||
background: var(--band-accent);
|
||||
color: var(--band-accent-ink);
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
transition: background-color var(--dur-quick) var(--ease);
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background: var(--band-accent-hover);
|
||||
}
|
||||
|
||||
/* ── 푸터 ───────────────────────────────────────────────────────── */
|
||||
.foot-inner {
|
||||
display: grid;
|
||||
gap: var(--space-2);
|
||||
}
|
||||
|
||||
.foot-name {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.foot-line {
|
||||
color: var(--band-ink-muted);
|
||||
font-size: var(--step--1);
|
||||
}
|
||||
|
||||
.foot-fine {
|
||||
margin-top: var(--space-4);
|
||||
padding-top: var(--space-3);
|
||||
border-top: 1px solid var(--band-line);
|
||||
font-size: var(--step--1);
|
||||
color: var(--band-ink-faint);
|
||||
}
|
||||
|
||||
/* ── 좁은 화면 ──────────────────────────────────────────────────── */
|
||||
@media (max-width: 640px) {
|
||||
.head-inner {
|
||||
flex-wrap: wrap;
|
||||
padding-block: var(--space-2);
|
||||
row-gap: var(--space-2);
|
||||
}
|
||||
|
||||
.nav {
|
||||
order: 3;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-2);
|
||||
border-top: 1px solid var(--line);
|
||||
padding-top: var(--space-2);
|
||||
}
|
||||
|
||||
.head-meta {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.counts {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
/* ── 모션을 줄이는 설정 ─────────────────────────────────────────── */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
html {
|
||||
scroll-behavior: auto;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ── 인쇄 — 현장 선택기는 종이에서 의미가 없으므로 네 패널을 모두 편다 ── */
|
||||
@media print {
|
||||
.site-head,
|
||||
.skip-link,
|
||||
.btn {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.band {
|
||||
background: #fff;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.field-panel {
|
||||
display: block !important;
|
||||
break-inside: avoid;
|
||||
}
|
||||
|
||||
.field-tabs {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
117
apps/site/public/work/twentyoz-corp/styles/tokens.css
Normal file
117
apps/site/public/work/twentyoz-corp/styles/tokens.css
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/* ==========================================================================
|
||||
트웬티온스 (TWENTYOZ) — 회사 홈페이지 리디자인 · 디자인 토큰 SSOT
|
||||
|
||||
컨셉 : 네 개의 현장 — 회사 소개가 아니라, 같은 기술이 서로 다른 현장에서
|
||||
무엇을 하고 있는지의 목록이 이 사이트의 본체다
|
||||
프리셋: field-record (신규 정의. swiss-minimal 을 뼈대로 삼되 본문을 키웠다)
|
||||
강조색: 신호 적색 1색. 라이트/다크는 규칙으로 정의된 한 쌍이므로 1종으로 센다
|
||||
|
||||
── 0단계 감사 · 현행 twentyoz.kr 실측 (2026-08-24, 1249px computed style)
|
||||
유지할 자산
|
||||
· radius 0px 742회 — 형태 어휘가 이미 통일돼 있다. 그대로 가져간다
|
||||
· 무채색 기조와 모노스페이스(JetBrains Mono 356회) — 정밀함의 어휘는 맞다
|
||||
· 실제 프로젝트 49건 · 파트너 19곳 · 제품 4종의 기술 스택 표기
|
||||
고쳐야 할 것
|
||||
· 대비 실패 **172개 요소** — rgb(102,102,102) 가 배경 rgb(2,2,2) 위에서 3.61:1,
|
||||
그것도 9~11px 로 284곳에 쓰였다. WCAG AA 미달이고 읽기 자체가 어렵다
|
||||
· font-family 가 Inter 뿐이라 **한글 폰트가 지정돼 있지 않다**.
|
||||
한국 회사의 한국어 사이트에서 한글이 시스템 기본값으로 떨어진다
|
||||
· h1 174.86px 에 letter-spacing −10.49px = **−0.06em**. 한글 상한(−0.02em)의 세 배다
|
||||
· 배경 #020202 — 순흑에 가깝다
|
||||
· 'Digital Genetics' 은유가 전면에 있다(CULTIVATING · DROPS · Sativa/Indica ·
|
||||
Germination · Wholesale Desk · ACQUIRE GENETICS · Open Specimens).
|
||||
SK하이닉스·LG디스플레이·한화솔루션·GS칼텍스에 산업용 IoT 를 파는 회사의
|
||||
어휘로는 사업을 가린다. 은유를 걷어내고 한 일을 앞에 둔다
|
||||
|
||||
── 레퍼런스 실측 (2026-08-24, 1440px)
|
||||
R1 구조 · samsara.com (커넥티드 오퍼레이션 / 산업 IoT — 같은 업종)
|
||||
배경 #FFFFFF · FK Grotesk + FK Grotesk Mono 2패밀리
|
||||
h1 72px/700 · 본문 16px(404회) · 최대 80px ÷ 본문 = 5.0배
|
||||
radius 0px 2399회 지배 · 강조색 #FEAE0F 이 버튼 1곳
|
||||
컨테이너 1425 전폭 ↔ 1345 ↔ 427 칼럼 · 섹션 13
|
||||
→ 가져온 원리: 섹션 제목이 '무엇을 증명하는가'를 직접 말한다
|
||||
(Proven where it counts / A track record / Proudly rated #1).
|
||||
B2B 는 주장이 아니라 기록으로 설득한다
|
||||
→ 안 가져온 것: 전체 대문자 h1 과 대문자 eyebrow 5종(슬롭 지문 2위),
|
||||
순백·순흑, 섹션 13개, 앰버 pill 버튼
|
||||
|
||||
R2 톤 · lars-mueller-publishers.com (출판사 — 다른 업종)
|
||||
텍스트 #414141 (순흑 아님) · NB Akademie Std 한 패밀리의 두 웨이트
|
||||
h1 34px/500 · **본문 20px(190회)** · line-height 30px = 1.5
|
||||
최대 ÷ 본문 = 1.7배 · radius 0px 1709회 지배 · 컨테이너 1240px
|
||||
→ 가져온 원리: **본문을 크게 쓰고 제목을 작게 둔다.** 위계를 크기 하나로
|
||||
만들지 않고 여백과 순서로도 만든다. 한 패밀리의 두 웨이트로 절제한다
|
||||
→ 안 가져온 것: 강조색 #542BFF(보라 계열 — 슬롭 지문),
|
||||
최대÷본문 1.7배(평평한 스케일은 안티패턴)
|
||||
|
||||
두 레퍼런스의 합성: 본문은 R2 쪽으로 키우고(17px), 최대÷본문은 R1 쪽으로
|
||||
벌린다(4.0배). 한쪽만 따르면 평평하거나 본문이 작아진다.
|
||||
========================================================================== */
|
||||
|
||||
:root {
|
||||
/* ── 타이포그래피 — 5단계 + 스케일 밖 디스플레이 1개 ── */
|
||||
--step--1: 0.8125rem; /* 13px — 표 머리·메타 */
|
||||
--step-0: 1.0625rem; /* 17px — 본문. R2 의 큰 본문을 한글에 맞춰 옮겼다 */
|
||||
--step-1: 1.25rem; /* 20px — 리드 */
|
||||
--step-2: clamp(1.375rem, 1.15rem + 1.1vw, 1.9375rem); /* 22 → 31px */
|
||||
--step-3: clamp(1.75rem, 1.25rem + 2.5vw, 2.875rem); /* 28 → 46px */
|
||||
--display: clamp(2.25rem, 1.3rem + 4.6vw, 4.25rem); /* 36 → 68px */
|
||||
/* 최대 ÷ 본문 = 68 ÷ 17 = 4.0배 */
|
||||
|
||||
--leading-tight: 1.2;
|
||||
--leading-normal: 1.7;
|
||||
--leading-loose: 1.85;
|
||||
--measure: 33em;
|
||||
|
||||
--font-body: Pretendard, "Pretendard Variable", -apple-system, system-ui, sans-serif;
|
||||
--font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, monospace;
|
||||
|
||||
/* ── 색 · 종이(라이트) ── */
|
||||
--surface: #fafaf8;
|
||||
--surface-2: #f0f0ec;
|
||||
--surface-3: #e5e5e0;
|
||||
--line: #dcdcd6;
|
||||
--line-strong: #b9b9b2;
|
||||
--ink: #111214; /* 17.9:1 */
|
||||
--ink-muted: #54585c; /* 6.97:1 */
|
||||
--ink-faint: #686d72; /* 5.03:1 */
|
||||
--accent: #c4341f; /* 5.21:1 · 흰 글자 얹으면 5.44:1 */
|
||||
--accent-hover: #9e2817;
|
||||
--accent-ink: #ffffff;
|
||||
--accent-wash: #f6e7e3;
|
||||
|
||||
/* ── 색 · 잉크(다크 반전 밴드) — 위 값들의 규칙적 반전 ── */
|
||||
--dark-surface: #111214;
|
||||
--dark-surface-2: #191b1e;
|
||||
--dark-surface-3: #212428;
|
||||
--dark-line: #2c3034;
|
||||
--dark-line-strong: #40454a;
|
||||
--dark-ink: #f2f2f0; /* 16.7:1 */
|
||||
--dark-ink-muted: #a2a6a9; /* 7.67:1 */
|
||||
--dark-ink-faint: #84898d; /* 5.31:1 */
|
||||
--dark-accent: #e8563c; /* 5.17:1 */
|
||||
--dark-accent-hover: #f2705a;
|
||||
--dark-accent-ink: #160906;
|
||||
--dark-accent-wash: #33170f;
|
||||
|
||||
/* ── 형태 — 현행 사이트가 radius 0 으로 통일돼 있다. 유지할 자산이다 ── */
|
||||
--radius: 0;
|
||||
|
||||
/* ── 간격 — 저장소 SSOT 표준 ── */
|
||||
--space-1: 0.25rem;
|
||||
--space-2: 0.5rem;
|
||||
--space-3: 1rem;
|
||||
--space-4: 1.5rem;
|
||||
--space-5: 2.5rem;
|
||||
--space-6: 4rem;
|
||||
--space-7: 6rem;
|
||||
--space-8: clamp(4.5rem, 3rem + 6vw, 9rem);
|
||||
|
||||
--container: 1120px;
|
||||
--pad-inline: clamp(1.25rem, 1rem + 2.5vw, 4rem);
|
||||
|
||||
/* ── 모션 ── */
|
||||
--dur-quick: 150ms;
|
||||
--dur-normal: 380ms;
|
||||
--ease: cubic-bezier(0.2, 0, 0, 1);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue