diff --git a/php/assets/app.css b/php/assets/app.css index c8cb82c..edc00e9 100644 --- a/php/assets/app.css +++ b/php/assets/app.css @@ -41,10 +41,13 @@ --mono: ui-monospace,SFMono-Regular,Consolas,"D2Coding",monospace; --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 20px; --sp-6: 24px; --sp-8: 32px; - --r-sm: 6px; --r: 10px; --r-lg: 16px; --r-pill: 999px; - --shadow: 0 1px 2px rgba(0,0,0,.4); - --shadow-lg: 0 12px 32px rgba(0,0,0,.45); + --r-sm: 8px; --r: 12px; --r-lg: 18px; --r-pill: 999px; + /* 소프트·확산형 그림자(참고 대시보드처럼 카드가 표면 위에 살짝 떠 보이게) */ + --shadow: 0 2px 10px rgba(0,0,0,.30); + --shadow-lg: 0 16px 40px rgba(0,0,0,.48); --ring: 0 0 0 3px rgba(108,123,255,.45); + /* 장식 골드 액센트(참고 2.png 인디고+골드) — 상태색 --warn 과 별개의 장식 역할 */ + --accent-gold: #ffc24b; } * { box-sizing: border-box; margin: 0; padding: 0; } @@ -93,8 +96,7 @@ header h1::before { content: ""; width: 10px; height: 10px; border-radius: 50%; .panel { padding: var(--sp-5); } .chart-panel { padding: var(--sp-5); margin-bottom: var(--sp-6); } -.card { padding: var(--sp-5) var(--sp-5) var(--sp-6); position: relative; overflow: hidden; } -.card::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 3px; background: linear-gradient(90deg, var(--primary), var(--chart-hum)); opacity: .9; } +.card { padding: var(--sp-5) var(--sp-5) var(--sp-6); position: relative; } .card > div:first-child { color: var(--ink-2); font-size: .78rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; } .card span { color: var(--ink-2); font-size: .8125rem; } .card .val { font-size: clamp(2.4rem, 4.2vw, 3.4rem); font-weight: 800; line-height: 1.02; margin-top: var(--sp-2); color: var(--ink); letter-spacing: -.02em; } @@ -103,9 +105,10 @@ header h1::before { content: ""; width: 10px; height: 10px; border-radius: 50%; .card .val.ok-color { color: var(--normal-ink); } .card .val.err-color { color: var(--leak-ink); } .card .val.warn-color { color: var(--warn-ink); } -.card:has(.val.ok-color)::before { background: var(--normal); } -.card:has(.val.err-color)::before { background: var(--leak); } -.card:has(.val.warn-color)::before { background: var(--warn); } +/* 상태색은 .val 색상으로 인코딩(상단 스트립 제거 — 참고 대시보드 스타일의 평평한 카드) */ +.card.ok, .card:has(.val.ok-color) { border-color: rgba(53,214,160,.32); } +.card.err, .card:has(.val.err-color) { border-color: rgba(255,84,112,.34); } +.card.warn, .card:has(.val.warn-color) { border-color: rgba(255,178,62,.32); } .card .val.ok-color::before, .card .val.err-color::before, .card .val.warn-color::before { content: none; } .status-hero { border-radius: var(--r-lg); padding: var(--sp-6); margin-bottom: var(--sp-5); display: grid; grid-template-columns: minmax(0,1fr) auto; gap: var(--sp-4); align-items: center; color: var(--ink); background: linear-gradient(180deg, rgba(53,214,160,.08), transparent 70%), var(--surface); border: 1px solid var(--line); position: relative; overflow: hidden; } @@ -536,20 +539,20 @@ tbody tr:hover td { background: var(--surface-2); } margin-bottom: var(--sp-2); } .kpi { - display: flex; flex-direction: column; justify-content: center; gap: 2px; + display: flex; flex-direction: column; justify-content: center; gap: 6px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); - box-shadow: var(--shadow); padding: var(--sp-3) var(--sp-4); min-height: 76px; - text-decoration: none; color: var(--ink); position: relative; overflow: hidden; + box-shadow: var(--shadow); padding: var(--sp-4) var(--sp-5); min-height: 104px; + text-decoration: none; color: var(--ink); transition: border-color .12s ease, transform .12s ease; } -.kpi::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 3px; background: var(--primary); } -.kpi:hover { border-color: var(--primary); } -.kpi .kpi-lbl { color: var(--ink-2); font-size: .72rem; font-weight: 600; letter-spacing: .03em; text-transform: uppercase; } -.kpi .kpi-val { font-size: clamp(1.3rem, 2.2vw, 1.7rem); font-weight: 800; line-height: 1.1; letter-spacing: -.02em; font-variant-numeric: tabular-nums; } +.kpi:hover { border-color: var(--primary); transform: translateY(-2px); } +/* 상태 3중 인코딩: 라벨 앞 상태 dot(도형+색) + 값 색 + 텍스트 — 상단 스트립 없이 */ +.kpi .kpi-lbl { display: flex; align-items: center; gap: 7px; color: var(--ink-2); font-size: .72rem; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; } +.kpi .kpi-lbl::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--normal); flex: none; } +.kpi .kpi-val { font-size: clamp(1.6rem, 2.8vw, 2.15rem); font-weight: 800; line-height: 1.05; letter-spacing: -.025em; font-variant-numeric: tabular-nums; } .kpi .kpi-sub { color: var(--ink-3); font-size: .72rem; font-variant-numeric: tabular-nums; } -.kpi.ok::before { background: var(--normal); } -.kpi.warn::before { background: var(--warn); } -.kpi.err::before { background: var(--leak); } -.kpi.ok .kpi-val { color: var(--normal-ink); } +.kpi.warn .kpi-lbl::before { background: var(--warn); } +.kpi.err .kpi-lbl::before { background: var(--leak); } +.kpi.ok .kpi-val { color: var(--ink); } .kpi.warn .kpi-val { color: var(--warn-ink); } .kpi.err .kpi-val { color: var(--leak-ink); }