diff --git a/app/static/app.css b/app/static/app.css index ebe710d..a6180ef 100644 --- a/app/static/app.css +++ b/app/static/app.css @@ -8,6 +8,13 @@ font-display: swap; src: url("/static/fonts/PretendardVariable.woff2") format("woff2-variations"); } +@font-face { + font-family: "JetBrains Mono"; + font-weight: 100 800; + font-style: normal; + font-display: swap; + src: url("/static/fonts/JetBrainsMono.woff2") format("woff2-variations"); +} :root { /* palette (design-ref §2) */ @@ -25,12 +32,13 @@ --accent-hover: #1b64da; --accent-deep: #1e40af; --accent-soft: #e8f3ff; - /* 밝은 상태색은 옅은 배경 위 대비 위해 텍스트용으로 약간 어둡게 */ --success-text: #00a37a; --warning-text: #c5700a; --danger: #f04452; --radius-card: 12px; + /* 영문/숫자(저장소명·버전·패키지수·시각)는 모노 — 도구다운 가독성 (design-ref §3) */ + --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace; /* Pico 매핑 */ --pico-font-family-sans-serif: "Pretendard Variable", -apple-system, @@ -38,7 +46,7 @@ system-ui, sans-serif; --pico-font-family: var(--pico-font-family-sans-serif); --pico-line-height: 1.55; - --pico-border-radius: 7px; /* 버튼/인풋 (design-ref §4) */ + --pico-border-radius: 7px; --pico-background-color: var(--bg-alt); --pico-color: var(--text-secondary); --pico-h1-color: var(--text); @@ -58,11 +66,12 @@ body { background: var(--bg-alt); color: var(--text-secondary); + -webkit-font-smoothing: antialiased; } main.container { max-width: 1040px; - padding-block: 32px; + padding-block: 40px; } h1, @@ -70,32 +79,37 @@ h2, h3 { color: var(--text); font-weight: 700; - letter-spacing: -0.01em; + letter-spacing: -0.02em; } h2 { - font-size: 20px; + font-size: 22px; margin: 0; } section { - margin-bottom: 40px; + margin-bottom: 44px; } -/* 상단 내비 (design-ref §4 web top nav: white, 1px bottom border) */ +.mono { + font-family: var(--font-mono); + font-feature-settings: "tnum" 1; +} + +/* 상단 내비 */ .app-nav { background: var(--bg); border-bottom: 1px solid var(--border); } .app-nav .container { max-width: 1040px; - padding-block: 16px; + padding-block: 18px; } .app-nav .brand { margin: 0; - font-size: 17px; + font-size: 18px; font-weight: 700; color: var(--text); - letter-spacing: -0.01em; + letter-spacing: -0.02em; } .app-nav .brand .accent { color: var(--accent); @@ -105,7 +119,46 @@ section { display: flex; align-items: center; justify-content: space-between; - margin-bottom: 16px; + margin-bottom: 18px; +} + +/* 버튼 — Toss: radius 7, weight 600, 누름 피드백 scale(0.98) (design-ref §4·§6) */ +button, +[role="button"] { + font-weight: 600; + transition: + background-color 0.12s ease, + border-color 0.12s ease, + transform 0.096s ease; +} +button:active, +[role="button"]:active { + transform: scale(0.98); +} +button.secondary, +[role="button"].secondary, +a.secondary { + --pico-background-color: var(--surface-2); + --pico-border-color: var(--surface-2); + --pico-color: var(--accent-hover); + font-weight: 600; +} +button.danger, +[role="button"].danger { + --pico-background-color: var(--danger); + --pico-border-color: var(--danger); + --pico-color: #ffffff; +} +button:disabled, +[role="button"]:disabled { + opacity: 0.45; +} +/* 표 안 액션 버튼: 컴팩트 */ +.btn-sm { + padding: 7px 14px; + font-size: 13px; + margin: 0; + width: auto; } /* 요약 카드 */ @@ -119,24 +172,36 @@ section { background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-card); - padding: 20px; + padding: 20px 22px; box-shadow: 0 1px 3px rgba(25, 31, 40, 0.04); + transition: border-color 0.12s ease; +} +.summary .card:hover { + border-color: var(--border-strong); } .summary .value { - font-size: 32px; - font-weight: 700; + font-family: var(--font-mono); + font-size: 34px; + font-weight: 600; color: var(--text); line-height: 1.1; - font-variant-numeric: tabular-nums; /* 숫자 정렬 (design-ref §3) */ + letter-spacing: -0.02em; + font-feature-settings: "tnum" 1; +} +.summary .value.is-accent { + color: var(--accent); +} +.summary .value.is-success { + color: var(--success-text); } .summary .label { - margin-top: 6px; + margin-top: 8px; font-size: 13px; font-weight: 500; color: var(--text-muted); } -/* 저장소 표 (카드로 감싸기, hairline 행) */ +/* 표 (카드로 감싸기, hairline 행, hover) */ .table-card { background: var(--bg); border: 1px solid var(--border); @@ -152,29 +217,50 @@ section { font-weight: 600; color: var(--text-dim); text-transform: uppercase; - letter-spacing: 0.03em; + letter-spacing: 0.04em; + background: var(--bg-alt); border-bottom: 1px solid var(--border); + padding-block: 14px; } .table-card tbody td { + height: 56px; border-bottom: 1px solid var(--border); - padding-block: 16px; + padding-block: 12px; vertical-align: middle; } .table-card tbody tr:last-child td { border-bottom: none; } -.repo-name { +.table-card tbody tr:hover { + background: var(--bg-alt); +} +.repo-name a { + font-family: var(--font-mono); font-weight: 600; color: var(--text); + text-decoration: none; } -.num { - font-variant-numeric: tabular-nums; +.repo-name a:hover { + color: var(--accent); +} +/* 숫자/버전/시각: 모노 + tabular */ +.num, +.mono { + font-family: var(--font-mono); + font-feature-settings: "tnum" 1; } td.num, th.num { text-align: right; } +/* 액션 셀: swap(버튼→진행률) 시 행 높이 안 흔들리게 고정 */ +.row-action { + display: flex; + align-items: center; + min-height: 34px; +} + /* 검증 배지 칩 (dot + 라벨, 이모지 없음) */ .badge { display: inline-flex; @@ -219,6 +305,7 @@ th.num { } .verify-detail small { color: var(--text-muted); + font-family: var(--font-mono); } /* 패키지 증감 */ @@ -229,35 +316,12 @@ th.num { color: var(--danger); } -/* 보조 버튼: 틴티드 블루 (design-ref §4 two-step blue) */ -button.secondary, -[role="button"].secondary, -a.secondary { - --pico-background-color: var(--surface-2); - --pico-border-color: var(--surface-2); - --pico-color: var(--accent-hover); - font-weight: 500; -} -button:disabled, -[role="button"]:disabled { - opacity: 0.45; -} - -/* 위험 버튼: 배포 확정 등 확인 모달에서만 (design-ref §4) */ -button.danger, -[role="button"].danger { - --pico-background-color: var(--danger); - --pico-border-color: var(--danger); - --pico-color: #ffffff; - font-weight: 500; -} - /* 동기화 진행률 바 */ .sync-progress { display: flex; flex-direction: column; - gap: 4px; - min-width: 160px; + gap: 5px; + min-width: 150px; } .sync-progress progress { margin: 0; @@ -265,27 +329,34 @@ button.danger, } .sync-progress small { color: var(--text-muted); + font-family: var(--font-mono); + font-size: 12px; } -/* 연결 상태 표시 (dot + 텍스트) */ +/* 연결 상태 칩 (dot + 텍스트) */ .status-line { display: inline-flex; align-items: center; gap: 8px; + padding: 6px 12px; + border-radius: 999px; font-weight: 500; + background: var(--surface); } .status-line::before { content: ""; - width: 9px; - height: 9px; + width: 8px; + height: 8px; border-radius: 50%; background: currentColor; } .status-ok { color: var(--success-text); + background: rgba(0, 200, 150, 0.1); } .status-bad { color: var(--danger); + background: rgba(240, 68, 82, 0.1); } .status-loading { color: var(--text-muted); diff --git a/app/static/favicon.svg b/app/static/favicon.svg new file mode 100644 index 0000000..42dbde1 --- /dev/null +++ b/app/static/favicon.svg @@ -0,0 +1,8 @@ + diff --git a/app/static/fonts/JetBrainsMono.woff2 b/app/static/fonts/JetBrainsMono.woff2 new file mode 100644 index 0000000..cd5102a Binary files /dev/null and b/app/static/fonts/JetBrainsMono.woff2 differ diff --git a/app/templates/base.html b/app/templates/base.html index 92fd305..6e0cefe 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -4,6 +4,7 @@