feat: strengthen design skill and refresh all showcases
Some checks failed
ci / build (push) Has been cancelled

This commit is contained in:
Yun Chan 2026-09-12 18:16:33 +09:00
parent 69e5cc1efd
commit e09d4efb1c
257 changed files with 8196 additions and 2374 deletions

View file

@ -76,6 +76,7 @@ h3 { font-size: var(--step-0); font-weight: 500; }
display: grid;
grid-template-columns: 244px minmax(0, 1fr);
min-height: 100dvh;
min-width: 0;
background: var(--background);
}
@ -149,7 +150,7 @@ h3 { font-size: var(--step-0); font-weight: 500; }
.topbar .brand { display: none; } /* 브랜드는 사이드바에 있다 — 모바일에서만 탑바가 이어받는다 */
.crumb { display: flex; align-items: center; gap: var(--space-2); font-size: var(--step-0); color: var(--muted-foreground); }
.crumb strong { color: var(--foreground); font-weight: 600; }
.topbar-right { display: flex; align-items: center; gap: var(--space-3); }
.topbar-right { display: flex; min-width: 0; align-items: center; gap: var(--space-3); }
.term-badge {
display: inline-flex; align-items: center;
font-size: var(--step-1); font-weight: 500;
@ -170,11 +171,11 @@ h3 { font-size: var(--step-0); font-weight: 500; }
/* ── 본문 ── */
.main { min-width: 0; display: flex; flex-direction: column; }
.view { display: none; }
.view { display: none; min-width: 0; }
.view.is-on { display: block; }
.view:focus { outline: none; }
.view-sub { color: var(--muted-foreground); font-size: var(--step-0); margin-top: 4px; max-width: 46em; }
.view-sub { color: var(--muted-foreground); font-size: var(--record-meta-size); margin-top: 4px; max-width: 46em; }
.view-head {
display: flex; justify-content: space-between; align-items: flex-start;
gap: var(--space-4);
@ -193,23 +194,23 @@ h3 { font-size: var(--step-0); font-weight: 500; }
.panel {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-sm);
border-radius: var(--record-radius);
box-shadow: none;
padding: var(--space-5);
min-width: 0;
}
.panel h2 { margin-bottom: var(--space-4); font-size: var(--step-2); }
.panel-note { font-size: var(--step-1); color: var(--faint); margin-top: var(--space-3); }
.panel-note { font-size: var(--record-meta-size); color: var(--faint); margin-top: var(--space-3); }
/* 통계 카드 */
.headline { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-4); }
.headline { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0; background: var(--card); border: 1px solid var(--record-rule); border-radius: var(--record-radius); box-shadow: none; font-variant-numeric: tabular-nums; }
.headline > div {
background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-lg);
box-shadow: var(--shadow-sm); padding: var(--space-4) var(--space-5);
min-width: 0; padding: var(--space-4) var(--space-5) var(--space-5); background: transparent; border: 0; border-right: 1px solid var(--record-rule); border-radius: 0; box-shadow: none;
}
.headline dt { font-size: var(--step-0); color: var(--muted-foreground); font-weight: 500; }
.headline > div:last-child { border-right: 0; }
.headline dt { font-size: var(--record-meta-size); color: var(--muted-foreground); font-weight: 500; }
.headline dd { font-size: var(--step-3); font-weight: 600; letter-spacing: -0.03em; line-height: 1.2; font-variant-numeric: tabular-nums; margin-top: 4px; }
.headline .stat-sub { font-size: var(--step--1); color: var(--faint); margin: 6px 0 0; margin-inline-start: 0; font-variant-numeric: tabular-nums; }
.headline .stat-sub { font-size: var(--record-meta-size); color: var(--faint); margin: 6px 0 0; margin-inline-start: 0; font-variant-numeric: tabular-nums; }
.dash-grid {
display: grid;
@ -221,15 +222,19 @@ h3 { font-size: var(--step-0); font-weight: 500; }
.week-panel { grid-row: span 2; }
/* ── 표 ── */
.table-wrap { overflow-x: auto; overflow-y: hidden; }
table { width: 100%; border-collapse: collapse; }
.table-wrap { max-width: 100%; overflow-x: auto; overflow-y: hidden; overscroll-behavior-inline: contain; scrollbar-gutter: stable both-edges; }
table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.table-wrap > table { min-width: 600px; }
#stu-table, #att-table, #as-table { min-width: 760px; }
#report-table { min-width: 680px; }
table th, table td { overflow-wrap: normal; word-break: keep-all; }
thead th {
text-align: left; font-weight: 500; font-size: var(--step-1);
text-align: left; font-weight: 600; font-size: var(--record-meta-size);
color: var(--muted-foreground); padding: 0 var(--space-3) var(--space-3);
border-bottom: 1px solid var(--border);
height: 36px; white-space: nowrap;
}
tbody td, tbody th { padding: var(--space-3); border-bottom: 1px solid var(--border); vertical-align: middle; text-align: left; }
tbody td, tbody th { padding: var(--space-3); border-bottom: 1px solid var(--border); vertical-align: middle; text-align: left; font-size: var(--record-body-size); line-height: 1.55; }
tbody th { font-weight: 500; }
tbody tr:last-child td, tbody tr:last-child th { border-bottom: 0; }
tbody tr { transition: background-color 80ms ease; }
@ -239,7 +244,7 @@ tbody tr:hover { background: var(--muted); }
.row-open {
appearance: none; border: 0; background: none; padding: 0;
font: inherit; font-weight: 500; color: var(--foreground);
cursor: pointer; text-align: left;
min-height: 24px; cursor: pointer; text-align: left;
transition: color 80ms ease;
}
.row-open:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
@ -285,8 +290,8 @@ tbody tr:hover { background: var(--muted); }
.wk-sum thead th { padding: 8px var(--space-2); }
.wk-sum tbody td { padding: 7px var(--space-2); }
.wk-sum tfoot td { padding: 8px var(--space-2); border-top: 1px solid var(--border-strong); font-weight: 600; }
.wk-sum td:first-child, .wk-sum th:first-child { padding-left: 0; white-space: nowrap; }
.wk-sum td:last-child, .wk-sum th:last-child { padding-right: 0; }
.wk-sum td:first-child, .wk-sum th:first-child { padding-left: var(--space-2); white-space: nowrap; }
.wk-sum td:last-child, .wk-sum th:last-child { padding-right: var(--space-2); }
.key { display: inline-flex; align-items: center; gap: 6px; }
.key i { width: 8px; height: 8px; display: inline-block; border-radius: var(--radius-xs); }
.k-att { background: var(--border-strong); }
@ -373,7 +378,7 @@ tbody tr:hover { background: var(--muted); }
background: none; color: var(--muted-foreground);
border: 1px solid var(--border-strong); border-radius: var(--radius);
height: 28px; padding: 0 10px;
transition: all 100ms ease;
transition: background-color 100ms ease, border-color 100ms ease, color 100ms ease;
white-space: nowrap;
}
.give-btn:hover { border-color: var(--foreground); color: var(--foreground); }
@ -387,7 +392,7 @@ tbody tr:hover { background: var(--muted); }
align-items: start;
}
.cal { table-layout: fixed; }
.cal th { text-align: center; font-size: var(--step-1); height: 32px; padding: 0; }
.cal th { text-align: center; font-size: var(--step-1); height: 32px; padding-inline: var(--space-2); }
.cal-day {
height: 76px; padding: var(--space-1);
border: 1px solid var(--border);
@ -454,6 +459,8 @@ tbody tr:hover { background: var(--muted); }
/* ── 모달 ── */
.modal {
position: fixed;
inset: 0;
margin: auto;
width: min(94vw, 860px);
max-height: min(86dvh, 760px);
@ -463,8 +470,11 @@ tbody tr:hover { background: var(--muted); }
background: var(--card);
color: var(--foreground);
overflow: hidden;
overscroll-behavior: contain;
box-shadow: var(--shadow-xl);
}
html:has(dialog.modal[open]) { overflow: hidden; }
.modal::backdrop { background: var(--backdrop-dim); backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); }
@media (prefers-reduced-motion: no-preference) {
.modal[open] { animation: modal-in 200ms cubic-bezier(0.16, 1, 0.3, 1) both; }
@ -613,6 +623,8 @@ tbody tr:hover { background: var(--muted); }
padding-top: max(0px, var(--safe-top));
}
.topbar .brand { display: flex; flex: none; padding: 0; }
.topbar-right { flex-wrap: wrap; justify-content: flex-end; gap: var(--space-1); }
.topbar-right > * { min-width: 0; }
.crumb { display: none; }
.main { padding-bottom: calc(72px + var(--safe-bottom)); } /* 바텀 내비 + 홈 인디케이터 확보 */
.dash-grid, .cal-layout, .counsel-grid { grid-template-columns: minmax(0, 1fr); }
@ -620,7 +632,7 @@ tbody tr:hover { background: var(--muted); }
.dist-body { grid-template-columns: minmax(0, 1fr); }
.view-head { flex-direction: column; align-items: flex-start; gap: var(--space-2); padding: var(--space-5) var(--space-4) var(--space-4); }
.view > *:not(.view-head) { margin-inline: var(--space-4); }
.headline { gap: var(--space-2); }
.headline { gap: 0; }
.term-badge { display: none; }
.cal-day { height: 56px; }
}
@ -634,24 +646,26 @@ tbody tr:hover { background: var(--muted); }
.mcover-mark { font-size: 5rem; }
.msheet { padding: var(--space-4); min-height: 0; }
.headline { grid-template-columns: minmax(0, 1fr); }
.headline > div { border-right: 0; border-bottom: 1px solid var(--record-rule); }
.headline > div:last-child { border-bottom: 0; }
}
/* ── 알림 센터 ── */
.bell-wrap { position: relative; }
.bell {
position: relative; width: 32px; height: 32px;
position: relative; width: 44px; height: 44px;
display: inline-flex; align-items: center; justify-content: center;
border-radius: var(--radius); border: none; background: none; cursor: pointer;
color: var(--muted-foreground); transition: background-color 80ms ease, color 80ms ease;
}
.bell:hover, .bell.is-open { background: var(--muted-2); color: var(--foreground); }
.bell-dot {
position: absolute; top: 4px; right: 4px;
position: absolute; top: 8px; right: 8px;
width: 8px; height: 8px; border-radius: var(--radius-pill);
background: var(--danger); border: 2px solid var(--background);
}
.bell-menu {
display: none; position: absolute; top: 40px; right: 0; z-index: 40;
display: none; position: absolute; top: 52px; right: 0; z-index: 40;
width: min(340px, calc(100vw - 32px));
background: var(--card); border: 1px solid var(--border);
border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); overflow: hidden;
@ -679,6 +693,21 @@ tbody tr:hover { background: var(--muted); }
.ntc.is-read p { color: var(--muted-foreground); }
.ntc time { display: block; font-size: var(--step--1); color: var(--faint); margin-top: 2px; }
/* 좁거나 낮은 화면에서는 종 모서리가 아니라 뷰포트가 알림판의 기준이다.
상대 위치를 유지하면 340px 패널이 좌측으로 밀리고 긴 목록이 하단 내비 아래로 사라진다. */
@media (max-width: 680px) {
.bell-menu {
position: fixed;
top: calc(56px + var(--safe-top) + var(--space-2));
right: max(var(--space-3), var(--safe-right));
bottom: calc(72px + var(--safe-bottom) + var(--space-2));
left: max(var(--space-3), var(--safe-left));
width: auto;
max-height: none;
overflow-y: auto;
}
}
/* ── 태그 칩 (유형·사유) ── */
.tag {
display: inline-flex; align-items: center; white-space: nowrap;
@ -920,15 +949,15 @@ kbd {
border-top: 1px solid var(--border);
padding: 6px max(var(--space-2), var(--safe-left)) calc(6px + var(--safe-bottom)) max(var(--space-2), var(--safe-right));
}
@media (max-width: 900px) { .bottom-nav { display: grid; grid-auto-flow: column; } }
@media (max-width: 900px) { .bottom-nav { display: grid; min-width: 0; grid-template-columns: repeat(5, minmax(0, 1fr)); grid-auto-flow: row; } }
.bnav-item {
appearance: none; background: none; border: 0; cursor: pointer; font: inherit;
display: grid; justify-items: center; align-content: center; gap: 3px;
min-height: 52px; min-width: 48px; padding: 4px 2px;
min-height: 52px; min-width: 0; padding: 4px 2px;
border-radius: var(--radius);
color: var(--muted-foreground);
}
.bnav-item span { font-size: var(--step--2); font-weight: 500; }
.bnav-item span { max-width: 100%; font-size: var(--step--2); font-weight: 500; overflow-wrap: anywhere; }
.bnav-item.is-current { color: var(--accent-ink); font-weight: 600; }
.bnav-item.is-current svg { color: var(--accent); }

View file

@ -90,6 +90,11 @@
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
--record-radius: 8px;
--record-rule: var(--border);
--record-body-size: 0.9375rem;
--record-meta-size: 0.8125rem;
/* 안전 영역 — viewport-fit=cover 선언 후에만 0이 아닌 값이 온다(WebKit 공식·MDN env()) */
--safe-top: env(safe-area-inset-top, 0px);
--safe-bottom: env(safe-area-inset-bottom, 0px);