vignette/docs/mockups/admin.html
Yun Chan d5b86c5f89 feat(docs): 전체 페이지 레이아웃 시안 추가
- login/learner-home/session-review/professor/admin/settings
- session-v2(밝은 에디토리얼 톤으로 재제작, 기존 어두운 stage 대체)
- 전부 동일 디자인 토큰(세이지틸+테라코타), 윤찬 철칙 준수
2026-06-25 21:27:24 +09:00

563 lines
32 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vignette — 관리자 콘솔</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/variable/pretendardvariable.min.css">
<style>
/* =====================================================================
Vignette — 관리자(Admin) 콘솔 와이어
토큰: DESIGN_CONCEPT.md §3 그대로. 역할 accent = 슬레이트(§6.2 admin).
철칙: border-left 0 · 이모지 0(아이콘=inline SVG) · 카드덤프 0 ·
순흑/순백 금지 · 강조는 weight/tint/kicker/dot로 · 넉넉한 여백.
===================================================================== */
:root{
/* 중성 베이스 */
--paper:#FBFAF8; --paper-2:#F4F2EE; --surface:#FFFFFF;
--neutral-100:#ECEFF1; --neutral-150:#E5E1DA; --neutral-200:#D5DBDE; --neutral-400:#98A4A9;
--ink:#1C2A2A; --ink-2:#5A6663; --ink-3:#93A09C; --hair:#E5E1DA;
/* 악센트 — 관리자: 슬레이트 (저채도, 운영) */
--accent:#5B5F6B; --accent-deep:#494C57; --accent-tint:#EEEFF1; --accent-bright:#7D818E;
/* 보조 온기 */
--clay:#B0735C; --clay-tint:#F6F0EC;
/* 의미색 */
--pos-text:#2C6E49; --pos-solid:#3B8C5E; --pos-tint:#E8F3EC;
--warn-text:#8A5A00; --warn-solid:#C28A2C; --warn-tint:#FAF1E0;
--crit-text:#A8352C; --crit-solid:#C4453A; --crit-tint:#FAEAE8;
--info-text:#2E5A7A; --info-solid:#3C7299; --info-tint:#EAF1F6;
--neutral-sig:#8895A2;
/* 별칭 */
--text-on-accent:#FBFAF8;
--focus-ring:rgba(91,95,107,.40);
/* 폰트 */
--font-sans:"Pretendard Variable",Pretendard,-apple-system,"Apple SD Gothic Neo","Noto Sans KR",system-ui,sans-serif;
--font-num:"Pretendard Variable","JetBrains Mono",ui-monospace,monospace;
/* spacing */
--sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:24px; --sp-6:32px; --sp-7:48px;
--radius:8px; --radius-sm:6px; --radius-lg:12px;
--maxw:1200px;
--shadow-sm:0 1px 2px rgba(28,42,42,.05);
--shadow-md:0 4px 14px rgba(28,42,42,.07);
--ease-out:cubic-bezier(.22,.61,.36,1);
}
*{margin:0;padding:0;box-sizing:border-box;}
html{scroll-behavior:smooth;}
body{
font-family:var(--font-sans); background:var(--paper); color:var(--ink);
-webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
letter-spacing:-0.01em; line-height:1.6;
}
.tab-num{font-variant-numeric:tabular-nums; letter-spacing:0.01em;}
/* ============ 공통 헤더 (톱바) ============ */
.topbar{
position:sticky; top:0; z-index:20; height:56px;
background:var(--surface); border-bottom:1px solid var(--hair);
display:flex; align-items:center; gap:var(--sp-6); padding:0 var(--sp-6);
}
.brand{display:flex; align-items:center; gap:10px;}
.brand .mark{width:22px; height:22px; flex:none;}
.brand .wm{font-size:17px; font-weight:700; letter-spacing:-0.02em; color:var(--ink);}
.brand .role{
margin-left:6px; font-family:var(--font-num); font-size:11px; font-weight:600;
letter-spacing:0.08em; text-transform:uppercase; color:var(--accent);
background:var(--accent-tint); padding:4px 9px; border-radius:5px;
}
.nav{display:flex; align-items:center; gap:2px; margin-left:var(--sp-4);}
.nav a{
font-size:14px; font-weight:500; color:var(--ink-3); text-decoration:none;
padding:8px 12px; border-radius:6px;
}
.nav a.on{color:var(--ink); font-weight:600; background:var(--accent-tint);}
.nav a:hover{color:var(--ink-2);}
.topbar .right{margin-left:auto; display:flex; align-items:center; gap:var(--sp-5);}
.envtag{font-family:var(--font-num); font-size:12px; color:var(--ink-3); display:flex; align-items:center; gap:7px;}
.envtag .d{width:6px; height:6px; border-radius:50%; background:var(--pos-solid);}
.who{display:flex; align-items:center; gap:9px;}
.who .av{width:30px; height:30px; border-radius:50%; background:var(--accent); color:var(--text-on-accent);
display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:600;}
.who .nm{font-size:13px; font-weight:600; color:var(--ink); line-height:1.2;}
.who .sub{font-size:11px; color:var(--ink-3);}
/* ============ 페이지 ============ */
.page{max-width:var(--maxw); margin:0 auto; padding:var(--sp-7) var(--sp-6) var(--sp-7);}
.kicker{
font-family:var(--font-num); font-size:12px; font-weight:600; letter-spacing:0.08em;
color:var(--accent); display:flex; align-items:center; gap:8px; margin-bottom:var(--sp-3);
}
.kicker .dot{width:6px; height:6px; border-radius:50%; background:var(--accent-bright);}
/* 페이지 헤드 */
.pagehead{display:flex; align-items:flex-end; justify-content:space-between; gap:var(--sp-5); margin-bottom:var(--sp-3);}
.pagehead h1{font-size:30px; font-weight:700; letter-spacing:-0.02em; color:var(--ink); line-height:1.25;}
.pagehead .lead{font-size:16px; color:var(--ink-2); margin-top:6px; max-width:600px;}
.pagehead .when{font-family:var(--font-num); font-size:13px; color:var(--ink-3); white-space:nowrap; text-align:right;}
.pagehead .when b{display:block; color:var(--ink-2); font-weight:600;}
/* 섹션 위계 */
.section{margin-top:var(--sp-7);}
.sechead{display:flex; align-items:baseline; justify-content:space-between; gap:var(--sp-4); margin-bottom:var(--sp-5);}
.sechead h2{font-size:20px; font-weight:600; letter-spacing:-0.01em; color:var(--ink);}
.sechead .meta{font-size:13px; color:var(--ink-3);}
.sechead .link{font-size:13px; font-weight:500; color:var(--accent); text-decoration:none; display:inline-flex; align-items:center; gap:6px;}
.sechead .link svg{width:14px; height:14px; stroke:var(--accent);}
/* ============ 1. 시스템 현황 ============ */
/* 한 줄 상태 요약 (큰 문장 하나 — 에디토리얼) */
.statusline{
display:flex; align-items:center; gap:14px;
padding:var(--sp-5) var(--sp-6); background:var(--surface);
border:1px solid var(--hair); border-radius:var(--radius-lg);
}
.statusline .pulse{width:11px; height:11px; border-radius:50%; background:var(--pos-solid); flex:none;
box-shadow:0 0 0 0 rgba(59,140,94,.4); animation:pulse 3.2s ease-in-out infinite;}
@keyframes pulse{0%,100%{box-shadow:0 0 0 0 rgba(59,140,94,.35)}50%{box-shadow:0 0 0 8px rgba(59,140,94,0)}}
.statusline .msg{font-size:18px; font-weight:500; color:var(--ink); line-height:1.5;}
.statusline .msg b{font-weight:700;}
.statusline .ts{margin-left:auto; font-family:var(--font-num); font-size:12px; color:var(--ink-3); white-space:nowrap;}
/* 핵심 지표 인라인 행 (카드덤프 아님 — 헤어라인 구분, 숫자 위계) */
.kpis{
display:grid; grid-template-columns:repeat(4,1fr); margin-top:var(--sp-5);
background:var(--surface); border:1px solid var(--hair); border-radius:var(--radius-lg);
overflow:hidden;
}
.kpi{padding:var(--sp-5) var(--sp-6); }
.kpi + .kpi{border-left:1px solid var(--hair);} /* 셀 divider — 강조선 아님, 칼럼 구분 헤어라인 */
.kpi .l{font-size:13px; color:var(--ink-3); font-weight:500;}
.kpi .n{font-size:34px; font-weight:700; color:var(--ink); letter-spacing:-0.02em; margin-top:8px; line-height:1;}
.kpi .n .u{font-size:15px; font-weight:500; color:var(--ink-3); margin-left:4px; letter-spacing:0;}
.kpi .d{font-size:12px; color:var(--ink-3); margin-top:9px; display:flex; align-items:center; gap:6px;}
.kpi .d .up{color:var(--pos-text); font-weight:600;}
.kpi .d .dn{color:var(--info-text); font-weight:600;}
/* 헬스 라인 (엔진/음성/DB — 절제된 상태 행) */
.health{margin-top:var(--sp-5); background:var(--surface); border:1px solid var(--hair); border-radius:var(--radius-lg);}
.hrow{display:grid; grid-template-columns:200px 1fr auto auto; align-items:center;
gap:var(--sp-4); padding:14px var(--sp-6);}
.hrow + .hrow{border-top:1px solid var(--hair);}
.hrow .svc{display:flex; align-items:center; gap:11px;}
.hrow .svc .d{width:8px; height:8px; border-radius:50%; flex:none;}
.hrow .svc .d.ok{background:var(--pos-solid);}
.hrow .svc .d.warn{background:var(--warn-solid);}
.hrow .svc .d.crit{background:var(--crit-solid);}
.hrow .svc .nm{font-size:15px; font-weight:600; color:var(--ink);}
.hrow .svc .sub{font-size:12px; color:var(--ink-3); display:block; font-weight:400;}
.hrow .gauge{height:5px; background:var(--paper-2); border-radius:3px; overflow:hidden; max-width:280px;}
.hrow .gauge .fill{height:100%; border-radius:3px;}
.hrow .gauge .fill.ok{background:var(--accent-bright);}
.hrow .gauge .fill.warn{background:var(--warn-solid);}
.hrow .num{font-family:var(--font-num); font-size:14px; font-weight:600; color:var(--ink-2); text-align:right; min-width:74px;}
.hrow .stat{font-size:12px; font-weight:600; padding:3px 10px; border-radius:5px; white-space:nowrap;}
.hrow .stat.ok{background:var(--pos-tint); color:var(--pos-text);}
.hrow .stat.warn{background:var(--warn-tint); color:var(--warn-text);}
.hrow .stat.crit{background:var(--crit-tint); color:var(--crit-text);}
/* ============ 2. 수집 현황 (분포) ============ */
.collect{display:grid; grid-template-columns:1.4fr 1fr; gap:var(--sp-6);}
.panel{background:var(--surface); border:1px solid var(--hair); border-radius:var(--radius-lg); padding:var(--sp-6);}
.panel .ph{font-size:16px; font-weight:600; color:var(--ink); margin-bottom:var(--sp-2);}
.panel .psub{font-size:13px; color:var(--ink-3); margin-bottom:var(--sp-5);}
/* 진행 세션/누적 분포 — 가로 게이지 목록 (카드 격자 회피) */
.distrib{display:flex; flex-direction:column; gap:var(--sp-5);}
.dist{display:grid; grid-template-columns:130px 1fr 56px; align-items:center; gap:var(--sp-4);}
.dist .dl{font-size:14px; color:var(--ink-2); font-weight:500;}
.dist .db{height:8px; background:var(--paper-2); border-radius:4px; overflow:hidden;}
.dist .db .f{height:100%; border-radius:4px; background:var(--accent-bright);}
.dist .db .f.clay{background:var(--clay);}
.dist .db .f.warn{background:var(--warn-solid);}
.dist .dv{font-family:var(--font-num); font-size:14px; font-weight:600; color:var(--ink); text-align:right;}
/* 역할 수집 요약 — 작은 행 목록 */
.rolelist{display:flex; flex-direction:column;}
.rr{display:flex; align-items:center; justify-content:space-between; padding:14px 0;}
.rr + .rr{border-top:1px solid var(--paper-2);}
.rr .rl{display:flex; align-items:center; gap:11px;}
.rr .rl .rd{width:9px; height:9px; border-radius:2px; flex:none;}
.rr .rl .nm{font-size:14px; color:var(--ink); font-weight:500;}
.rr .rl .nm .sub{display:block; font-size:12px; color:var(--ink-3); font-weight:400;}
.rr .rv{font-family:var(--font-num); font-size:18px; font-weight:700; color:var(--ink);}
.rr .rv .delta{font-size:12px; font-weight:600; color:var(--pos-text); margin-left:8px;}
/* ============ 3. 감사 로그 (교수자 활동) ============ */
.audit{background:var(--surface); border:1px solid var(--hair); border-radius:var(--radius-lg); overflow:hidden;}
.audit .toolbar{display:flex; align-items:center; gap:var(--sp-3); padding:var(--sp-4) var(--sp-5);
border-bottom:1px solid var(--hair);}
.audit .toolbar .search{flex:1; max-width:320px; display:flex; align-items:center; gap:9px;
background:var(--paper-2); border:1px solid var(--hair); border-radius:var(--radius-sm); padding:8px 12px;}
.audit .toolbar .search svg{width:15px; height:15px; stroke:var(--ink-3); flex:none;}
.audit .toolbar .search input{border:none; background:none; outline:none; font-family:var(--font-sans);
font-size:14px; color:var(--ink); width:100%;}
.audit .toolbar .search input::placeholder{color:var(--ink-3);}
.chip{font-size:13px; font-weight:500; color:var(--ink-2); padding:7px 13px; border-radius:6px;
border:1px solid var(--hair); background:var(--surface); cursor:pointer; white-space:nowrap;}
.chip.on{background:var(--accent-tint); color:var(--accent-deep); border-color:transparent; font-weight:600;}
.audit .spacer{flex:1;}
table{width:100%; border-collapse:collapse;}
thead th{
font-family:var(--font-num); font-size:11px; font-weight:600; letter-spacing:0.06em;
text-transform:uppercase; color:var(--ink-3); text-align:left;
padding:11px var(--sp-5); background:var(--paper-2); border-bottom:1px solid var(--hair);
}
tbody td{padding:14px var(--sp-5); border-bottom:1px solid var(--paper-2); font-size:14px; color:var(--ink-2); vertical-align:middle;}
tbody tr:last-child td{border-bottom:none;}
tbody tr:hover{background:var(--paper);}
td .actor{display:flex; align-items:center; gap:10px;}
td .actor .av{width:28px; height:28px; border-radius:50%; flex:none; display:flex; align-items:center; justify-content:center;
font-size:11px; font-weight:600; background:var(--accent-tint); color:var(--accent-deep);}
td .actor .nm{font-size:14px; font-weight:600; color:var(--ink); line-height:1.3;}
td .actor .nm .sub{display:block; font-size:11px; color:var(--ink-3); font-weight:400;}
td.time{font-family:var(--font-num); font-size:13px; color:var(--ink-3); white-space:nowrap;}
td .act{display:inline-flex; align-items:center; gap:8px;}
td .act .g{width:7px; height:7px; border-radius:50%; flex:none; background:var(--accent-bright);}
td .act .g.view{background:var(--info-solid);}
td .act .g.export{background:var(--clay);}
td .act .g.grade{background:var(--pos-solid);}
td .act .g.edit{background:var(--warn-solid);}
td .target{color:var(--ink); font-weight:500;}
td .target .meta{display:block; font-size:12px; color:var(--ink-3); font-weight:400;}
td .scope{font-size:12px; font-weight:600; padding:3px 9px; border-radius:5px; background:var(--accent-tint); color:var(--accent-deep);}
td .scope.sens{background:var(--warn-tint); color:var(--warn-text);}
.audit .footer{display:flex; align-items:center; justify-content:space-between; padding:13px var(--sp-5); border-top:1px solid var(--hair);}
.audit .footer .cnt{font-size:13px; color:var(--ink-3);}
.audit .footer .pg{display:flex; gap:6px;}
.audit .footer .pg button{font-family:var(--font-num); font-size:13px; color:var(--ink-2); border:1px solid var(--hair);
background:var(--surface); width:30px; height:30px; border-radius:6px; cursor:pointer;}
.audit .footer .pg button.on{background:var(--accent); color:var(--text-on-accent); border-color:transparent; font-weight:600;}
/* ============ 4. 관리 진입 ============ */
.mgmt{display:grid; grid-template-columns:repeat(4,1fr); gap:var(--sp-4);}
.entry{
display:flex; flex-direction:column; gap:11px; padding:var(--sp-5);
background:var(--surface); border:1px solid var(--hair); border-radius:var(--radius-lg);
text-decoration:none; color:inherit; transition:border-color .16s var(--ease-out), transform .16s var(--ease-out);
}
.entry:hover{border-color:var(--accent-bright); transform:translateY(-1px);}
.entry .ico{width:34px; height:34px; border-radius:8px; background:var(--accent-tint);
display:flex; align-items:center; justify-content:center;}
.entry .ico svg{width:18px; height:18px; stroke:var(--accent-deep); fill:none;}
.entry .t{font-size:15px; font-weight:600; color:var(--ink);}
.entry .d{font-size:13px; color:var(--ink-3); line-height:1.5;}
.entry .go{margin-top:auto; font-size:12px; font-weight:600; color:var(--accent); display:flex; align-items:center; gap:5px; padding-top:4px;}
.entry .go svg{width:13px; height:13px; stroke:var(--accent);}
.entry .badge{font-family:var(--font-num); font-size:11px; font-weight:600; color:var(--warn-text);
background:var(--warn-tint); padding:2px 7px; border-radius:4px; margin-left:auto;}
footer.foot{max-width:var(--maxw); margin:0 auto; padding:var(--sp-6); border-top:1px solid var(--hair);
margin-top:var(--sp-7); display:flex; align-items:center; justify-content:space-between;
font-size:12px; color:var(--ink-3);}
@media (prefers-reduced-motion: reduce){
*,*::before,*::after{animation-duration:.01ms!important; transition-duration:.01ms!important;}
}
@media (max-width:1080px){
.kpis{grid-template-columns:repeat(2,1fr);}
.kpi:nth-child(3){border-left:none; border-top:1px solid var(--hair);}
.kpi:nth-child(4){border-top:1px solid var(--hair);}
.collect{grid-template-columns:1fr;}
.mgmt{grid-template-columns:repeat(2,1fr);}
}
</style>
</head>
<body>
<!-- ============ 공통 헤더 ============ -->
<header class="topbar">
<div class="brand">
<svg class="mark" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<rect x="3" y="3" width="18" height="18" rx="5" stroke="#5B5F6B" stroke-width="2"/>
<circle cx="12" cy="12" r="4.2" fill="#5B5F6B"/>
</svg>
<span class="wm">Vignette</span>
<span class="role">Admin</span>
</div>
<nav class="nav">
<a href="#" class="on">대시보드</a>
<a href="#audit">감사 로그</a>
<a href="#mgmt">데이터·페르소나</a>
<a href="#">공지</a>
</nav>
<div class="right">
<div class="envtag"><span class="d"></span>운영 환경 · v2.4.1</div>
<div class="who">
<div class="av"></div>
<div>
<div class="nm">박운영</div>
<div class="sub">시스템 관리자</div>
</div>
</div>
</div>
</header>
<div class="page">
<!-- 페이지 헤드 -->
<div class="pagehead">
<div>
<div class="kicker"><span class="dot"></span>운영 콘솔</div>
<h1>시스템 현황</h1>
<p class="lead">플랫폼 가동 상태와 전체 사용·세션 흐름을 한눈에. 교수자가 무엇을 열람했는지까지 추적합니다.</p>
</div>
<div class="when">
<b>2026-06-25 21:14 KST</b>
최근 동기화 22초 전
</div>
</div>
<!-- 한 줄 상태 요약 -->
<div class="statusline">
<span class="pulse"></span>
<span class="msg">모든 핵심 서비스가 <b>정상 가동</b> 중입니다. 음성 합성 지연만 평소보다 약간 높습니다.</span>
<span class="ts tab-num">uptime 47d 12h</span>
</div>
<!-- 핵심 지표 -->
<div class="kpis">
<div class="kpi">
<div class="l">진행 중 세션</div>
<div class="n tab-num">14<span class="u"></span></div>
<div class="d"><span class="up">+5</span> 지난 1시간 대비</div>
</div>
<div class="kpi">
<div class="l">오늘 완료 세션</div>
<div class="n tab-num">186<span class="u"></span></div>
<div class="d"><span class="up">+12%</span> 전일 동시간 대비</div>
</div>
<div class="kpi">
<div class="l">활성 사용자 (24h)</div>
<div class="n tab-num">312<span class="u"></span></div>
<div class="d">학습 287 · 교수 21 · 관리 4</div>
</div>
<div class="kpi">
<div class="l">평균 평가 지연</div>
<div class="n tab-num">1.8<span class="u"></span></div>
<div class="d"><span class="dn">목표 2.0초</span> 이내</div>
</div>
</div>
<!-- 헬스 라인 -->
<div class="section" style="margin-top:var(--sp-5)">
<div class="sechead">
<h2>서비스 헬스</h2>
<span class="meta">엔진 · 음성 · DB · 큐 · 스토리지</span>
</div>
<div class="health">
<div class="hrow">
<div class="svc"><span class="d ok"></span><span><span class="nm">내담자 대화 엔진</span><span class="sub">LLM 추론 · 가드레일</span></span></div>
<div class="gauge"><div class="fill ok" style="width:42%"></div></div>
<div class="num tab-num">42% 부하</div>
<span class="stat ok">정상</span>
</div>
<div class="hrow">
<div class="svc"><span class="d warn"></span><span><span class="nm">음성 합성 (TTS)</span><span class="sub">스트리밍 · 8개 보이스</span></span></div>
<div class="gauge"><div class="fill warn" style="width:78%"></div></div>
<div class="num tab-num">P95 1.4s</div>
<span class="stat warn">지연 주의</span>
</div>
<div class="hrow">
<div class="svc"><span class="d ok"></span><span><span class="nm">음성 인식 (STT)</span><span class="sub">실시간 스트림</span></span></div>
<div class="gauge"><div class="fill ok" style="width:36%"></div></div>
<div class="num tab-num">P95 0.6s</div>
<span class="stat ok">정상</span>
</div>
<div class="hrow">
<div class="svc"><span class="d ok"></span><span><span class="nm">세션·평가 DB</span><span class="sub">PostgreSQL 기본</span></span></div>
<div class="gauge"><div class="fill ok" style="width:51%"></div></div>
<div class="num tab-num">conn 51/200</div>
<span class="stat ok">정상</span>
</div>
<div class="hrow">
<div class="svc"><span class="d ok"></span><span><span class="nm">평가 작업 큐</span><span class="sub">회기말 리뷰 생성</span></span></div>
<div class="gauge"><div class="fill ok" style="width:18%"></div></div>
<div class="num tab-num">대기 3건</div>
<span class="stat ok">정상</span>
</div>
</div>
</div>
<!-- ============ 2. 수집 현황 ============ -->
<div class="section">
<div class="sechead">
<h2>사용·세션 수집 현황</h2>
<span class="meta">최근 7일 기준</span>
</div>
<div class="collect">
<div class="panel">
<div class="ph">시나리오별 세션 분포</div>
<div class="psub">이번 주 누적 1,284회기 · 가장 많이 연습된 사례 순</div>
<div class="distrib">
<div class="dist"><span class="dl">우울 호소 청소년</span><div class="db"><div class="f clay" style="width:88%"></div></div><span class="dv tab-num">412</span></div>
<div class="dist"><span class="dl">불안·공황 20대</span><div class="db"><div class="f" style="width:64%"></div></div><span class="dv tab-num">298</span></div>
<div class="dist"><span class="dl">관계 갈등 성인</span><div class="db"><div class="f" style="width:48%"></div></div><span class="dv tab-num">221</span></div>
<div class="dist"><span class="dl">학업 스트레스 고3</span><div class="db"><div class="f" style="width:37%"></div></div><span class="dv tab-num">174</span></div>
<div class="dist"><span class="dl">위기 개입 시뮬</span><div class="db"><div class="f warn" style="width:25%"></div></div><span class="dv tab-num">112</span></div>
<div class="dist"><span class="dl">기타</span><div class="db"><div class="f" style="width:14%"></div></div><span class="dv tab-num">67</span></div>
</div>
</div>
<div class="panel">
<div class="ph">역할별 사용 현황</div>
<div class="psub">전체 등록 계정 대비 활성</div>
<div class="rolelist">
<div class="rr">
<div class="rl"><span class="rd" style="background:#3E7A6E"></span><span class="nm">학습자<span class="sub">상담 수련생 · 등록 248</span></span></div>
<div class="rv tab-num">231<span class="delta">+18</span></div>
</div>
<div class="rr">
<div class="rl"><span class="rd" style="background:#3A5BA0"></span><span class="nm">교수자<span class="sub">슈퍼바이저 · 등록 34</span></span></div>
<div class="rv tab-num">29<span class="delta">+2</span></div>
</div>
<div class="rr">
<div class="rl"><span class="rd" style="background:#5B5F6B"></span><span class="nm">관리자<span class="sub">운영 · 등록 6</span></span></div>
<div class="rv tab-num">4</div>
</div>
<div class="rr">
<div class="rl"><span class="rd" style="background:var(--clay)"></span><span class="nm">페르소나<span class="sub">가상 내담자 풀</span></span></div>
<div class="rv tab-num">23<span class="delta">+3</span></div>
</div>
</div>
</div>
</div>
</div>
<!-- ============ 3. 교수자 활동 감사 로그 ============ -->
<div class="section" id="audit">
<div class="sechead">
<h2>교수자 활동 감사 로그</h2>
<a href="#" class="link">전체 로그 내보내기
<svg viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
</a>
</div>
<div class="audit">
<div class="toolbar">
<div class="search">
<svg viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
<input placeholder="교수자·학습자·세션 ID로 검색">
</div>
<span class="chip on">전체</span>
<span class="chip">세션 열람</span>
<span class="chip">오디오 재생</span>
<span class="chip">PDF 내보내기</span>
<span class="chip">평가 수정</span>
<div class="spacer"></div>
<span class="chip">최근 24시간</span>
</div>
<table>
<thead>
<tr>
<th style="width:120px">시각</th>
<th style="width:200px">교수자</th>
<th style="width:160px">행위</th>
<th>대상</th>
<th style="width:120px">범위</th>
</tr>
</thead>
<tbody>
<tr>
<td class="time">21:08:42</td>
<td><div class="actor"><span class="av"></span><span class="nm">김상담<span class="sub">슈퍼바이저</span></span></div></td>
<td><span class="act"><span class="g view"></span>회기 리뷰 열람</span></td>
<td><span class="target">서연 사례 · 회기 1 리뷰<span class="meta">학습자 이수민 · 세션 #S-20448</span></span></td>
<td><span class="scope sens">학습자 식별</span></td>
</tr>
<tr>
<td class="time">20:51:17</td>
<td><div class="actor"><span class="av"></span><span class="nm">정교수<span class="sub">슈퍼바이저</span></span></div></td>
<td><span class="act"><span class="g export"></span>리뷰 PDF 내보내기</span></td>
<td><span class="target">불안·공황 20대 · 회기 3<span class="meta">학습자 박지훈 · 세션 #S-20431</span></span></td>
<td><span class="scope sens">원본 포함</span></td>
</tr>
<tr>
<td class="time">20:39:05</td>
<td><div class="actor"><span class="av"></span><span class="nm">김상담<span class="sub">슈퍼바이저</span></span></div></td>
<td><span class="act"><span class="g grade"></span>슈퍼바이저 코멘트 작성</span></td>
<td><span class="target">감정 반영 구간에 코멘트 3건<span class="meta">학습자 이수민 · 세션 #S-20448</span></span></td>
<td><span class="scope">평가 작성</span></td>
</tr>
<tr>
<td class="time">20:22:48</td>
<td><div class="actor"><span class="av"></span><span class="nm">한지도<span class="sub">슈퍼바이저</span></span></div></td>
<td><span class="act"><span class="g view"></span>오디오 다시듣기</span></td>
<td><span class="target">관계 갈등 성인 · 회기 2<span class="meta">학습자 최영아 · 세션 #S-20419</span></span></td>
<td><span class="scope sens">음성 원본</span></td>
</tr>
<tr>
<td class="time">19:57:31</td>
<td><div class="actor"><span class="av"></span><span class="nm">정교수<span class="sub">슈퍼바이저</span></span></div></td>
<td><span class="act"><span class="g edit"></span>평가 항목 수정</span></td>
<td><span class="target">'닫힌 질문' 라벨 1건 해제<span class="meta">학습자 박지훈 · 세션 #S-20431</span></span></td>
<td><span class="scope">평가 수정</span></td>
</tr>
<tr>
<td class="time">19:40:12</td>
<td><div class="actor"><span class="av"></span><span class="nm">한지도<span class="sub">슈퍼바이저</span></span></div></td>
<td><span class="act"><span class="g view"></span>학습자 성장 곡선 열람</span></td>
<td><span class="target">담당 그룹 12명 추세<span class="meta">2026 봄학기 상담실습 A반</span></span></td>
<td><span class="scope">집계 조회</span></td>
</tr>
<tr>
<td class="time">19:12:55</td>
<td><div class="actor"><span class="av"></span><span class="nm">김상담<span class="sub">슈퍼바이저</span></span></div></td>
<td><span class="act"><span class="g view"></span>실시간 세션 관찰</span></td>
<td><span class="target">우울 호소 청소년 · 진행 중<span class="meta">학습자 이수민 · 세션 #S-20448</span></span></td>
<td><span class="scope sens">실시간 열람</span></td>
</tr>
</tbody>
</table>
<div class="footer">
<span class="cnt">최근 24시간 248건 중 17 표시 · 모든 열람은 위·변조 불가 로그로 보존됩니다</span>
<div class="pg">
<button class="on">1</button>
<button>2</button>
<button>3</button>
<button></button>
</div>
</div>
</div>
</div>
<!-- ============ 4. 관리 진입 ============ -->
<div class="section" id="mgmt">
<div class="sechead">
<h2>관리</h2>
<span class="meta">데이터 · 페르소나 · 공지 · 정책</span>
</div>
<div class="mgmt">
<a href="#" class="entry">
<div class="ico"><svg viewBox="0 0 24 24" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="8" ry="3"/><path d="M4 5v14c0 1.66 3.58 3 8 3s8-1.34 8-3V5"/><path d="M4 12c0 1.66 3.58 3 8 3s8-1.34 8-3"/></svg></div>
<div class="t">데이터 관리</div>
<div class="d">세션 기록·평가 데이터 보존, 익명화, 내보내기 정책.</div>
<div class="go">바로가기 <svg viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg></div>
</a>
<a href="#" class="entry">
<div class="ico"><svg viewBox="0 0 24 24" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="4"/><path d="M4 21c0-4 3.6-6 8-6s8 2 8 6"/></svg></div>
<div class="t">페르소나 관리 <span class="badge">신규 3</span></div>
<div class="d">가상 내담자 풀, 정서 파라미터, 미성년 라벨 검수.</div>
<div class="go">바로가기 <svg viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg></div>
</a>
<a href="#" class="entry">
<div class="ico"><svg viewBox="0 0 24 24" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 11l18-5v12L3 14v-3z"/><path d="M11.6 16.8a3 3 0 1 1-5.8-1.6"/></svg></div>
<div class="t">공지 관리</div>
<div class="d">학기 일정, 점검 안내, 역할별 배너 공지 발행.</div>
<div class="go">바로가기 <svg viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg></div>
</a>
<a href="#" class="entry">
<div class="ico"><svg viewBox="0 0 24 24" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2l8 3v6c0 5-3.5 8.5-8 10-4.5-1.5-8-5-8-10V5l8-3z"/><path d="M9 12l2 2 4-4"/></svg></div>
<div class="t">정책·가드레일</div>
<div class="d">위기 개입 규칙, 안전 점검 임계치, 권한 정책.</div>
<div class="go">바로가기 <svg viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg></div>
</a>
</div>
</div>
</div>
<footer class="foot">
<span>Vignette · AI 심리상담 시뮬레이션 훈련 플랫폼 · 한신대학교 산학협력</span>
<span class="tab-num">운영 환경 · v2.4.1</span>
</footer>
</body>
</html>