Files
comrelay/Relay 화면 전체/업무 상세.html
T
2026-06-16 17:12:08 +09:00

1011 lines
75 KiB
HTML
Raw 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>메인 배너 이미지 2종 디자인 — Relay</title>
<link rel="preconnect" href="https://cdn.jsdelivr.net">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard.css">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #f4f5f7; --panel: #ffffff; --border: #e6e8ec; --border-strong: #d7dae0;
--text: #16181d; --text-2: #5b626e; --text-3: #9298a3;
--accent: #4f46e5; --accent-hover: #4338ca; --accent-weak: #eef0fe; --accent-border: #c7ccfb;
--green: #1f9d57; --green-weak: #e8f6ee; --blue: #1d4ed8; --blue-weak: #e8efff; --blue-border: #c9dbff;
--red: #d6455d; --red-weak: #fdeef0; --red-border: #f1c0c8; --amber: #b7791f; --amber-weak: #fdf4e3; --amber-border: #f3e2bd;
--radius: 6px; --radius-sm: 4px; --shadow-sm: 0 1px 2px rgba(20,24,33,.05);
}
html, body { background: var(--bg); color: var(--text); font-family: "Pretendard", -apple-system, system-ui, sans-serif; font-size: 14px; line-height: 1.5; -webkit-font-smoothing: antialiased; }
body { min-height: 100vh; }
/* topbar */
.topbar { height: 52px; background: var(--panel); border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 28px; padding: 0 20px; position: sticky; top: 0; z-index: 50; }
.brand { display: flex; align-items: center; gap: 9px; font-weight: 700; font-size: 15px; letter-spacing: -.2px; }
.brand .logo { width: 26px; height: 26px; border-radius: 7px; background: linear-gradient(135deg, #5b54f0, #4338ca); display: grid; place-items: center; color: #fff; font-size: 15px; font-weight: 800; box-shadow: 0 2px 6px rgba(79,70,229,.35); }
.topnav { display: flex; align-items: center; gap: 2px; }
.topnav a { color: var(--text-2); text-decoration: none; font-size: 13.5px; font-weight: 500; padding: 7px 12px; border-radius: var(--radius-sm); line-height: 1; white-space: nowrap; }
.topnav a:hover { background: #f1f2f4; color: var(--text); }
.topnav a.active { color: var(--accent); background: var(--accent-weak); font-weight: 600; }
.topbar-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.icon-btn { width: 32px; height: 32px; border-radius: var(--radius-sm); border: none; background: transparent; color: var(--text-2); display: grid; place-items: center; cursor: pointer; }
.icon-btn:hover { background: #f1f2f4; color: var(--text); }
.icon-btn.agent { color: var(--accent); }
.icon-btn.agent:hover { background: var(--accent-weak); color: var(--accent-hover); }
.me { width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center; font-size: 11.5px; font-weight: 700; color: #fff; background: #0ea5a3; margin-left: 4px; }
/* page */
.page { max-width: 1080px; margin: 0 auto; padding: 0 24px 60px; }
.crumb { display: flex; align-items: center; gap: 7px; color: var(--text-3); font-size: 12.5px; padding: 16px 0 0; white-space: nowrap; }
.crumb .lnk { color: var(--text-2); font-weight: 600; text-decoration: none; }
.crumb .lnk:hover { color: var(--accent); }
.crumb .sep { opacity: .5; }
.crumb b { color: var(--text-2); font-weight: 600; }
.pagehead { display: flex; align-items: flex-start; gap: 14px; padding: 12px 0 18px; }
.ph-main { flex: 1; min-width: 0; }
.ph-titlerow { display: flex; align-items: center; gap: 10px; }
.st-badge { font-size: 11.5px; font-weight: 600; padding: 3px 10px; border-radius: 20px; white-space: nowrap; }
.st-badge.prog { color: var(--blue); background: var(--blue-weak); border: 1px solid var(--blue-border); }
.st-badge.review { color: var(--amber); background: var(--amber-weak); border: 1px solid var(--amber-border); }
.st-badge.done { color: var(--green); background: var(--green-weak); border: 1px solid #cde8d8; }
.st-badge.changes { color: var(--red); background: var(--red-weak); border: 1px solid var(--red-border); }
.ph-tid { font-size: 14px; font-weight: 600; color: var(--text-3); }
h1.ph-title { font-size: 23px; font-weight: 700; letter-spacing: -.5px; margin-top: 8px; line-height: 1.3; }
.pagehead .actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; padding-top: 2px; }
.btn { height: 34px; padding: 0 14px; border-radius: var(--radius); font-size: 13.5px; font-weight: 600; border: 1px solid var(--border-strong); background: var(--panel); color: var(--text-2); cursor: pointer; display: inline-flex; align-items: center; gap: 6px; line-height: 1; text-decoration: none; white-space: nowrap; }
.btn:hover { background: #f7f8fa; color: var(--text); }
.btn svg { width: 15px; height: 15px; }
.btn.icon { width: 34px; padding: 0; justify-content: center; }
/* more menu */
.more-wrap { position: relative; }
.menu { display: none; position: absolute; top: calc(100% + 6px); right: 0; z-index: 40; width: 168px; background: #fff; border: 1px solid var(--border); border-radius: 9px; box-shadow: 0 12px 32px rgba(20,24,33,.16); padding: 5px; }
.menu.open { display: block; }
.menu-item { display: flex; align-items: center; gap: 10px; width: 100%; border: none; background: transparent; font-family: inherit; font-size: 13px; font-weight: 500; color: var(--text); padding: 8px 9px; border-radius: var(--radius-sm); cursor: pointer; text-align: left; white-space: nowrap; }
.menu-item:hover { background: #f5f6f8; }
.menu-item svg { width: 16px; height: 16px; color: var(--text-3); flex-shrink: 0; }
.menu-item.danger { color: var(--red); }
.menu-item.danger svg { color: var(--red); }
.menu-item.danger:hover { background: var(--red-weak); }
.menu-sep { height: 1px; background: var(--border); margin: 5px 0; }
/* modal */
.modal-backdrop { position: fixed; inset: 0; background: rgba(20,24,33,.5); display: none; align-items: center; justify-content: center; z-index: 100; padding: 24px; }
.modal-backdrop.open { display: flex; }
.modal { width: 100%; max-width: 440px; background: #fff; border-radius: 14px; box-shadow: 0 24px 64px rgba(20,24,33,.32); overflow: hidden; }
.modal-body { padding: 26px 24px 8px; text-align: center; }
.modal-ico { width: 46px; height: 46px; border-radius: 50%; background: var(--red-weak); color: var(--red); display: grid; place-items: center; margin: 0 auto 14px; }
.modal-ico svg { width: 22px; height: 22px; }
.modal-title { font-size: 17px; font-weight: 700; letter-spacing: -.3px; }
.modal-desc { font-size: 13px; color: var(--text-2); line-height: 1.6; margin-top: 8px; }
.modal-desc b { color: var(--text); font-weight: 600; }
.modal-foot { display: flex; gap: 9px; padding: 18px 24px 20px; }
.mbtn { flex: 1; height: 40px; border-radius: var(--radius); font-size: 13.5px; font-weight: 600; border: 1px solid var(--border-strong); background: #fff; color: var(--text-2); cursor: pointer; }
.mbtn:hover { background: #f1f2f4; color: var(--text); }
.mbtn.danger { background: var(--red); border-color: var(--red); color: #fff; box-shadow: 0 1px 2px rgba(214,69,93,.4); }
.mbtn.danger:hover { background: #c23a51; }
.mbtn.approve { background: var(--green); border-color: var(--green); color: #fff; box-shadow: 0 1px 2px rgba(31,157,87,.4); }
.mbtn.approve:hover { background: #188a4b; }
.modal-textarea { width: 100%; min-height: 92px; border: 1px solid var(--border-strong); border-radius: var(--radius); padding: 10px 12px; font-family: inherit; font-size: 13.5px; line-height: 1.6; color: var(--text); resize: vertical; }
.modal-textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-weak); }
.modal-textarea::placeholder { color: var(--text-3); }
/* approval sidebar card */
.ap-card { padding: 16px 18px 18px; border-width: 1px; border-style: solid; }
.ap-card.review { border-color: var(--amber-border); background: var(--amber-weak); }
.ap-card.request { border-color: var(--accent-border); background: var(--accent-weak); }
.ap-card-head { display: flex; align-items: center; gap: 9px; }
.ap-card-ico { width: 30px; height: 30px; border-radius: 8px; background: #fff; display: grid; place-items: center; flex-shrink: 0; border: 1px solid; }
.ap-card.review .ap-card-ico { color: var(--amber); border-color: var(--amber-border); }
.ap-card.request .ap-card-ico { color: var(--accent); border-color: var(--accent-border); }
.ap-card-ico svg { width: 17px; height: 17px; }
.ap-card-title { font-size: 14px; font-weight: 700; white-space: nowrap; }
.ap-card.review .ap-card-title { color: #8a5a12; }
.ap-card.request .ap-card-title { color: var(--accent-hover); }
.ap-card-meta { font-size: 12px; color: var(--text-2); margin-top: 10px; line-height: 1.5; }
.ap-card-meta b { color: var(--text); font-weight: 600; }
.ap-card-desc { font-size: 12.5px; color: var(--text-2); margin-top: 10px; line-height: 1.55; }
.ap-card-note { font-size: 12.5px; color: var(--text); background: #fff; border: 1px solid var(--amber-border); border-radius: 8px; padding: 9px 11px; margin-top: 10px; line-height: 1.5; }
.ap-card-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 13px; }
.ap-btn { height: 38px; padding: 0 14px; border-radius: var(--radius); font-size: 13.5px; font-weight: 600; cursor: pointer; border: 1px solid var(--border-strong); background: #fff; color: var(--text-2); display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
.ap-btn svg { width: 15px; height: 15px; }
.ap-btn.reject:hover { background: #fdeef0; border-color: var(--red-border); color: var(--red); }
.ap-btn.approve { background: var(--green); border-color: var(--green); color: #fff; box-shadow: 0 1px 2px rgba(31,157,87,.4); }
.ap-btn.approve:hover { background: #188a4b; }
.ap-btn.request-send { background: var(--accent); border-color: var(--accent); color: #fff; box-shadow: 0 1px 2px rgba(79,70,229,.4); }
.ap-btn.request-send:hover { background: var(--accent-hover); }
/* thread tabs: 댓글 / 활동 */
.thread-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border); margin-bottom: 18px; }
.thread-tab { position: relative; border: none; background: transparent; font-family: inherit; font-size: 13.5px; font-weight: 600; color: var(--text-3); padding: 8px 12px 11px; cursor: pointer; display: inline-flex; align-items: center; gap: 7px; line-height: 1; white-space: nowrap; }
.thread-tab:hover { color: var(--text-2); }
.thread-tab.active { color: var(--accent); }
.thread-tab.active::after { content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; background: var(--accent); border-radius: 2px; }
.tt-count { font-size: 11.5px; font-weight: 600; color: var(--text-3); background: #f1f2f4; border-radius: 20px; padding: 1px 7px; line-height: 1.55; }
.thread-tab.active .tt-count { color: var(--accent); background: var(--accent-weak); }
.thread-panel[hidden] { display: none; }
/* activity timeline */
.activity { display: flex; flex-direction: column; padding-top: 2px; }
.act { display: grid; grid-template-columns: 28px 1fr; gap: 13px; position: relative; }
.act::before { content: ''; position: absolute; left: 13px; top: 30px; bottom: -2px; width: 2px; background: var(--border); }
.act:last-child::before { display: none; }
.act-ico { width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center; border: 1px solid var(--border); background: #fff; color: var(--text-2); z-index: 1; }
.act-ico svg { width: 14px; height: 14px; }
.act-ico.green { background: var(--green-weak); border-color: #cde8d8; color: var(--green); }
.act-ico.amber { background: var(--amber-weak); border-color: var(--amber-border); color: var(--amber); }
.act-ico.blue { background: var(--blue-weak); border-color: var(--blue-border); color: var(--blue); }
.act-ico.accent { background: var(--accent-weak); border-color: var(--accent-border); color: var(--accent); }
.act-body { padding-bottom: 20px; min-width: 0; }
.act:last-child .act-body { padding-bottom: 0; }
.act-text { font-size: 13.5px; color: var(--text); line-height: 1.5; }
.act-text b { font-weight: 600; }
.act-file { display: inline-flex; align-items: center; gap: 7px; margin-top: 7px; padding: 5px 9px; border: 1px solid var(--border); border-radius: var(--radius); font-size: 12px; font-weight: 600; color: var(--text-2); }
.act-file .fi { width: 20px; height: 20px; border-radius: 4px; background: #e25950; color: #fff; display: grid; place-items: center; font-size: 7px; font-weight: 800; }
.act-chips { display: inline-flex; align-items: center; gap: 7px; margin-top: 8px; }
.act-chip { font-size: 11.5px; font-weight: 600; padding: 2px 9px; border-radius: 20px; white-space: nowrap; }
.act-chip.from { color: var(--text-2); background: #f1f2f4; border: 1px solid var(--border); }
.act-chip.to { color: var(--amber); background: var(--amber-weak); border: 1px solid var(--amber-border); }
.act-chips svg { width: 14px; height: 14px; color: var(--text-3); }
.act-time { font-size: 11.5px; color: var(--text-3); margin-top: 6px; }
/* layout */
.layout { display: grid; grid-template-columns: 1fr 320px; gap: 20px; align-items: start; }
.card { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; box-shadow: var(--shadow-sm); }
.main-card { padding: 22px 26px 26px; }
.sect + .sect { margin-top: 26px; padding-top: 22px; border-top: 1px solid var(--border); }
.sect-label { display: flex; align-items: center; gap: 8px; font-size: 12.5px; font-weight: 600; color: var(--text-2); margin-bottom: 12px; white-space: nowrap; }
.sect-label .pr { margin-left: auto; display: flex; align-items: center; gap: 9px; }
.progress-bar { width: 92px; height: 6px; border-radius: 4px; background: #eceef1; overflow: hidden; }
.progress-bar > i { display: block; height: 100%; background: var(--green); border-radius: 4px; }
.progress-txt { font-size: 12px; font-weight: 600; color: var(--text-2); white-space: nowrap; }
.content { font-size: 14px; color: var(--text); line-height: 1.7; }
.content p { margin-bottom: 11px; }
.content p:last-child { margin-bottom: 0; }
.content .mention { color: var(--accent); font-weight: 600; background: var(--accent-weak); padding: 0 3px; border-radius: 3px; }
/* checklist */
.checklist { display: flex; flex-direction: column; }
.citem { display: flex; align-items: center; gap: 11px; padding: 8px 0; border-radius: var(--radius-sm); }
.cbox { width: 18px; height: 18px; border-radius: 5px; border: 1.5px solid var(--border-strong); flex-shrink: 0; display: grid; place-items: center; background: #fff; }
.cbox.done { background: var(--green); border-color: var(--green); }
.cbox svg { width: 12px; height: 12px; color: #fff; opacity: 0; }
.cbox.done svg { opacity: 1; }
.citem .ctext { font-size: 13.5px; color: var(--text); white-space: nowrap; }
.citem.done .ctext { color: var(--text-3); text-decoration: line-through; }
/* nested subtasks (read-only) */
.task-group + .task-group { margin-top: 11px; padding-top: 11px; border-top: 1px solid var(--border); }
.citem.parent .ctext { font-weight: 600; }
.sub-count { margin-left: auto; font-size: 11px; font-weight: 600; color: var(--text-2); background: #f1f2f4; border: 1px solid var(--border); border-radius: 20px; padding: 1px 8px; line-height: 1.55; white-space: nowrap; }
.citem.parent.done .sub-count { color: var(--green); background: var(--green-weak); border-color: #cde8d8; }
.subtasks { margin-left: 29px; padding-left: 14px; border-left: 1.5px solid var(--border); display: flex; flex-direction: column; }
.subtask { display: flex; align-items: center; gap: 10px; padding: 6px 0; border-radius: var(--radius-sm); }
.cbox.sm { width: 16px; height: 16px; border-radius: 5px; }
.cbox.sm svg { width: 11px; height: 11px; }
.subtask .ctext { font-size: 13px; color: var(--text-2); white-space: nowrap; }
.subtask.done .ctext { color: var(--text-3); text-decoration: line-through; }
/* comments */
.comment { display: flex; gap: 11px; padding: 14px 0; border-top: 1px solid var(--border); }
.comment:first-of-type { border-top: none; }
.c-av { width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; font-size: 12px; font-weight: 700; color: #fff; flex-shrink: 0; }
.c-body { flex: 1; min-width: 0; }
.c-head { display: flex; align-items: center; gap: 8px; }
.c-name { font-size: 13.5px; font-weight: 600; white-space: nowrap; }
.c-role { font-size: 11px; font-weight: 600; color: var(--accent); background: var(--accent-weak); border-radius: 20px; padding: 1px 7px; white-space: nowrap; }
.c-time { font-size: 12px; color: var(--text-3); white-space: nowrap; }
.c-text { font-size: 13.5px; color: var(--text); line-height: 1.6; margin-top: 4px; }
.c-file { display: inline-flex; align-items: center; gap: 7px; margin-top: 8px; padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--radius); font-size: 12.5px; font-weight: 600; color: var(--text-2); }
.c-file .fi { width: 22px; height: 22px; border-radius: 5px; background: #e25950; color: #fff; display: grid; place-items: center; font-size: 8px; font-weight: 800; }
/* 답글 (대댓글) */
.c-actions { margin-top: 7px; }
.c-reply-btn { font-size: 12px; font-weight: 600; color: var(--text-3); background: none; border: none; cursor: pointer; padding: 2px 0; display: inline-flex; align-items: center; gap: 5px; font-family: inherit; white-space: nowrap; }
.c-reply-btn:hover { color: var(--accent); }
.c-reply-btn svg { width: 13px; height: 13px; }
.c-replies { margin-top: 13px; display: flex; flex-direction: column; gap: 14px; }
.c-reply { display: flex; gap: 9px; }
.c-reply .c-av { width: 24px; height: 24px; font-size: 10.5px; }
.reply-form { display: none; gap: 9px; margin-top: 12px; }
.reply-form.open { display: flex; }
.reply-form .c-av { width: 24px; height: 24px; font-size: 10.5px; }
.reply-form .field { flex: 1; }
.reply-form textarea { width: 100%; min-height: 44px; border: 1px solid var(--border-strong); border-radius: var(--radius); padding: 8px 10px; font-family: inherit; font-size: 13px; line-height: 1.55; resize: vertical; color: var(--text); }
.reply-form textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-weak); }
.reply-form textarea::placeholder { color: var(--text-3); }
.reply-form .crow { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
.btn.sm { height: 30px; padding: 0 12px; font-size: 12.5px; }
.btn.ghost { border-color: transparent; background: transparent; }
.btn.ghost:hover { background: #f1f2f4; }
.composer { display: flex; gap: 11px; margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--border); }
.composer .field { flex: 1; }
.composer textarea { width: 100%; min-height: 64px; border: 1px solid var(--border-strong); border-radius: var(--radius); padding: 10px 12px; font-family: inherit; font-size: 13.5px; resize: vertical; color: var(--text); }
.composer textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-weak); }
.composer textarea::placeholder { color: var(--text-3); }
.composer .crow { display: flex; justify-content: flex-end; margin-top: 9px; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; box-shadow: 0 1px 2px rgba(79,70,229,.4); }
.btn.primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
/* sidebar */
.side { display: flex; flex-direction: column; gap: 16px; }
.side-card { padding: 16px 18px 18px; }
.side-field + .side-field { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--border); }
.side-label { font-size: 12px; font-weight: 600; color: var(--text-3); margin-bottom: 9px; white-space: nowrap; }
.status-badge { display: inline-flex; align-items: center; gap: 8px; height: 30px; padding: 0 13px; border: 1px solid var(--blue-border); background: var(--blue-weak); border-radius: 20px; font-size: 13px; font-weight: 600; color: var(--blue); white-space: nowrap; }
.status-badge .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--blue); }
.status-badge.review { color: var(--amber); background: var(--amber-weak); border-color: var(--amber-border); }
.status-badge.review .dot { background: var(--amber); }
.assignees { display: flex; flex-direction: column; gap: 9px; }
.ass { display: flex; align-items: center; gap: 9px; }
.avatar { width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; font-size: 11px; font-weight: 700; color: #fff; flex-shrink: 0; }
.av-a { background: #e0518d; } .av-b { background: #3d8bf2; } .av-c { background: #16a37b; } .av-d { background: #b3631f; } .av-f { background: #d0982a; }
.ass .nm { font-size: 13px; font-weight: 600; white-space: nowrap; }
.ass .rl { font-size: 11.5px; color: var(--text-3); white-space: nowrap; }
.dl { display: flex; align-items: center; gap: 9px; font-size: 13.5px; font-weight: 600; color: var(--text); white-space: nowrap; }
.dl svg { width: 16px; height: 16px; color: var(--text-3); }
.dl .dday { font-size: 11.5px; font-weight: 700; color: var(--amber); background: #fdf4e3; border: 1px solid #f3e2bd; border-radius: 20px; padding: 1px 7px; margin-left: auto; white-space: nowrap; }
.files { display: flex; flex-direction: column; gap: 7px; }
.file { display: flex; align-items: center; gap: 10px; padding: 8px 9px; border: 1px solid var(--border); border-radius: var(--radius); }
.file-ico { width: 28px; height: 28px; border-radius: 6px; display: grid; place-items: center; flex-shrink: 0; font-size: 9px; font-weight: 800; color: #fff; }
.fi-img { background: #2aa775; } .fi-zip { background: #8a64d6; }
.file-info { min-width: 0; flex: 1; }
.file-name { font-size: 12.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; }
.file-size { font-size: 11.5px; color: var(--text-3); display: block; }
.issuer { display: flex; align-items: center; gap: 10px; }
.issuer .nm { font-size: 13px; font-weight: 600; white-space: nowrap; }
.issuer .rl { font-size: 11.5px; color: var(--text-3); white-space: nowrap; }
.meta-line { font-size: 12px; color: var(--text-3); margin-top: 4px; white-space: nowrap; }
/* ===== AI 터미널 에이전트 패널 ===== */
.btn.agent-open { background: var(--accent); border-color: var(--accent); color: #fff; box-shadow: 0 1px 2px rgba(79,70,229,.4); }
.btn.agent-open:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; }
.btn.agent-open svg { width: 15px; height: 15px; }
.agent-panel { position: fixed; top: 0; right: 0; bottom: 0; width: 440px; max-width: 92vw; z-index: 120; background: #0f1117; color: #e6e8ec; display: flex; flex-direction: column; border-left: 1px solid #262a33; box-shadow: -16px 0 48px rgba(0,0,0,.30); transform: translateX(100%); transition: transform .26s cubic-bezier(.4,0,.2,1); font-family: "Pretendard", system-ui, sans-serif; }
.agent-panel.open { transform: none; }
.ag-head { display: flex; align-items: center; gap: 11px; padding: 13px 14px; border-bottom: 1px solid #262a33; flex-shrink: 0; }
.ag-logo { width: 32px; height: 32px; border-radius: 8px; background: linear-gradient(135deg,#5b54f0,#4338ca); display: grid; place-items: center; color: #fff; flex-shrink: 0; }
.ag-logo svg { width: 17px; height: 17px; }
.ag-h-main { flex: 1; min-width: 0; }
.ag-name { font-size: 13.5px; font-weight: 700; display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.ag-status { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 600; color: #3ecf8e; }
.ag-status .dot { width: 6px; height: 6px; border-radius: 50%; background: #3ecf8e; box-shadow: 0 0 0 3px rgba(62,207,142,.18); }
.ag-ctx { font-size: 11px; color: #7b8190; margin-top: 3px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ag-hbtn { width: 30px; height: 30px; border: none; background: transparent; color: #9298a3; border-radius: 6px; display: grid; place-items: center; cursor: pointer; flex-shrink: 0; }
.ag-hbtn:hover { background: #1b1e26; color: #e6e8ec; }
.ag-hbtn svg { width: 16px; height: 16px; }
.ag-body { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 16px 14px 24px; display: flex; flex-direction: column; gap: 14px; }
.ag-body > * { flex-shrink: 0; }
.ag-sys { font-size: 11px; color: #6b7280; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; text-align: center; padding: 2px 0; }
.ag-sys b { color: #9298a3; font-weight: 600; }
.ag-msg { display: flex; gap: 10px; width: 100%; align-items: flex-start; }
.ag-msg .ava { width: 26px; height: 26px; flex: 0 0 26px; border-radius: 7px; display: grid; place-items: center; font-size: 11px; font-weight: 700; line-height: 1; overflow: hidden; }
.ag-msg.bot .ava { background: linear-gradient(135deg,#5b54f0,#4338ca); color: #fff; }
.ag-msg.bot .ava svg { width: 15px; height: 15px; }
.ag-msg .bubble { font-size: 13px; line-height: 1.62; max-width: 300px; min-width: 0; word-break: break-word; overflow-wrap: anywhere; }
.ag-msg.bot .bubble { background: #171a21; border: 1px solid #23262f; border-radius: 10px; padding: 9px 12px; color: #d4d8e0; }
.ag-msg.user { justify-content: flex-end; }
.ag-msg.user .ava { order: 2; background: #0ea5a3; color: #fff; border-radius: 50%; }
.ag-msg.user .bubble { order: 1; background: #4f46e5; color: #fff; border-radius: 10px; padding: 9px 12px; }
.ag-tool { border: 1px solid #23262f; border-radius: 9px; overflow: hidden; background: #0a0c11; margin-left: 36px; }
.ag-tool-head { display: flex; align-items: center; gap: 7px; padding: 6px 10px; background: #13161d; border-bottom: 1px solid #23262f; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; color: #7b8190; }
.ag-tool-head .tdot { width: 8px; height: 8px; border-radius: 50%; background: #3ecf8e; flex-shrink: 0; }
.ag-tool-head .cmd { color: #c7ccd6; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ag-tool-body { padding: 9px 11px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px; line-height: 1.75; color: #aab0bd; white-space: pre-wrap; }
.ag-tool-body .ok { color: #3ecf8e; }
.ag-tool-body .key { color: #7aa2f7; }
.ag-tool-body .warn { color: #e0af68; }
.ag-list { margin: 7px 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 7px; }
.ag-list li { display: flex; gap: 9px; font-size: 13px; line-height: 1.5; }
.ag-list .num { color: #7aa2f7; font-family: ui-monospace, monospace; font-weight: 700; flex-shrink: 0; }
/* 자동 생성 지시서 카드 */
.ag-draft { margin-left: 36px; border: 1px solid #2b2f3a; border-radius: 11px; overflow: hidden; background: #12151c; }
.ag-draft.created { opacity: .7; }
.ag-draft-top { padding: 11px 13px 12px; border-bottom: 1px solid #23262f; }
.ag-draft-badge { font-size: 10.5px; font-weight: 700; color: #7aa2f7; font-family: ui-monospace, monospace; letter-spacing: .3px; }
.ag-draft-title { font-size: 14px; font-weight: 700; color: #f0f1f4; margin-top: 7px; line-height: 1.4; }
.ag-draft-sec { padding: 11px 13px; border-bottom: 1px solid #23262f; }
.ag-draft-label { font-size: 10px; font-weight: 700; color: #6b7280; font-family: ui-monospace, monospace; letter-spacing: .5px; text-transform: uppercase; margin-bottom: 8px; }
.ag-draft-desc { font-size: 12.5px; line-height: 1.62; color: #c3c8d2; }
.ag-todos { display: flex; flex-direction: column; gap: 1px; }
.ag-todo { display: flex; align-items: flex-start; gap: 9px; padding: 7px 6px; border-radius: 7px; cursor: pointer; }
.ag-todo:hover { background: #171a21; }
.ag-todo .box { width: 17px; height: 17px; border-radius: 5px; border: 1.5px solid #3a3f4b; flex-shrink: 0; display: grid; place-items: center; margin-top: 1px; background: #0f1117; }
.ag-todo.sel .box { background: #4f46e5; border-color: #4f46e5; }
.ag-todo .box svg { width: 11px; height: 11px; color: #fff; opacity: 0; }
.ag-todo.sel .box svg { opacity: 1; }
.ag-todo .tt { font-size: 12.5px; line-height: 1.5; color: #969cab; }
.ag-todo.sel .tt { color: #e6e8ec; }
.ag-draft-count { font-size: 11px; color: #7b8190; padding: 10px 13px 0; font-family: ui-monospace, monospace; }
.ag-draft-count b { color: #c7ccd6; }
.ag-draft-foot { display: flex; gap: 8px; padding: 11px 13px 12px; }
.ag-draft-btn { height: 34px; border-radius: 8px; font-size: 12.5px; font-weight: 700; cursor: pointer; border: 1px solid #2b2f3a; background: #1b1e26; color: #aab0bd; display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 0 12px; white-space: nowrap; }
.ag-draft-btn:hover { color: #fff; border-color: #3a3f4b; }
.ag-draft-btn.primary { flex: 1; background: #4f46e5; border-color: #4f46e5; color: #fff; }
.ag-draft-btn.primary:hover { background: #4338ca; }
.ag-draft-btn.primary:disabled { background: #2b2f3a; border-color: #2b2f3a; color: #6b7280; cursor: not-allowed; }
.ag-draft-btn svg { width: 14px; height: 14px; display: block; flex-shrink: 0; position: relative; top: 1.5px; }
.ag-draft-done { display: flex; align-items: center; gap: 7px; padding: 11px 13px 12px; font-size: 12px; font-weight: 600; color: #3ecf8e; font-family: ui-monospace, monospace; }
.ag-draft-done svg { width: 14px; height: 14px; }
/* 구현 검토 리포트 카드 */
.ag-review { margin-left: 36px; border: 1px solid #2b2f3a; border-radius: 11px; overflow: hidden; background: #12151c; }
.ag-review-top { padding: 11px 13px 12px; border-bottom: 1px solid #23262f; }
.ag-review-badge { font-size: 10.5px; font-weight: 700; color: #7aa2f7; font-family: ui-monospace, monospace; letter-spacing: .3px; }
.ag-review-title { font-size: 13.5px; font-weight: 700; color: #f0f1f4; margin-top: 7px; line-height: 1.4; }
.ag-rv { display: flex; gap: 10px; padding: 10px 13px; border-bottom: 1px solid #1c1f27; align-items: flex-start; }
.ag-rv:last-of-type { border-bottom: none; }
.rv-ico { width: 20px; height: 20px; border-radius: 50%; flex-shrink: 0; display: grid; place-items: center; margin-top: 1px; }
.rv-ico svg { width: 12px; height: 12px; }
.ag-rv.ok .rv-ico { background: rgba(62,207,142,.15); color: #3ecf8e; }
.ag-rv.warn .rv-ico { background: rgba(224,175,104,.15); color: #e0af68; }
.ag-rv.miss .rv-ico { background: rgba(247,118,142,.15); color: #f7768e; }
.rv-main { flex: 1; min-width: 0; }
.rv-text { font-size: 12.5px; font-weight: 600; color: #d4d8e0; line-height: 1.4; }
.rv-note { font-size: 11px; color: #7b8190; margin-top: 3px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; line-height: 1.5; }
.rv-tag { font-size: 10px; font-weight: 700; padding: 2px 7px; border-radius: 20px; flex-shrink: 0; white-space: nowrap; font-family: ui-monospace, monospace; margin-top: 1px; }
.ag-rv.ok .rv-tag { color: #3ecf8e; background: rgba(62,207,142,.12); }
.ag-rv.warn .rv-tag { color: #e0af68; background: rgba(224,175,104,.12); }
.ag-rv.miss .rv-tag { color: #f7768e; background: rgba(247,118,142,.12); }
.ag-review-sum { display: flex; align-items: center; gap: 7px; padding: 10px 13px; background: #14171f; border-top: 1px solid #23262f; font-size: 11.5px; color: #aab0bd; font-family: ui-monospace, monospace; }
.ag-review-sum b.g { color: #3ecf8e; } .ag-review-sum b.a { color: #e0af68; } .ag-review-sum b.r { color: #f7768e; }
.ag-review-foot { display: flex; gap: 8px; padding: 11px 13px 12px; }
.ag-foot { border-top: 1px solid #262a33; padding: 11px 14px 12px; flex-shrink: 0; }
.ag-quick { display: flex; gap: 6px; margin-bottom: 9px; flex-wrap: wrap; }
.ag-chip { font-size: 11.5px; font-weight: 600; color: #aab0bd; background: #171a21; border: 1px solid #262a33; border-radius: 20px; padding: 4px 10px; cursor: pointer; font-family: ui-monospace, monospace; }
.ag-chip:hover { border-color: #4f46e5; color: #fff; }
.ag-inputrow { display: flex; align-items: center; gap: 8px; background: #171a21; border: 1px solid #2b2f3a; border-radius: 10px; padding: 7px 7px 7px 12px; }
.ag-inputrow:focus-within { border-color: #4f46e5; }
.ag-input { flex: 1; background: transparent; border: none; outline: none; resize: none; color: #e6e8ec; font-family: inherit; font-size: 13px; line-height: 1.5; max-height: 100px; padding: 4px 0; }
.ag-input::placeholder { color: #5b626e; }
.ag-send { width: 32px; height: 32px; border: none; border-radius: 8px; background: #4f46e5; color: #fff; display: grid; place-items: center; cursor: pointer; flex-shrink: 0; }
.ag-send:hover { background: #4338ca; }
.ag-send svg { width: 16px; height: 16px; }
.ag-hint { font-size: 10.5px; color: #5b626e; margin-top: 8px; text-align: center; font-family: ui-monospace, monospace; }
</style>
</head>
<body>
<header class="topbar">
<div class="brand"><div class="logo">R</div>Relay</div>
<nav class="topnav">
<a href="내 업무.html">내 업무</a>
<a href="저장소 목록.html" class="active">저장소</a>
</nav>
<div class="topbar-right">
<button class="icon-btn agent" id="agentOpen" type="button" title="Relay 에이전트"><svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg></button>
<button class="icon-btn" title="검색"><svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="m21 21-4-4"/></svg></button>
<button class="icon-btn" title="알림"><svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></svg></button>
<div class="me"></div>
</div>
</header>
<div class="page" data-screen-label="업무 상세">
<div class="crumb">
<a href="저장소 목록.html" class="lnk">저장소</a>
<span class="sep">/</span>
<a href="저장소 상세.html" class="lnk">3분기 신제품 런칭 캠페인</a>
<span class="sep">/</span>
<a href="저장소 상세.html" class="lnk">업무</a>
<span class="sep">/</span>
<b>#9</b>
</div>
<div class="pagehead">
<div class="ph-main">
<div class="ph-titlerow">
<span class="st-badge review">승인 대기</span>
<span class="ph-tid">#9</span>
</div>
<h1 class="ph-title">메인 배너 이미지 2종 (가로/세로) 디자인</h1>
</div>
<div class="actions">
<a class="btn" href="업무 작성.html"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>수정</a>
<div class="more-wrap">
<button class="btn icon" id="moreBtn" type="button" title="더보기"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="5" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="12" cy="19" r="1.5"/></svg></button>
<div class="menu" id="moreMenu">
<button class="menu-item" type="button">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
업무 복제
</button>
<button class="menu-item" type="button">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-1 1"/><path d="M14 11a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l1-1"/></svg>
링크 복사
</button>
<div class="menu-sep"></div>
<button class="menu-item danger" id="deleteOpen" type="button">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6M14 11v6"/></svg>
업무 삭제
</button>
</div>
</div>
</div>
</div>
<div class="layout">
<!-- main -->
<section class="card main-card">
<div class="sect">
<div class="sect-label">업무 내용</div>
<div class="content">
<p>9월 신제품 런칭 캠페인에 사용할 메인 배너를 가로형/세로형 2종으로 제작합니다. 톤앤매너는 <span class="mention">@브랜드_가이드라인.pdf</span> 기준을 따라주세요.</p>
<p>퍼포먼스 광고와 자사몰 상단에 동시 노출되므로, 두 비율 모두 핵심 메시지("민감 피부 저자극")가 명확히 보이도록 구성해주세요. 1차 시안 확정 후 모바일 적응형까지 진행합니다.</p>
</div>
</div>
<div class="sect">
<div class="sect-label">해야 할 일
<span class="pr"><span class="progress-bar"><i style="width:33%"></i></span><span class="progress-txt">1 / 3 완료</span></span>
</div>
<div class="checklist">
<div class="citem done">
<span class="cbox done"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span>
<span class="ctext">가로형 메인 배너 1920×1080 디자인</span>
</div>
<div class="citem">
<span class="cbox"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span>
<span class="ctext">세로형 메인 배너 1080×1920 디자인</span>
</div>
<div class="citem">
<span class="cbox"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span>
<span class="ctext">모바일 적응형 600×600 제작</span>
</div>
</div>
</div>
<div class="sect">
<div class="thread-tabs" id="threadTabs">
<button class="thread-tab active" data-tab="comments" type="button">댓글 <span class="tt-count">3</span></button>
<button class="thread-tab" data-tab="activity" type="button">활동 <span class="tt-count">6</span></button>
</div>
<div class="thread-panel" data-panel="comments">
<div class="comment">
<span class="c-av av-f"></span>
<div class="c-body">
<div class="c-head"><span class="c-name">정태경</span><span class="c-role">지시자</span><span class="c-time">2일 전</span></div>
<div class="c-text">가로형부터 확정하고 세로형 진행해주세요. 카피 위치는 좌측 정렬 기준입니다.</div>
<div class="c-replies">
<div class="c-reply">
<span class="c-av av-b"></span>
<div class="c-body">
<div class="c-head"><span class="c-name">박지훈</span><span class="c-time">2일 전</span></div>
<div class="c-text">네, 가로형 정렬 기준으로 먼저 잡겠습니다.</div>
</div>
</div>
</div>
<div class="c-actions"><button class="c-reply-btn" type="button"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 17 4 12 9 7"/><path d="M20 18v-2a4 4 0 0 0-4-4H4"/></svg>답글</button></div>
<div class="reply-form">
<span class="c-av" style="background:#0ea5a3"></span>
<div class="field">
<textarea placeholder="답글을 입력하세요…"></textarea>
<div class="crow"><button class="btn ghost sm reply-cancel" type="button">취소</button><button class="btn primary sm reply-submit" type="button">답글 등록</button></div>
</div>
</div>
</div>
</div>
<div class="comment">
<span class="c-av av-b"></span>
<div class="c-body">
<div class="c-head"><span class="c-name">박지훈</span><span class="c-time">1일 전</span></div>
<div class="c-text">가로형 1차 시안 업로드했습니다. 검토 부탁드려요.</div>
<div class="c-file"><span class="fi">IMG</span>main_banner_h_v1.png</div>
<div class="c-replies"></div>
<div class="c-actions"><button class="c-reply-btn" type="button"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 17 4 12 9 7"/><path d="M20 18v-2a4 4 0 0 0-4-4H4"/></svg>답글</button></div>
<div class="reply-form">
<span class="c-av" style="background:#0ea5a3"></span>
<div class="field">
<textarea placeholder="답글을 입력하세요…"></textarea>
<div class="crow"><button class="btn ghost sm reply-cancel" type="button">취소</button><button class="btn primary sm reply-submit" type="button">답글 등록</button></div>
</div>
</div>
</div>
</div>
<div class="comment">
<span class="c-av av-d"></span>
<div class="c-body">
<div class="c-head"><span class="c-name">최유진</span><span class="c-time">3시간 전</span></div>
<div class="c-text">세로형은 내일 오전까지 공유하겠습니다.</div>
<div class="c-replies"></div>
<div class="c-actions"><button class="c-reply-btn" type="button"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 17 4 12 9 7"/><path d="M20 18v-2a4 4 0 0 0-4-4H4"/></svg>답글</button></div>
<div class="reply-form">
<span class="c-av" style="background:#0ea5a3"></span>
<div class="field">
<textarea placeholder="답글을 입력하세요…"></textarea>
<div class="crow"><button class="btn ghost sm reply-cancel" type="button">취소</button><button class="btn primary sm reply-submit" type="button">답글 등록</button></div>
</div>
</div>
</div>
</div>
<div class="composer">
<span class="c-av" style="background:#0ea5a3"></span>
<div class="field">
<textarea placeholder="댓글을 입력하세요…"></textarea>
<div class="crow"><button class="btn primary" type="button">댓글 등록</button></div>
</div>
</div>
</div><!-- /comments panel -->
<div class="thread-panel" data-panel="activity" hidden>
<div class="activity">
<div class="act">
<span class="act-ico amber"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M9 12l2 2 4-4"/></svg></span>
<div class="act-body">
<div class="act-text"><b>박지훈</b>님이 승인을 요청했습니다</div>
<div class="act-chips"><span class="act-chip from">진행 중</span><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg><span class="act-chip to">승인 대기</span></div>
<div class="act-time">2시간 전 · 오후 3:24</div>
</div>
</div>
<div class="act">
<span class="act-ico green"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span>
<div class="act-body">
<div class="act-text"><b>박지훈</b>님이 <b>가로형 메인 배너 1920×1080 디자인</b> 항목을 완료했습니다</div>
<div class="act-time">1일 전 · 오후 6:10</div>
</div>
</div>
<div class="act">
<span class="act-ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg></span>
<div class="act-body">
<div class="act-text"><b>박지훈</b>님이 파일을 첨부했습니다</div>
<div class="act-file"><span class="fi">IMG</span>main_banner_h_v1.png</div>
<div class="act-time">1일 전 · 오후 6:08</div>
</div>
</div>
<div class="act">
<span class="act-ico blue"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/></svg></span>
<div class="act-body">
<div class="act-text"><b>정태경</b>님이 마감기한을 <b>6월 18일 (목)</b>로 설정했습니다</div>
<div class="act-time">6월 8일 · 오전 10:32</div>
</div>
</div>
<div class="act">
<span class="act-ico blue"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75"/></svg></span>
<div class="act-body">
<div class="act-text"><b>정태경</b>님이 <b>박지훈</b>, <b>최유진</b>님을 담당자로 지정했습니다</div>
<div class="act-time">6월 8일 · 오전 10:31</div>
</div>
</div>
<div class="act">
<span class="act-ico accent"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"/><line x1="4" y1="22" x2="4" y2="15"/></svg></span>
<div class="act-body">
<div class="act-text"><b>정태경</b>님이 업무를 생성했습니다</div>
<div class="act-time">6월 8일 · 오전 10:30</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- sidebar -->
<aside class="side">
<!-- 승인 대기: 지시자(정태경) 시점 결정 카드 -->
<div class="card ap-card review">
<div class="ap-card-head">
<span class="ap-card-ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 8v4l3 2"/><circle cx="12" cy="12" r="9"/></svg></span>
<span class="ap-card-title">승인 요청 도착</span>
</div>
<div class="ap-card-meta"><b>박지훈</b>님이 작업 완료 후 승인을 요청했습니다 · 2시간 전</div>
<div class="ap-card-note">가로형/세로형 메인 배너 1차 제작을 완료했습니다. 모바일 적응형은 컨펌 후 진행 예정이며, 우선 두 비율 검토 부탁드립니다.</div>
<div class="ap-card-actions">
<button class="ap-btn approve" id="approveOpen" type="button"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>승인하기</button>
<button class="ap-btn reject" id="changesOpen" type="button"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 7v6h6"/><path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"/></svg>수정 요청</button>
</div>
</div>
<div class="card side-card">
<div class="side-field">
<div class="side-label">상태</div>
<span class="status-badge review"><span class="dot"></span>승인 대기</span>
</div>
<div class="side-field">
<div class="side-label">담당자 · 2명</div>
<div class="assignees">
<div class="ass"><span class="avatar av-b"></span><span><div class="nm">박지훈</div><div class="rl">퍼포먼스 마케팅</div></span></div>
<div class="ass"><span class="avatar av-d"></span><span><div class="nm">최유진</div><div class="rl">UX 디자인</div></span></div>
</div>
</div>
<div class="side-field">
<div class="side-label">마감기한</div>
<div class="dl">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/></svg>
6월 18일 (목)
<span class="dday">D-3</span>
</div>
</div>
</div>
<div class="card side-card">
<div class="side-field">
<div class="side-label">첨부파일 · 2개</div>
<div class="files">
<div class="file"><span class="file-ico fi-img">IMG</span><span class="file-info"><span class="file-name">레퍼런스_무드보드.png</span><span class="file-size">3.2 MB</span></span></div>
<div class="file"><span class="file-ico fi-zip">ZIP</span><span class="file-info"><span class="file-name">배너_소스_파일.zip</span><span class="file-size">18.4 MB</span></span></div>
</div>
</div>
</div>
<div class="card side-card">
<div class="side-field">
<div class="side-label">지시자</div>
<div class="issuer"><span class="avatar av-f"></span><span><div class="nm">정태경</div><div class="rl">마케팅 그룹 리드</div></span></div>
<div class="meta-line">6월 8일 지시 · #9</div>
</div>
</div>
</aside>
</div>
</div>
<!-- 삭제 확인 모달 -->
<div class="modal-backdrop" id="deleteModal">
<div class="modal" role="dialog" aria-modal="true">
<div class="modal-body">
<div class="modal-ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6M14 11v6"/></svg></div>
<h2 class="modal-title">업무를 삭제할까요?</h2>
<p class="modal-desc"><b>#9 메인 배너 이미지 2종 (가로/세로) 디자인</b> 업무와 체크리스트·댓글·첨부파일이 영구적으로 삭제됩니다. 이 작업은 되돌릴 수 없습니다.</p>
</div>
<div class="modal-foot">
<button class="mbtn" id="deleteCancel" type="button">취소</button>
<button class="mbtn danger" type="button">삭제</button>
</div>
</div>
</div>
<!-- 승인 확인 모달 -->
<div class="modal-backdrop" id="approveModal">
<div class="modal" role="dialog" aria-modal="true">
<div class="modal-body">
<div class="modal-ico" style="background:var(--green-weak);color:var(--green)"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><path d="M22 4 12 14.01l-3-3"/></svg></div>
<h2 class="modal-title">이 업무를 승인할까요?</h2>
<p class="modal-desc"><b>박지훈</b>님의 검토 요청을 승인합니다. 업무 상태가 <b>완료</b>로 변경되고 담당자에게 알림이 전송됩니다.</p>
</div>
<div class="modal-foot">
<button class="mbtn" data-close="approveModal" type="button">취소</button>
<button class="mbtn approve" type="button">승인</button>
</div>
</div>
</div>
<!-- 수정 요청(반려) 모달 -->
<div class="modal-backdrop" id="changesModal">
<div class="modal" role="dialog" aria-modal="true">
<div class="modal-body" style="text-align:left;padding:22px 24px 8px">
<h2 class="modal-title">수정 요청</h2>
<p class="modal-desc" style="margin:8px 0 14px">보완이 필요한 내용을 적어주세요. 담당자에게 전달되며 업무가 다시 <b>진행 중</b>으로 돌아갑니다.</p>
<textarea class="modal-textarea" placeholder="예) 세로형 카피 가독성이 낮으니 자간과 대비를 조정해주세요."></textarea>
</div>
<div class="modal-foot">
<button class="mbtn" data-close="changesModal" type="button">취소</button>
<button class="mbtn danger" type="button">수정 요청 보내기</button>
</div>
</div>
</div>
<script>
/* 댓글 / 활동 탭 전환 */
(function () {
var tabs = document.getElementById('threadTabs');
if (!tabs) return;
var btns = tabs.querySelectorAll('.thread-tab');
var panels = document.querySelectorAll('.thread-panel');
btns.forEach(function (b) {
b.addEventListener('click', function () {
btns.forEach(function (x) { x.classList.remove('active'); });
b.classList.add('active');
var name = b.getAttribute('data-tab');
panels.forEach(function (p) { p.hidden = p.getAttribute('data-panel') !== name; });
});
});
})();
</script>
<script>
/* 댓글 답글 */
(function () {
document.querySelectorAll('.comment > .c-body').forEach(function (cb) {
var btn = cb.querySelector(':scope > .c-actions > .c-reply-btn');
var form = cb.querySelector(':scope > .reply-form');
var replies = cb.querySelector(':scope > .c-replies');
if (!btn || !form) return;
var ta = form.querySelector('textarea');
btn.addEventListener('click', function () {
form.classList.toggle('open');
if (form.classList.contains('open')) ta.focus();
});
form.querySelector('.reply-cancel').addEventListener('click', function () {
form.classList.remove('open'); ta.value = '';
});
form.querySelector('.reply-submit').addEventListener('click', function () {
var text = ta.value.trim(); if (!text) return;
var el = document.createElement('div');
el.className = 'c-reply';
el.innerHTML = '<span class="c-av" style="background:#0ea5a3">정</span>'
+ '<div class="c-body"><div class="c-head"><span class="c-name">정태경</span><span class="c-role">지시자</span><span class="c-time">방금</span></div>'
+ '<div class="c-text"></div></div>';
el.querySelector('.c-text').textContent = text;
replies.appendChild(el);
ta.value = ''; form.classList.remove('open');
});
});
})();
</script>
<script>
moreBtn.addEventListener('click', function (e) { e.stopPropagation(); moreMenu.classList.toggle('open'); });
document.addEventListener('click', function () { moreMenu.classList.remove('open'); });
moreMenu.addEventListener('click', function (e) { e.stopPropagation(); });
/* 삭제 모달 */
var dModal = document.getElementById('deleteModal');
document.getElementById('deleteOpen').addEventListener('click', function () { moreMenu.classList.remove('open'); dModal.classList.add('open'); });
document.getElementById('deleteCancel').addEventListener('click', function () { dModal.classList.remove('open'); });
dModal.addEventListener('click', function (e) { if (e.target === dModal) dModal.classList.remove('open'); });
document.addEventListener('keydown', function (e) { if (e.key === 'Escape') dModal.classList.remove('open'); });
/* 승인 / 수정 요청 모달 */
function openModal(id) { document.getElementById(id).classList.add('open'); }
function closeModal(el) { el.classList.remove('open'); }
document.getElementById('approveOpen').addEventListener('click', function () { openModal('approveModal'); });
document.getElementById('changesOpen').addEventListener('click', function () { openModal('changesModal'); });
document.querySelectorAll('[data-close]').forEach(function (b) {
b.addEventListener('click', function () { closeModal(document.getElementById(b.getAttribute('data-close'))); });
});
['approveModal', 'changesModal'].forEach(function (id) {
var m = document.getElementById(id);
m.addEventListener('click', function (e) { if (e.target === m) closeModal(m); });
});
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape') { closeModal(document.getElementById('approveModal')); closeModal(document.getElementById('changesModal')); }
});
</script>
<!-- ===== AI 터미널 에이전트 패널 ===== -->
<aside class="agent-panel" id="agentPanel">
<div class="ag-head">
<div class="ag-logo"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg></div>
<div class="ag-h-main">
<div class="ag-name">Relay 에이전트 <span class="ag-status"><span class="dot"></span>온라인</span></div>
<div class="ag-ctx">repo: q3-launch-campaign · 지시서 작성</div>
</div>
<button class="ag-hbtn" id="agentReset" type="button" title="새 세션"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-3-6.7"/><path d="M21 4v5h-5"/></svg></button>
<button class="ag-hbtn" id="agentClose" type="button" title="닫기"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18M6 6l12 12"/></svg></button>
</div>
<div class="ag-body" id="agBody">
<div class="ag-sys"><b>업무 지시서 작성 모드</b></div>
<div class="ag-msg bot">
<span class="ava"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg></span>
<span class="bubble">지시할 업무를 자연어로 설명하거나 <b>/새지시</b> 명령으로 시작하세요. 제가 <b>업무 내용</b><b>해야 할 일</b>을 자동으로 구성해 드립니다.</span>
</div>
<div class="ag-msg user">
<span class="ava"></span>
<span class="bubble">/새지시 9월 신제품 출시용 인스타그램 릴스 3편 제작</span>
</div>
<div class="ag-tool">
<div class="ag-tool-head"><span class="tdot"></span><span class="cmd">$ relay order draft --analyze</span></div>
<div class="ag-tool-body">분석 완료 <span class="ok"></span>
<span class="key">유형</span> 콘텐츠 제작 · 영상
<span class="key">플랫폼</span> Instagram Reels
<span class="key">수량</span> 3편
<span class="key">저장소</span> q3-launch-campaign</div>
</div>
<div class="ag-msg bot">
<span class="ava"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg></span>
<span class="bubble">이렇게 이해했어요. 이 방향이 맞나요? 맞으면 <b>진행</b>이라고 알려주시고, 담당자나 마감을 함께 지정해 주셔도 좋아요.</span>
</div>
<div class="ag-msg user">
<span class="ava"></span>
<span class="bubble">맞아. 담당자는 정민호, 마감은 6월 30일로 진행해줘</span>
</div>
<div class="ag-msg bot">
<span class="ava"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg></span>
<span class="bubble">업무 내용과 해야 할 일을 자동으로 구성했어요. 포함할 항목을 선택한 뒤 지시서를 만드세요.</span>
</div>
<div class="ag-draft">
<div class="ag-draft-top">
<div class="ag-draft-badge">⌁ 자동 생성된 지시서 초안</div>
<div class="ag-draft-title">9월 신제품 출시 인스타그램 릴스 3편 제작</div>
</div>
<div class="ag-draft-sec">
<div class="ag-draft-label">업무 내용</div>
<div class="ag-draft-desc">9월 신제품 출시를 알리기 위한 인스타그램 릴스 3편을 제작합니다. 숏폼 포맷으로 핵심 메시지를 빠르게 전달하고, 브랜드 가이드라인의 톤앤매너를 유지합니다. 1차 기획안 확정 후 촬영·편집을 진행합니다.</div>
</div>
<div class="ag-draft-sec">
<div class="ag-draft-label">해야 할 일 · 선택</div>
<div class="ag-todos">
<div class="ag-todo sel"><span class="box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span><span class="tt">릴스 3편 기획안 및 스토리보드 작성</span></div>
<div class="ag-todo sel"><span class="box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span><span class="tt">촬영 콘티 확정 및 촬영 소스 준비</span></div>
<div class="ag-todo sel"><span class="box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span><span class="tt">영상 편집 및 자막 작업 (3편)</span></div>
<div class="ag-todo sel"><span class="box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span><span class="tt">브랜드 가이드라인 톤앤매너 검수</span></div>
<div class="ag-todo sel"><span class="box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></span><span class="tt">업로드 일정 확정 및 예약 발행</span></div>
</div>
</div>
<div class="ag-draft-count">선택 <b class="sel-n">5</b> / 5 · 담당 정민호 · 마감 6월 30일</div>
<div class="ag-draft-foot">
<button class="ag-draft-btn regen" type="button">다시 생성</button>
<button class="ag-draft-btn primary create" type="button">지시서 만들기</button>
</div>
</div>
</div>
<div class="ag-foot">
<div class="ag-quick">
<button class="ag-chip" type="button">/새지시</button>
<button class="ag-chip" type="button">/검토요청</button>
</div>
<div class="ag-inputrow">
<textarea class="ag-input" id="agInput" rows="1" placeholder="지시할 업무를 설명하거나 /새지시 …"></textarea>
<button class="ag-send" id="agSend" type="button" title="전송"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="m22 2-7 20-4-9-9-4Z"/><path d="M22 2 11 13"/></svg></button>
</div>
<div class="ag-hint">/새지시 [업무 설명] 입력 · Enter 전송</div>
</div>
</aside>
<script>
(function () {
var panel = document.getElementById('agentPanel');
var body = document.getElementById('agBody');
var input = document.getElementById('agInput');
document.getElementById('agentOpen').addEventListener('click', function () { panel.classList.add('open'); input.focus(); });
document.getElementById('agentClose').addEventListener('click', function () { panel.classList.remove('open'); });
document.addEventListener('keydown', function (e) { if (e.key === 'Escape') panel.classList.remove('open'); });
function esc(s) { return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); }
function scrollDown() { body.scrollTop = body.scrollHeight; }
var BOT = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg>';
var CHK = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>';
var NL = String.fromCharCode(10);
function addUser(text) {
var el = document.createElement('div');
el.className = 'ag-msg user';
el.innerHTML = '<span class="ava">정</span><span class="bubble">' + esc(text) + '</span>';
body.appendChild(el); scrollDown();
}
function addBot(text) {
var el = document.createElement('div');
el.className = 'ag-msg bot';
el.innerHTML = '<span class="ava">' + BOT + '</span><span class="bubble">' + text + '</span>';
body.appendChild(el); scrollDown();
}
function addTool(cmd, lines) {
var el = document.createElement('div');
el.className = 'ag-tool';
el.innerHTML = '<div class="ag-tool-head"><span class="tdot"></span><span class="cmd">' + esc(cmd) + '</span></div><div class="ag-tool-body">' + lines + '</div>';
body.appendChild(el); scrollDown();
}
function buildDraft(title) {
var list = [title + ' 기획안 및 범위 정리', '초안 제작 및 1차 작업', '중간 점검 및 피드백 반영', '브랜드 가이드라인 검수', '최종 산출물 공유 및 일정 확정'];
var items = list.map(function (t) { return '<div class="ag-todo sel"><span class="box">' + CHK + '</span><span class="tt">' + esc(t) + '</span></div>'; }).join('');
var el = document.createElement('div');
el.className = 'ag-draft';
el.innerHTML =
'<div class="ag-draft-top"><div class="ag-draft-badge">⌁ 자동 생성된 지시서 초안</div><div class="ag-draft-title">' + esc(title) + '</div></div>' +
'<div class="ag-draft-sec"><div class="ag-draft-label">업무 내용</div><div class="ag-draft-desc">“' + esc(title) + '” 업무를 진행합니다. 핵심 목표를 정의하고 단계별로 산출물을 완성하며, 브랜드 가이드라인과 일정에 맞춰 마무리합니다.</div></div>' +
'<div class="ag-draft-sec"><div class="ag-draft-label">해야 할 일 · 선택</div><div class="ag-todos">' + items + '</div></div>' +
'<div class="ag-draft-count">선택 <b class="sel-n">5</b> / 5</div>' +
'<div class="ag-draft-foot"><button class="ag-draft-btn regen" type="button">다시 생성</button><button class="ag-draft-btn primary create" type="button">지시서 만들기</button></div>';
body.appendChild(el); scrollDown();
}
function recount(card) {
if (!card) return;
var n = card.querySelectorAll('.ag-todo.sel').length;
var a = card.querySelector('.sel-n'); if (a) a.textContent = n;
var b2 = card.querySelector('.cnt'); if (b2) b2.textContent = n;
var btn = card.querySelector('.create'); if (btn) btn.disabled = (n === 0);
}
var orderSeq = 17;
function createOrder(card) {
if (!card || card.classList.contains('created')) return;
var n = card.querySelectorAll('.ag-todo.sel').length; if (n === 0) return;
card.classList.add('created');
var foot = card.querySelector('.ag-draft-foot'); if (foot) foot.outerHTML = '<div class="ag-draft-done">' + CHK + ' 지시서로 생성됨</div>';
var id = orderSeq++;
addTool('$ relay order create', '<span class="ok">✓ 지시서 생성됨</span> #' + id + NL + '<span class="key">저장소</span> q3-launch-campaign' + NL + '<span class="key">담당</span> 정민호' + NL + '<span class="key">항목</span> ' + n + '개' + NL + '<span class="key">알림</span> 전송 ✓');
addBot('지시서 <b>#' + id + '</b>이(가) 생성되어 담당자에게 전달됐어요. 업무 화면에서 확인할 수 있어요.');
}
function runReview() {
setTimeout(function () {
addTool('$ relay review --task #9 --scan', 'checklist 항목 3개 로드 ✓' + NL + 'repo 스캔 중… q3-launch-campaign@main' + NL + 'matched <span class="ok">banners/main_h_1920x1080.png</span>' + NL + 'matched <span class="warn">banners/main_v_1080x1920.png</span>' + NL + 'missing <span class="key">mobile/adaptive_600.*</span>');
addBot('해야 할 일 3개를 실제 산출물과 대조해 검토했어요. 결과는 아래와 같아요.');
buildReview();
}, 520);
}
function buildReview() {
var rows = [
{ st: 'ok', t: '가로형 메인 배너 1920×1080 디자인', n: 'banners/main_h_1920x1080.png · 규격·세이프영역 확인', tag: '구현 확인' },
{ st: 'warn', t: '세로형 메인 배너 1080×1920 디자인', n: '파일은 있으나 카피 세이프영역 미반영 · 보완 권장', tag: '부분 구현' },
{ st: 'miss', t: '모바일 적응형 600×600 제작', n: 'mobile/adaptive_600 산출물을 찾지 못했어요', tag: '누락' }
];
var ICO = {
ok: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>',
warn: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"><path d="M12 9v4M12 17h.01M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/></svg>',
miss: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18M6 6l12 12"/></svg>'
};
var items = rows.map(function (r) {
return '<div class="ag-rv ' + r.st + '"><span class="rv-ico">' + ICO[r.st] + '</span><span class="rv-main"><span class="rv-text">' + r.t + '</span><span class="rv-note">' + r.n + '</span></span><span class="rv-tag">' + r.tag + '</span></div>';
}).join('');
var el = document.createElement('div');
el.className = 'ag-review';
el.innerHTML =
'<div class="ag-review-top"><div class="ag-review-badge">⌁ 구현 검토 리포트</div><div class="ag-review-title">메인 배너 이미지 2종 디자인 · #9</div></div>' +
items +
'<div class="ag-review-sum">항목 3개 · <b class="g">확인 1</b> · <b class="a">보완 1</b> · <b class="r">누락 1</b></div>' +
'<div class="ag-review-foot"><button class="ag-draft-btn rv-comment" type="button">보완 항목 댓글로 추가</button><button class="ag-draft-btn primary rv-request" type="button">승인 요청 보내기</button></div>';
body.appendChild(el); scrollDown();
}
function send() {
var text = input.value.trim(); if (!text) return;
addUser(text); input.value = ''; input.style.height = 'auto';
var m = text.match(/^\/(새지시|지시)\s+(.+)/);
if (/^\/(검토요청|검토|review)/.test(text)) {
runReview();
} else if (m) {
var req = m[2].trim();
setTimeout(function () {
addTool('$ relay order draft --analyze', '분석 완료 <span class="ok">✓</span>' + NL + '<span class="key">요청</span> ' + esc(req) + NL + '<span class="key">저장소</span> q3-launch-campaign');
addBot('요청을 바탕으로 지시서 초안을 구성했어요. 포함할 항목을 선택한 뒤 지시서를 만드세요.');
buildDraft(req);
}, 480);
} else {
setTimeout(function () {
addBot('<b>/새지시 [업무 설명]</b> 형식으로 입력하시면 업무 내용과 해야 할 일을 자동으로 구성해 드려요. 예: <span style="color:#7aa2f7">/새지시 랜딩페이지 리뉴얼</span>');
}, 430);
}
}
body.addEventListener('click', function (e) {
var todo = e.target.closest('.ag-todo');
if (todo && !todo.closest('.created')) { todo.classList.toggle('sel'); recount(todo.closest('.ag-draft')); return; }
var create = e.target.closest('.create');
if (create) { createOrder(create.closest('.ag-draft')); return; }
var regen = e.target.closest('.regen');
if (regen) { addBot('초안을 다시 구성할게요. 항목을 조정하거나 다른 설명을 입력해 주세요.'); return; }
var rvc = e.target.closest('.rv-comment');
if (rvc) { addBot('보완이 필요한 <b>2개 항목</b>(세로형 세이프영역, 모바일 적응형)을 업무 댓글로 정리해 남겼어요.'); return; }
var rvr = e.target.closest('.rv-request');
if (rvr) {
var card = rvr.closest('.ag-review');
rvr.disabled = true; rvr.textContent = '요청 전송됨';
addTool('$ relay review --submit #9', '<span class="warn">⚠ 누락 1 · 보완 1</span> 포함하여 요청' + NL + '<span class="ok">✓ 승인 요청 전송됨</span> → 정태경(지시자)');
addBot('검토 결과를 포함해 승인을 요청했어요. 지시자가 리포트를 함께 확인합니다.');
return;
}
});
document.getElementById('agSend').addEventListener('click', send);
input.addEventListener('keydown', function (e) { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } });
input.addEventListener('input', function () { this.style.height = 'auto'; this.style.height = Math.min(this.scrollHeight, 100) + 'px'; });
document.querySelectorAll('.ag-chip').forEach(function (c) {
c.addEventListener('click', function () {
var t = c.textContent.trim();
if (t === '/새지시') { input.value = '/새지시 '; input.focus(); }
else if (t === '/검토요청') { runReview(); }
else { addBot('<b>/새지시 [업무 설명]</b>은 지시서 초안을, <b>/검토요청</b>은 해야 할 일의 구현 여부를 점검해 드려요.'); }
});
});
document.getElementById('agentReset').addEventListener('click', function () {
body.querySelectorAll('.ag-msg, .ag-tool, .ag-draft, .ag-review').forEach(function (n, i) { if (i > 0) n.remove(); });
addBot('새 세션을 시작했어요. 지시할 업무를 설명하거나 <b>/새지시</b> 명령으로 시작하세요.');
});
document.querySelectorAll('.ag-draft').forEach(recount);
})();
</script>
</body>
</html>