/* =========================================================== 아리 — 작업(Tasks) · RON 디자인 언어 (journey.css 위에 얹는 레이어) · 칸반 / 리스트 뷰 · 우측 절반 드로어 — 무한 중첩 하위 작업 journey.css 의 토큰·상단바·레일·.panel·.act·.avatar 재사용 =========================================================== */ /* ---- 보조 토큰 ---- */ :root { --teal: #5fa6a0; --mauve: #9c8bcb; --teal-soft: rgba(95, 166, 160, 0.16); --mauve-soft: rgba(156, 139, 203, 0.16); } /* 레일에 라벨 줄세움 위해 width 살짝 */ .tpage { max-width: 1560px; margin: 0 auto; padding: 0 30px 46px; } /* ===================== 페이지 헤더 ===================== */ .thead-row { display: flex; align-items: flex-end; gap: 16px; padding: 6px 6px 18px; } .thead-ic { width: 54px; height: 54px; border-radius: 17px; flex-shrink: 0; display: grid; place-items: center; background: var(--ink); color: var(--blue); box-shadow: var(--sh-soft); } .thead-ic .ic { width: 26px; height: 26px; } .thead-titles { min-width: 0; } .thead-titles h1 { font-family: var(--font); font-weight: 700; font-size: clamp(28px, 3vw, 42px); letter-spacing: -0.04em; line-height: 1; margin: 0; } .thead-sub { font-size: 14px; color: var(--muted); margin-top: 9px; } .thead-sub b { color: var(--ink-2); font-weight: 600; } .thead-stack { margin-left: auto; display: flex; align-items: center; gap: 8px; } /* ===================== 툴바 ===================== */ .ttoolbar { display: flex; align-items: center; gap: 12px; padding: 0 6px 18px; flex-wrap: wrap; } .view-seg { display: inline-flex; gap: 3px; padding: 4px; background: var(--panel); border: 1px solid var(--panel-brd); -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur); border-radius: 999px; box-shadow: var(--sh-soft); } .view-seg button { display: inline-flex; align-items: center; gap: 7px; font-size: 13.5px; font-weight: 600; color: var(--ink-2); padding: 9px 16px; border-radius: 999px; transition: background .15s, color .15s; } .view-seg button .ic { width: 16px; height: 16px; opacity: .75; } .view-seg button:hover { color: var(--ink); } .view-seg button.on { background: var(--ink); color: #fff; } .view-seg button.on .ic { opacity: 1; } .t-search { display: flex; align-items: center; gap: 9px; flex: 1; min-width: 180px; max-width: 340px; background: var(--panel); border: 1px solid var(--panel-brd); -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur); border-radius: 999px; padding: 0 16px; height: 44px; box-shadow: var(--sh-soft); } .t-search .ic { width: 17px; height: 17px; color: var(--muted); flex-shrink: 0; } .t-search input { flex: 1; min-width: 0; border: none; background: none; outline: none; font-size: 14px; color: var(--ink); } .t-search input::placeholder { color: var(--faint); } .t-new { margin-left: auto; display: inline-flex; align-items: center; gap: 8px; background: var(--ink); color: #fff; font-size: 14px; font-weight: 600; padding: 0 20px; height: 44px; border-radius: 999px; box-shadow: var(--sh-soft); transition: transform .13s; } .t-new .ic { width: 17px; height: 17px; } .t-new:hover { transform: translateY(-1px); } /* 공통: 태그·아바타·칩 */ .av { width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0; display: grid; place-items: center; color: #fff; font-weight: 700; font-size: 11.5px; border: 2px solid var(--white); } .ptag { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 600; color: var(--ink-2); background: var(--card-2); border-radius: 999px; padding: 4px 10px; white-space: nowrap; } .ptag .pdot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; } .prio { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 600; white-space: nowrap; } .prio .ic { width: 13px; height: 13px; } .prio-높음 { color: var(--red); } .prio-보통 { color: var(--ink-2); } .prio-낮음 { color: var(--faint); } .due { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; color: var(--ink-2); font-family: var(--font-mono); white-space: nowrap; } .due .ic { width: 13px; height: 13px; color: var(--muted); } .due.soon { color: var(--red); } .due.soon .ic { color: var(--red); } .miniprog { display: inline-flex; align-items: center; gap: 7px; } .miniprog .bar { width: 46px; height: 5px; border-radius: 999px; background: var(--card-2); overflow: hidden; } .miniprog .bar span { display: block; height: 100%; background: var(--blue-d); border-radius: 999px; } .miniprog .n { font-size: 11px; color: var(--muted); font-family: var(--font-mono); display: inline-flex; align-items: center; gap: 3px; } .miniprog .n .ic { width: 12px; height: 12px; } /* ===================== 좌측 사이드바 (프로젝트 목록) ===================== */ .tsidebar { position: sticky; top: 100px; flex-shrink: 0; width: 244px; align-self: flex-start; display: flex; flex-direction: column; gap: 4px; background: var(--panel); border: 1px solid var(--panel-brd); -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur); border-radius: var(--r-lg); box-shadow: var(--sh-soft); padding: 12px; max-height: calc(100vh - 124px); overflow-y: auto; } .sb-back { display: flex; align-items: center; gap: 9px; width: 100%; font-size: 13px; font-weight: 600; color: var(--muted); padding: 9px 11px; border-radius: 11px; transition: background .14s, color .14s; } .sb-back .ic { width: 16px; height: 16px; } .sb-back:hover { background: var(--card-2); color: var(--ink); } .sb-label { font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--faint); padding: 14px 12px 7px; } .sb-sec { display: flex; flex-direction: column; gap: 2px; } .sb-item { display: flex; align-items: center; gap: 11px; width: 100%; text-align: left; font-size: 13.5px; font-weight: 500; color: var(--ink-2); padding: 9px 11px; border-radius: 11px; transition: background .13s, color .13s; position: relative; } .sb-item .ic { width: 17px; height: 17px; color: var(--muted); flex-shrink: 0; } .sb-item .sb-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; margin: 0 3px; } .sb-item .sb-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .sb-item .sb-count { font-size: 11.5px; font-family: var(--font-mono); color: var(--faint); } .sb-item:hover { background: var(--card-2); color: var(--ink); } .sb-item:hover .ic { color: var(--ink-2); } .sb-item.on { background: var(--ink); color: #fff; } .sb-item.on .ic { color: #fff; } .sb-item.on .sb-count { color: rgba(255,255,255,.7); } .sb-divider { height: 1px; background: var(--line); margin: 8px 4px; } .sb-prj-head { display: flex; align-items: center; padding: 14px 12px 7px; } .sb-prj-head .sb-label { padding: 0; flex: 1; } .sb-prj-head .sb-addprj { width: 24px; height: 24px; border-radius: 7px; display: grid; place-items: center; color: var(--muted); transition: background .13s, color .13s; } .sb-prj-head .sb-addprj .ic { width: 15px; height: 15px; } .sb-prj-head .sb-addprj:hover { background: var(--card-2); color: var(--ink); } .sb-new { display: flex; align-items: center; gap: 9px; width: 100%; font-size: 13px; font-weight: 600; color: var(--blue-d); padding: 10px 11px; border-radius: 11px; margin-top: 6px; transition: background .14s; } .sb-new .ic { width: 16px; height: 16px; } .sb-new:hover { background: var(--blue-soft); } /* ===================== 칸반 (한 장의 카드 안, 컬럼은 섹션) ===================== */ .kboard { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0; } .kcol { display: flex; flex-direction: column; gap: 13px; min-width: 0; padding: 0 16px; } .kcol:first-child { padding-left: 2px; } .kcol:last-child { padding-right: 2px; } .kcol + .kcol { border-left: 1px solid var(--line); } .kcol-head { display: flex; align-items: center; gap: 9px; padding: 0 4px 2px; } .kcol-head .kdot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; } .kcol-head .kt { font-size: 13.5px; font-weight: 700; letter-spacing: -0.01em; } .kcol-head .kn { font-size: 11.5px; color: var(--muted); font-family: var(--font-mono); } .kcol-head .kadd { margin-left: auto; width: 28px; height: 28px; border-radius: 9px; display: grid; place-items: center; color: var(--muted); transition: background .14s, color .14s; } .kcol-head .kadd .ic { width: 16px; height: 16px; } .kcol-head .kadd:hover { background: var(--card-2); color: var(--ink); } .kcol-body { flex: 1; display: flex; flex-direction: column; gap: 12px; border-radius: var(--r); padding: 4px; min-height: 120px; transition: background .15s, box-shadow .15s; } .kcol.over .kcol-body { background: var(--blue-soft); box-shadow: inset 0 0 0 2px var(--blue); } .kcol-empty { font-size: 12px; color: var(--faint); text-align: center; padding: 18px 8px; } .tcard { background: var(--card); border: 1px solid var(--line); border-radius: var(--r); padding: 14px; box-shadow: var(--sh-card); cursor: pointer; display: flex; flex-direction: column; gap: 11px; transition: transform .14s, box-shadow .14s; } .tcard:hover { transform: translateY(-2px); box-shadow: var(--sh-card), 0 16px 32px -22px rgba(28,36,54,.34); } .tcard.dragging { opacity: .4; } .tcard.done .tcard-title { color: var(--faint); text-decoration: line-through; } .tcard-top { display: flex; align-items: center; gap: 8px; } .tcard-top .kmore { margin-left: auto; width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center; color: var(--faint); } .tcard-top .kmore .ic { width: 16px; height: 16px; } .tcard-top .kmore:hover { background: var(--card-2); color: var(--ink); } .tcard-title { font-size: 14px; font-weight: 600; letter-spacing: -0.01em; line-height: 1.34; } .tcard-foot { display: flex; align-items: center; gap: 10px; padding-top: 11px; border-top: 1px solid var(--line); } .tcard-foot .av { margin-left: auto; } /* ===================== 리스트 ===================== */ .lst { background: var(--card); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--sh-card); overflow: hidden; } .lst-head, .lrow { display: grid; grid-template-columns: minmax(0,1fr) 130px 80px 92px 92px 110px; align-items: center; gap: 14px; padding: 0 22px; } .lst-head { height: 46px; border-bottom: 1px solid var(--line); } .lst-head > div { font-size: 11.5px; font-weight: 600; color: var(--muted); } .lst-head .c, .lrow .c { justify-self: center; } .lrow { min-height: 60px; border-bottom: 1px solid var(--line); cursor: pointer; transition: background .14s; } .lrow:last-child { border-bottom: none; } .lrow:hover { background: var(--card-2); } .lrow.done .lt-title { color: var(--faint); text-decoration: line-through; } .lt { display: flex; align-items: center; gap: 12px; min-width: 0; padding: 12px 0; } .lt .lstatus { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; } .lt-title { font-size: 14px; font-weight: 600; letter-spacing: -0.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .lt-title .subcount { color: var(--faint); font-weight: 500; font-family: var(--font-mono); font-size: 12px; margin-left: 7px; } /* ===================== 우측 드로어 (반쪽 화면) ===================== */ .drawer-scrim { position: fixed; inset: 0; z-index: 80; background: rgba(16, 20, 26, 0.22); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); opacity: 0; animation: scrim .25s ease forwards; } @keyframes scrim { to { opacity: 1; } } .drawer { position: fixed; top: 0; right: 0; bottom: 0; z-index: 81; width: clamp(460px, 46vw, 760px); display: flex; flex-direction: column; background: var(--white); border-left: 1px solid var(--panel-brd); box-shadow: -40px 0 80px -40px rgba(16,20,26,.4); transform: translateX(100%); animation: drawerIn .34s cubic-bezier(.2,.7,.2,1) forwards; } @keyframes drawerIn { to { transform: none; } } @media (prefers-reduced-motion: reduce) { .drawer-scrim, .drawer { animation: none; opacity: 1; transform: none; } } /* 드로어 헤더 — 브레드크럼 + 닫기 */ .dh { display: flex; align-items: center; gap: 10px; padding: 16px 20px; border-bottom: 1px solid var(--line); flex-shrink: 0; } .dh-crumbs { display: flex; align-items: center; gap: 2px; min-width: 0; flex: 1; overflow: hidden; } .dh-crumbs .cz { font-size: 12.5px; font-weight: 600; color: var(--muted); white-space: nowrap; padding: 4px 8px; border-radius: 8px; max-width: 220px; overflow: hidden; text-overflow: ellipsis; transition: background .14s, color .14s; } .dh-crumbs button.cz:hover { background: var(--card-2); color: var(--ink); } .dh-crumbs .cz.cur { color: var(--ink); } .dh-crumbs .csep { color: var(--faint); display: grid; place-items: center; flex-shrink: 0; } .dh-crumbs .csep .ic { width: 14px; height: 14px; } .dh-up, .dh-x { width: 38px; height: 38px; border-radius: 11px; flex-shrink: 0; display: grid; place-items: center; color: var(--ink-2); background: var(--card-2); transition: background .14s, color .14s; } .dh-up .ic, .dh-x .ic { width: 18px; height: 18px; } .dh-up:hover, .dh-x:hover { background: var(--line-2); color: var(--ink); } .dbody { flex: 1; overflow-y: auto; padding: 26px 30px 40px; } /* 상태 체크 + 타이틀 */ .dtitle-row { display: flex; align-items: flex-start; gap: 14px; } .dcheck { width: 28px; height: 28px; border-radius: 9px; flex-shrink: 0; margin-top: 3px; border: 2px solid var(--line-2); display: grid; place-items: center; color: transparent; transition: all .14s; cursor: pointer; } .dcheck .ic { width: 16px; height: 16px; } .dcheck.done { background: var(--teal); border-color: var(--teal); color: #fff; } .dtitle { font-family: var(--font); font-size: 26px; font-weight: 700; letter-spacing: -0.03em; line-height: 1.22; flex: 1; min-width: 0; border: none; background: none; outline: none; color: var(--ink); resize: none; padding: 0; word-break: keep-all; } .dtitle.done { color: var(--faint); text-decoration: line-through; } /* 메타 그리드 */ .dmeta { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 20px; margin: 24px 0 6px; } .dmi { display: flex; flex-direction: column; gap: 7px; } .dmi .ml { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 600; color: var(--muted); } .dmi .ml .ic { width: 14px; height: 14px; } .dmv { display: inline-flex; align-items: center; gap: 8px; font-size: 13.5px; font-weight: 600; color: var(--ink); } .status-wrap { position: relative; } .status-pill { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: var(--ink); background: var(--card-2); border-radius: 999px; padding: 7px 13px; } .status-pill .pdot { width: 8px; height: 8px; border-radius: 50%; } .status-pill .ic { width: 14px; height: 14px; color: var(--muted); } .status-menu { position: absolute; top: calc(100% + 6px); left: 0; z-index: 5; min-width: 150px; background: var(--white); border: 1px solid var(--line-2); border-radius: 14px; box-shadow: var(--sh-panel); padding: 6px; } .status-menu button { display: flex; align-items: center; gap: 9px; width: 100%; text-align: left; font-size: 13px; font-weight: 500; color: var(--ink-2); padding: 9px 11px; border-radius: 9px; } .status-menu button:hover { background: var(--card-2); color: var(--ink); } .status-menu button .pdot { width: 8px; height: 8px; border-radius: 50%; } /* 섹션 라벨 */ .dlabel { display: flex; align-items: center; gap: 8px; margin: 28px 0 12px; font-size: 12.5px; font-weight: 700; color: var(--ink-2); letter-spacing: -0.01em; } .dlabel .ic { width: 15px; height: 15px; color: var(--muted); } .dlabel .cnt { font-family: var(--font-mono); font-size: 12px; font-weight: 500; color: var(--muted); } .dlabel .dline { flex: 1; height: 1px; background: var(--line); } /* 설명 */ .ddesc { font-size: 14px; line-height: 1.6; color: var(--ink-2); white-space: pre-wrap; border-radius: var(--r-sm); padding: 13px 15px; background: var(--card-2); cursor: text; } .ddesc.empty { color: var(--faint); } .ddesc-edit { width: 100%; min-height: 92px; font-family: inherit; font-size: 14px; line-height: 1.6; color: var(--ink); border: 1px solid var(--blue); border-radius: var(--r-sm); padding: 12px 14px; outline: none; resize: vertical; background: var(--white); } /* ---- 하위 작업 트리 (무한 중첩) ---- */ .subtree { display: flex; flex-direction: column; gap: 2px; } .subrow { display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: 12px; cursor: pointer; transition: background .13s; position: relative; } .subrow:hover { background: var(--card-2); } .subrow .twist { width: 22px; height: 22px; border-radius: 7px; flex-shrink: 0; display: grid; place-items: center; color: var(--muted); transition: transform .16s, background .13s, color .13s; } .subrow .twist .ic { width: 14px; height: 14px; } .subrow .twist.open { transform: rotate(90deg); } .subrow .twist:hover { background: var(--line-2); color: var(--ink); } .subrow .twist-spacer { width: 22px; flex-shrink: 0; } .scheck { width: 21px; height: 21px; border-radius: 6px; flex-shrink: 0; border: 2px solid var(--line-2); display: grid; place-items: center; color: transparent; transition: all .13s; } .scheck .ic { width: 12px; height: 12px; } .scheck.done { background: var(--teal); border-color: var(--teal); color: #fff; } .subrow .stitle { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 500; color: var(--ink); letter-spacing: -0.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .subrow.done .stitle { color: var(--faint); text-decoration: line-through; } .subrow .smeta { display: flex; align-items: center; gap: 9px; flex-shrink: 0; } .subrow .schips { font-size: 10.5px; color: var(--muted); font-family: var(--font-mono); display: inline-flex; align-items: center; gap: 3px; } .subrow .schips .ic { width: 12px; height: 12px; } .subrow .av { width: 24px; height: 24px; font-size: 10px; } .subrow .sdrill { width: 26px; height: 26px; border-radius: 8px; display: grid; place-items: center; color: var(--faint); opacity: 0; transition: opacity .13s, background .13s, color .13s; } .subrow:hover .sdrill { opacity: 1; } .subrow .sdrill:hover { background: var(--line-2); color: var(--ink); } .subrow .sdrill .ic { width: 15px; height: 15px; } .subkids { margin-left: 22px; padding-left: 10px; border-left: 1.5px solid var(--line); display: flex; flex-direction: column; gap: 2px; } .sub-add { display: inline-flex; align-items: center; gap: 8px; margin: 4px 0 0 10px; font-size: 13px; font-weight: 600; color: var(--blue-d); padding: 8px 10px; border-radius: 10px; transition: background .13s; } .sub-add .ic { width: 15px; height: 15px; } .sub-add:hover { background: var(--blue-soft); } .sub-input { display: flex; align-items: center; margin: 4px 0; width: 100%; font-size: 13.5px; color: var(--ink); border: 1px solid var(--blue); border-radius: 10px; padding: 9px 12px; outline: none; background: var(--white); } /* 빈 상태 */ .subempty { display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; padding: 22px 10px; color: var(--faint); font-size: 13px; } .subempty .ic { width: 26px; height: 26px; color: var(--line-2); } /* 드로어 푸터 */ .dfoot { display: flex; align-items: center; gap: 10px; padding: 14px 20px; border-top: 1px solid var(--line); flex-shrink: 0; } .dfoot .btn { display: inline-flex; align-items: center; gap: 7px; font-size: 13.5px; font-weight: 600; padding: 11px 18px; border-radius: 12px; transition: transform .12s, background .14s; } .dfoot .btn .ic { width: 16px; height: 16px; } .dfoot .btn.danger { color: var(--red); background: var(--red-soft); } .dfoot .btn.danger:hover { background: rgba(206,105,105,.24); } .dfoot .btn.ghost { color: var(--ink-2); background: var(--card-2); } .dfoot .btn.ghost:hover { background: var(--line-2); } .dfoot .btn.primary { margin-left: auto; background: var(--ink); color: #fff; } .dfoot .btn.primary:hover { transform: translateY(-1px); } /* 진입 — .enter 클래스가 JS로 붙은 뒤에만 애니메이션 (기본 상태는 항상 보임) */ .tpage.enter .panel, .tpage.enter .kboard, .tpage.enter .thead-row > *, .tpage.enter .ttoolbar { animation: tup .5s cubic-bezier(.2,.7,.2,1) both; } @keyframes tup { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } } @media (prefers-reduced-motion: reduce) { .tpage.enter .panel, .tpage.enter .kboard, .tpage.enter .thead-row > *, .tpage.enter .ttoolbar { animation: none; } } /* ===================== 반응형 ===================== */ @media (max-width: 860px) { .tsidebar { position: static; width: 100%; max-height: none; flex-direction: row; flex-wrap: wrap; align-items: center; gap: 6px; overflow-x: auto; } .tsidebar .sb-label, .tsidebar .sb-prj-head, .tsidebar .sb-divider, .tsidebar .sb-back, .tsidebar .sb-new { display: none; } .tsidebar .sb-sec { flex-direction: row; flex-wrap: wrap; gap: 6px; } .sb-item { width: auto; } .sb-item .sb-count { display: none; } } @media (max-width: 1180px) { .kboard { grid-template-columns: repeat(2, 1fr); gap: 22px 18px; } .kcol { padding: 0; } .kcol:first-child, .kcol:last-child { padding: 0; } .kcol + .kcol { border-left: none; } .lst-head, .lrow { grid-template-columns: minmax(0,1fr) 90px 88px 110px; } .lst-head .hide-md, .lrow .hide-md { display: none; } } @media (max-width: 860px) { .tpage { padding: 0 14px 30px; } .drawer { width: 100%; } .kboard { grid-template-columns: 1fr; } .lst-head, .lrow { grid-template-columns: minmax(0,1fr) 84px 96px; padding: 0 16px; } .lst-head .hide-sm, .lrow .hide-sm { display: none; } .dmeta { grid-template-columns: 1fr; } }