旧排版(顶栏页签 + 数据卡片置顶 + 长页堆叠 + 详情卡片堆在对话下)全部去掉,功能不变: - 左侧栏:导航按任务/管理分组,底部紧凑概览卡片始终可见;整页不再单页长滚动,各 pane 各自滚动 - 任务工作台:左任务列表轨(搜索/筛选/分页),中派发(可收起)+ 单列对话,右任务详情检查器 - 详情检查器:概览/协作/评审与审批/线程四个内页签,一次只显示一组 - 其余功能各成独立页面:项目与成员、环境与 Workers、技能与自动化、系统与 Key - 视图同步到 location.hash(#view-tasks 等) 构建:npm run build(tsc + vite singlefile)通过,产物 332130 字节;本地全量 cloud 1275 项全过(skipped 4)。
324 lines
23 KiB
CSS
324 lines
23 KiB
CSS
/* Single token source — GitHub Primer (light) visual language.
|
|
This supersedes the Muse web/desktop palette: Primer canvas,
|
|
borders, foregrounds and accents only. No grey/blue chat bubbles,
|
|
no pill shapes, no coloured page backgrounds, no shadows beyond
|
|
GitHub's hairline button shadow. Layout is width-adaptive (see the
|
|
"Width-adaptive columns" block below): 1 column under 900px,
|
|
2 columns at 900-1399px, 3 columns at 1400px and up — each column
|
|
is an independent wrapper (.dash-col) whose sections stack tightly
|
|
on their own; the narrow single column is restored to the original
|
|
stacked order with display:contents plus an explicit order per
|
|
section (see the narrow block). */
|
|
:root{
|
|
--text:#1f2328; --muted:#656d76; --subtle:#6e7781;
|
|
--line:#d0d7de; --line-muted:#d8dee4;
|
|
--paper:#ffffff; --card:#ffffff; --subtle-bg:#f6f8fa; --inset-bg:#f6f8fa;
|
|
--accent:#0969da; --accent-emphasis:#0969da;
|
|
--green:#2da44e; --green-hover:#2c974b; --success:#1a7f37;
|
|
--danger:#d1242f; --danger-bg:#ffebe9;
|
|
--attention:#9a6700; --done:#8250df; --selected-bg:#ddf4ff;
|
|
--radius:6px; --shadow:0 1px 0 rgba(27,31,36,.04);
|
|
--sans:-apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif;
|
|
--mono:ui-monospace,SFMono-Regular,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;
|
|
--ctl:32px;
|
|
}
|
|
*{box-sizing:border-box}
|
|
html,body,#root{height:100%}
|
|
body{font-family:var(--sans);margin:0;color:var(--text);background:#fff;line-height:1.5;font-size:14px}
|
|
a{color:var(--accent);text-underline-offset:3px}
|
|
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
|
|
@media (prefers-reduced-motion:reduce){*{scroll-behavior:auto!important;transition:none!important}}
|
|
.muted{color:var(--muted);font-size:12px;line-height:1.5}
|
|
.err{color:var(--danger)} .ok{color:var(--success)}
|
|
/* GitHub buttons: secondary by default, 6px radius, 5px 16px padding.
|
|
"primary" and the legacy "seal" name are the green primary action
|
|
(dispatch / submit), exactly like GitHub's primary button. */
|
|
button{cursor:pointer;font-weight:500;border-radius:var(--radius);border:1px solid var(--line);background:#fff;color:var(--text);box-shadow:var(--shadow)}
|
|
button:hover{background:var(--subtle-bg)}
|
|
button:disabled{opacity:.45;cursor:not-allowed;box-shadow:none}
|
|
button.primary,button.seal{background:var(--green);border-color:rgba(27,31,36,.15);color:#fff}
|
|
button.primary:hover,button.seal:hover{background:var(--green-hover)}
|
|
button.danger{color:var(--danger);border-color:var(--line);background:#fff}
|
|
button.danger:hover{background:var(--danger-bg);color:var(--danger)}
|
|
.icon-btn{width:32px;height:32px;padding:0;display:grid;place-items:center;border:1px solid var(--line);border-radius:var(--radius);background:#fff;color:var(--text);font-size:16px;line-height:1}
|
|
.icon-btn:hover{background:var(--subtle-bg)}
|
|
|
|
/* Dashboard shell: ONE scrollable console page.
|
|
Dark GitHub-style header (#24292f, white text) with the anchor nav
|
|
inside it, a data-cards row, then every module as a section. */
|
|
.dash-topbar{position:sticky;top:0;z-index:10;background:#24292f;color:#fff;border-bottom:1px solid rgba(255,255,255,.15);padding:10px 20px 8px}
|
|
.dash-topbar .muted{color:rgba(255,255,255,.75)}
|
|
.dash-topbar-row{display:flex;gap:14px;align-items:center;flex-wrap:wrap}
|
|
.dash-brand{font-weight:600;font-size:16px;color:#fff}
|
|
.dash-status{font-size:13px;font-weight:600;color:rgba(255,255,255,.75)}
|
|
.dash-status.ok{color:#2da44e}
|
|
.dash-stamp{margin-left:auto}
|
|
.dash-nav{display:flex;gap:4px;flex-wrap:wrap;margin-top:8px}
|
|
.dash-nav a{color:#fff;text-decoration:none;font-size:13px;font-weight:600;padding:6px 12px;border-radius:var(--radius)}
|
|
.dash-nav a:hover{background:rgba(255,255,255,.12);text-decoration:none}
|
|
/* Tab nav: buttons styled like the old anchor nav (dark header, white
|
|
text), active tab gets the hover background permanently. */
|
|
.tab-nav button{background:transparent;border:0;box-shadow:none;color:#fff;font-size:13px;font-weight:600;padding:6px 12px;border-radius:var(--radius)}
|
|
.tab-nav button:hover{background:rgba(255,255,255,.12)}
|
|
.tab-nav button.active{background:rgba(255,255,255,.18)}
|
|
/* Tab pages: the main page is a flex column (not the old 3-column
|
|
grid), so a tab's content spans the full width. The workbench tab
|
|
is a 2-column grid (tasks left, dispatch + conversation + detail
|
|
right) at >=900px and a single column below that; other tabs are
|
|
a single stacked column. Workbench columns keep the equal-height
|
|
rule from the wide/medium blocks (fixed height, internal scroll). */
|
|
.dash-page-tabs{display:flex}
|
|
.dash-page-tabs > .tab-content{grid-column:1 / -1;min-width:0;display:flex;flex-direction:column;gap:20px}
|
|
.tab-workbench{display:grid;grid-template-columns:320px minmax(0,1fr);gap:20px;align-items:start}
|
|
.tab-workbench > *{min-width:0}
|
|
@media (max-width:899px){
|
|
.tab-workbench{grid-template-columns:1fr}
|
|
/* Narrow workbench keeps the old single-column order (dispatch
|
|
first, then tasks, then conversation) even though the DOM now
|
|
groups tasks in the left column wrapper. */
|
|
.tab-workbench #sec-dispatch{order:1} .tab-workbench #sec-tasks{order:2} .tab-workbench #sec-conv{order:3}
|
|
}
|
|
.dash-page{max-width:1180px;margin:0 auto;padding:20px;display:flex;flex-direction:column;gap:20px}
|
|
.dash-page > *{min-width:0} /* grid/flex children must shrink, never push the page wider; long lines scroll inside pre/.trace-box/.table-wrap instead */
|
|
.dash-section > *{min-width:0}
|
|
.dash-section{scroll-margin-top:130px;display:flex;flex-direction:column;gap:16px}
|
|
.dash-section.card{padding:16px}
|
|
.dash-cards{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
|
|
.dash-card{background:#fff;border:1px solid var(--line);border-radius:var(--radius);padding:16px;min-width:0}
|
|
.dash-card-label{color:var(--muted);font-size:12px;font-weight:600}
|
|
.dash-card-value{font-size:24px;font-weight:600;line-height:1.3;overflow-wrap:anywhere}
|
|
|
|
/* Boxes: bordered, 6px radius, white body, subtle header row. */
|
|
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:none;padding:16px}
|
|
.card h2{font-size:14px;margin:0 0 12px;font-weight:600}
|
|
.card h3{font-size:14px;margin:24px 0 12px;padding-top:16px;border-top:1px solid var(--line);font-weight:600}
|
|
.card h3:first-of-type{border-top:0;padding-top:0}
|
|
.composer h2{font-size:16px}
|
|
.composer textarea.prompt{min-height:148px;font-size:14px;padding:12px;border-radius:var(--radius)}
|
|
.composer textarea.coord{font-family:var(--mono);font-size:13px}
|
|
/* Unified controls: same-row controls are all 32px (GitHub height) */
|
|
.bar{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin:12px 0}
|
|
.bar > button,.bar > label{display:inline-flex;align-items:center;height:var(--ctl);min-height:var(--ctl);padding:0 16px;box-sizing:border-box;white-space:nowrap}
|
|
.bar > input,.bar > select{height:var(--ctl);min-height:var(--ctl)}
|
|
input,select,textarea,button{font:inherit;font-size:14px;padding:5px 12px;border-radius:var(--radius);border:1px solid var(--line);background:#fff;color:var(--text)}
|
|
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(9,105,218,.3)}
|
|
select{appearance:none;-webkit-appearance:none;cursor:pointer;padding-right:34px;background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%23656d76' stroke-width='1.5' stroke-linecap='round'/></svg>");background-repeat:no-repeat;background-position:right 12px center}
|
|
select::-ms-expand{display:none}
|
|
select:disabled,input:disabled{color:var(--muted);background:var(--subtle-bg);cursor:not-allowed}
|
|
input[type="checkbox"]{width:16px;height:16px;accent-color:var(--accent)}
|
|
input[type="file"]{height:var(--ctl);display:inline-flex;align-items:center;padding:0 12px;border:1px dashed var(--line);border-radius:var(--radius);background:#fff}
|
|
input[type="file"]::file-selector-button{height:24px;padding:0 12px;margin-right:10px;border:1px solid var(--line);border-radius:var(--radius);background:var(--subtle-bg);color:var(--text);font:inherit;font-size:13px;cursor:pointer}
|
|
textarea{width:100%;min-height:84px;resize:vertical;line-height:1.5;padding:12px;border-radius:var(--radius)}
|
|
.composer .bar label{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--line);border-radius:var(--radius);padding:5px 12px;background:#fff;cursor:pointer;font-size:13px;font-weight:500}
|
|
.composer .bar label:has(input:checked){background:var(--text);color:#fff;border-color:var(--text)}
|
|
.stacked{margin-bottom:12px}
|
|
.stacked + .bar{margin-top:0}
|
|
/* Data lists: bordered rows, no coloured backgrounds */
|
|
.data-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px}
|
|
.data-list li{position:relative;margin:0;padding:8px 12px;background:#fff;border:1px solid var(--line);border-radius:var(--radius);line-height:1.5;display:flex;flex-wrap:wrap;align-items:center;gap:8px;overflow-wrap:anywhere}
|
|
.data-list li .row-main{flex:1 1 200px;min-width:0}
|
|
.data-list li button{flex:none}
|
|
.data-list li.is-online,.data-list li.is-offline{padding-left:26px}
|
|
.data-list li.is-online::before,.data-list li.is-offline::before{content:"";position:absolute;left:12px;top:15px;width:8px;height:8px;border-radius:50%}
|
|
.data-list li.is-online::before{background:var(--success)}
|
|
.data-list li.is-offline::before{background:var(--danger)}
|
|
.data-group{margin-bottom:12px}.data-group:last-child{margin-bottom:0}.data-group > b{display:block;margin-bottom:8px}
|
|
/* Status colours (Primer text; issue dots use the same classes) */
|
|
.st-queued{color:var(--muted)}.st-running{color:var(--success);font-weight:600}.st-completed{color:var(--done)}.st-failed,.st-merge-failed{color:var(--danger)}.st-merged{color:var(--done)}.st-interrupted{color:var(--attention)}
|
|
/* Task table */
|
|
.table-wrap{border:0;border-top:1px solid var(--line);overflow:auto;background:var(--card)}
|
|
table{border-collapse:collapse;width:100%;font-size:13px}
|
|
th,td{padding:8px 16px;text-align:left;vertical-align:top;border-bottom:1px solid var(--line)}
|
|
th{background:var(--subtle-bg);color:var(--muted);font-size:12px;font-weight:600;white-space:nowrap}
|
|
tbody tr{cursor:pointer}
|
|
tbody tr:hover{background:var(--subtle-bg)}
|
|
tr.selected{background:var(--selected-bg)}
|
|
td.prompt-col{font-size:14px;line-height:1.5}
|
|
/* Result / error blocks and trace: subtle inset, monospace */
|
|
pre{background:var(--inset-bg);color:var(--text);border:1px solid var(--line);border-radius:var(--radius);padding:16px;overflow:auto;max-height:420px;white-space:pre-wrap;word-break:break-word;font-size:13px;font-family:var(--mono);line-height:1.5}
|
|
.trace-box{background:var(--inset-bg);color:var(--text);border:1px solid var(--line);border-radius:var(--radius);padding:16px;max-height:520px;overflow:auto;font-size:13px;line-height:1.5;font-family:var(--mono)}
|
|
.trace-box .muted{color:var(--muted)}
|
|
/* GitHub issues-style task list: hairline rows, status dot at left,
|
|
14px title, 12px muted meta, selected row light blue-grey. */
|
|
.search-box{display:flex;align-items:center;gap:8px;border:1px solid var(--line);border-radius:var(--radius);background:#fff;padding:0 12px;color:var(--muted)}
|
|
.search-box input{flex:1;border:0;padding:5px 0}
|
|
.search-box input:focus{box-shadow:none}
|
|
.list-section-head{display:flex;align-items:center;justify-content:space-between;font-size:14px;font-weight:600;margin:12px 0 4px}
|
|
.issue-list{list-style:none;margin:0;padding:0;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden}
|
|
/* Unbounded lists get their own scrollbar instead of stretching the
|
|
whole column (and the whole page) indefinitely: the task list is
|
|
capped at 60vh, the API Key list at 320px. Search/filter bars sit
|
|
outside these containers, so they stay visible while the list
|
|
scrolls. overscroll-behavior:contain keeps a list scroll from
|
|
immediately dragging the page (or the column) with it. */
|
|
.issue-list{max-height:60vh;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain}
|
|
.api-key-list{max-height:320px;overflow-y:auto;overscroll-behavior:contain;display:flex;flex-direction:column;gap:8px}
|
|
.issue-item{padding:8px 16px;border-bottom:1px solid var(--line);cursor:pointer;display:flex;gap:10px;align-items:flex-start;background:#fff}
|
|
.issue-item:last-child{border-bottom:0}
|
|
.issue-item:hover{background:var(--subtle-bg)}
|
|
.issue-item.selected{background:var(--selected-bg)}
|
|
.issue-state{flex:none;width:16px;height:16px;margin-top:2px;border-radius:50%;background:var(--muted)}
|
|
.issue-state.st-running,.issue-state.st-queued{background:var(--success)}
|
|
.issue-state.st-completed,.issue-state.st-merged{background:var(--done)}
|
|
.issue-state.st-failed,.issue-state.st-merge-failed{background:var(--danger)}
|
|
.issue-state.st-interrupted{background:var(--attention)}
|
|
.issue-first{flex:none;width:22px;height:22px;margin-top:1px;border:1px solid var(--line);border-radius:6px;background:var(--subtle-bg);display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:600;color:var(--muted);overflow:hidden}
|
|
/* Task detail card layout: cards stacked with a gap, KPI cards in a
|
|
responsive grid (auto-fit, so the narrow right column collapses
|
|
to one per row instead of squeezing three). Only layout: no data,
|
|
action or section is added or removed by this styling. */
|
|
.detail-stack{display:flex;flex-direction:column;gap:16px;min-width:0}
|
|
.detail-stack > .card{margin:0}
|
|
.detail-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px;margin-top:12px}
|
|
.detail-card{background:#fff;border:1px solid var(--line);border-radius:var(--radius);padding:12px 16px;min-width:0}
|
|
.detail-card-label{color:var(--muted);font-size:12px;font-weight:600}
|
|
.detail-card-value{font-size:20px;font-weight:600;line-height:1.3;overflow-wrap:anywhere}
|
|
.detail-card .muted{font-size:12px;line-height:1.5;overflow-wrap:anywhere}
|
|
.detail-kv{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:8px 16px;margin:0;font-size:13px}
|
|
.detail-kv > div{min-width:0}
|
|
.detail-kv dt{color:var(--muted);font-size:12px}
|
|
.detail-kv dd{margin:0;overflow-wrap:anywhere}
|
|
.issue-title{font-size:14px;line-height:1.5;overflow-wrap:anywhere}
|
|
.issue-meta{font-size:12px;color:var(--muted);line-height:1.5}
|
|
/* Conversation as a GitHub timeline / comments: white comment boxes
|
|
with a subtle header row, connected by a muted vertical line.
|
|
No bubbles, no left/right alignment by role — every entry is a
|
|
full-width comment. Status entries are plain muted timeline text. */
|
|
.conversation{display:flex;flex-direction:column;gap:16px}
|
|
.chat-column{max-width:100%;margin:0 auto;width:100%}
|
|
.chat-list{position:relative;display:flex;flex-direction:column;gap:12px;max-height:none;overflow:visible;padding:4px 0 4px 20px;border-left:2px solid var(--line);margin-left:8px}
|
|
.gh-comment{border:1px solid var(--line);border-radius:var(--radius);background:#fff;overflow:hidden}
|
|
.gh-comment-header{background:var(--subtle-bg);border-bottom:1px solid var(--line);padding:8px 16px;font-size:13px}
|
|
.gh-comment-author{font-weight:600;color:var(--text)}
|
|
.gh-comment-body{padding:16px;white-space:pre-wrap;word-break:break-word;line-height:1.5}
|
|
.gh-comment.tool .gh-comment-body{font-family:var(--mono);font-size:13px}
|
|
.chat-status{font-size:12px;color:var(--muted);line-height:1.5}
|
|
.chat-follow{position:sticky;bottom:8px;align-self:center;background:#fff;border:1px solid var(--line);color:var(--text);z-index:2}
|
|
.gh-comment-box{border:1px solid var(--line);border-radius:var(--radius);background:#fff;overflow:hidden}
|
|
.gh-comment-box textarea{border:0;border-radius:0;min-height:84px}
|
|
.gh-comment-box textarea:focus{box-shadow:none}
|
|
.gh-comment-footer{display:flex;justify-content:flex-end;gap:8px;padding:8px;border-top:1px solid var(--line);background:var(--subtle-bg)}
|
|
.conv-divider{border-top:1px solid var(--line);margin:4px 0}
|
|
/* Width-adaptive columns — independent column wrappers, NOT shared
|
|
grid rows. Why: the previous layout gave every section an explicit
|
|
grid-column AND grid-row, so one grid row's height was the tallest
|
|
section in that row. A tall task list in row 2 held the whole row
|
|
tall, and the conversation (row 3) started far below a short
|
|
dispatch box — align-items:start only kept each box at its own
|
|
content height, it never pulled the next row up. That is the
|
|
blank gap between modules. Now each .dash-col is one grid item
|
|
whose sections stack in a flex column with a 20px gap, so a module
|
|
always follows the previous module in its own column, whatever
|
|
the other columns' heights are. The only blank left is at the
|
|
bottom of a shorter column, which is normal for column layouts,
|
|
not a gap between two modules.
|
|
Medium (900-1399px): left = tasks + projects; right column =
|
|
middle wrapper (dispatch + conversation) followed by the right
|
|
wrapper (environments + Workers + skills + automations + triage +
|
|
admin + API Key), in that order. Wide (>=1400px): left / middle /
|
|
right wrappers side by side. .dash-cards spans all columns at
|
|
every grid width. Nothing is duplicated or hidden at any width. */
|
|
.dash-col{display:flex;flex-direction:column;gap:20px;min-width:0}
|
|
.dash-col > *{min-width:0}
|
|
/* Equal-height columns (wide/medium only; narrow stays a single
|
|
page-scrolled column, see the max-width:899px block): every column
|
|
is the same fixed height — viewport height minus the sticky
|
|
topbar, the data-cards row and page padding (260px, floored at
|
|
480px so short viewports still get a usable pane) — and scrolls
|
|
internally when its sections exceed it, instead of growing
|
|
indefinitely and leaving the other columns ending far above it.
|
|
Together with the capped task/API Key lists above, no single
|
|
list can push one column (and the page) to infinite height. */
|
|
@media (min-width:900px) and (max-width:1399px){
|
|
.dash-page{display:grid;grid-template-columns:320px minmax(0,1fr);align-items:stretch}
|
|
.dash-page > .dash-cards{grid-column:1 / -1;grid-row:1}
|
|
.dash-col{height:calc(100vh - 260px);min-height:480px;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain}
|
|
.dash-col-left{grid-column:1;grid-row:2}
|
|
.dash-col-mid{grid-column:2;grid-row:2}
|
|
.dash-col-right{grid-column:2;grid-row:3}
|
|
}
|
|
@media (min-width:1400px){
|
|
.dash-page{max-width:1560px;display:grid;grid-template-columns:310px minmax(0,1fr) 330px;align-items:stretch}
|
|
.dash-col{height:calc(100vh - 260px);min-height:480px;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain}
|
|
.dash-page > .dash-cards{grid-column:1 / -1;grid-row:1}
|
|
.dash-cards{grid-template-columns:repeat(6,1fr)}
|
|
.dash-col-left{grid-column:1;grid-row:2}
|
|
.dash-col-mid{grid-column:2;grid-row:2}
|
|
.dash-col-right{grid-column:3;grid-row:2}
|
|
}
|
|
@media (max-width:899px){ /* 899, not 900: narrow is strictly <900px, so 900px exactly already gets the 2-column grid + 3-per-row cards */
|
|
/* Narrow single column: unwrap the column wrappers so sections
|
|
stack as direct flex items of .dash-page, in the ORIGINAL order
|
|
(dispatch first), not in column-group order (tasks first).
|
|
Browsers without display:contents degrade to grouped stacking,
|
|
which is still tight — just in a different order. */
|
|
.dash-col{display:contents}
|
|
#sec-dispatch{order:1} #sec-tasks{order:2} #sec-conv{order:3}
|
|
#sec-projects{order:4} #sec-env{order:5} #sec-workers{order:6}
|
|
#sec-skills{order:7} #sec-automations{order:8} #sec-triage{order:9}
|
|
#sec-admin{order:10} #sec-key{order:11}
|
|
.dash-cards{grid-template-columns:repeat(2,1fr)}
|
|
.dash-hide-sm{display:none}
|
|
.dash-page{padding:14px}
|
|
.dash-section.card{padding:16px}
|
|
.card{padding:16px}
|
|
th:nth-child(2),td:nth-child(2),th:nth-child(3),td:nth-child(3),th:nth-child(7),td:nth-child(7){display:none}
|
|
}
|
|
@media (max-width:560px){
|
|
.dash-cards{grid-template-columns:1fr}
|
|
.dash-nav{flex-wrap:nowrap;overflow-x:auto}
|
|
.card{padding:16px}
|
|
th:nth-child(6),td:nth-child(6),th:nth-child(9),td:nth-child(9){display:none}
|
|
.bar > input[type="text"],.bar > input[type="password"],.bar > select{flex:1 1 100%}
|
|
th,td{padding:8px 12px}
|
|
}
|
|
|
|
/* Redesign shell (2026-10-30): replaces the old top-tab + stacked-page
|
|
layout. Sidebar + workspace grid, each pane scrolls on its own;
|
|
the page itself never scrolls as one long column. */
|
|
.shell{display:grid;grid-template-columns:260px minmax(0,1fr);height:100vh;background:#fff}
|
|
.shell-side{background:#f6f8fa;border-right:1px solid var(--line);display:flex;flex-direction:column;min-height:0;overflow-y:auto}
|
|
.shell-brand{font-weight:600;font-size:16px;padding:16px 16px 12px}
|
|
.shell-nav{display:flex;flex-direction:column;gap:16px;padding:0 12px 16px}
|
|
.shell-nav-group-label{font-size:12px;font-weight:600;color:var(--muted);padding:0 8px 6px}
|
|
.shell-nav-group{display:flex;flex-direction:column;gap:2px}
|
|
.shell-nav button{text-align:left;border:0;box-shadow:none;background:transparent;padding:8px;border-radius:var(--radius);font-weight:500}
|
|
.shell-nav button:hover{background:#fff}
|
|
.shell-nav button.active{background:var(--text);color:#fff}
|
|
.shell-stats{margin-top:auto;border-top:1px solid var(--line);padding:16px 12px}
|
|
.shell-stats-label{font-size:12px;font-weight:600;color:var(--muted);padding:0 4px 8px}
|
|
.shell-stats .dash-cards{display:flex;flex-direction:column;gap:8px}
|
|
.shell-stats .dash-card{padding:12px}
|
|
.shell-stats .dash-card-value{font-size:18px}
|
|
.shell-main{display:flex;flex-direction:column;min-width:0;min-height:0}
|
|
.shell-header{display:flex;gap:14px;align-items:center;flex-wrap:wrap;padding:12px 20px;border-bottom:1px solid var(--line);background:#fff}
|
|
.shell-header h1{font-size:16px;margin:0}
|
|
.shell-header .dash-status{font-size:13px;font-weight:600}
|
|
.shell-header .dash-status.ok{color:var(--success)}
|
|
.shell-stamp{margin-left:auto}
|
|
.workspace{display:grid;grid-template-columns:300px minmax(0,1fr) 360px;flex:1;min-height:0}
|
|
.workspace-rail,.workspace-center,.workspace-inspector{overflow-y:auto;padding:16px;min-width:0}
|
|
.workspace-rail{border-right:1px solid var(--line);background:#fff}
|
|
.workspace-rail h2,.workspace-conv h2{font-size:14px;margin:0 0 12px;font-weight:600}
|
|
.workspace-rail .issue-list{max-height:none}
|
|
.workspace-center{background:#fff;display:flex;flex-direction:column;gap:16px}
|
|
.composer-toggle{display:flex}
|
|
.workspace-conv{flex:1}
|
|
.workspace-inspector{border-left:1px solid var(--line);background:var(--subtle-bg)}
|
|
.workspace-inspector .detail-stack{display:flex;flex-direction:column;gap:12px}
|
|
.detail-tabs{display:flex;gap:4px;flex-wrap:wrap}
|
|
.detail-tabs button{padding:6px 12px;font-size:13px;font-weight:600}
|
|
.detail-tabs button.active{background:var(--text);color:#fff;border-color:var(--text)}
|
|
.page{flex:1;overflow-y:auto;padding:20px;display:flex;flex-direction:column;gap:20px;max-width:1100px;width:100%}
|
|
.page > *{min-width:0}
|
|
@media (max-width:1100px){
|
|
.shell{grid-template-columns:1fr;height:auto;min-height:100vh}
|
|
.shell-side{flex-direction:row;flex-wrap:wrap;align-items:flex-start;border-right:0;border-bottom:1px solid var(--line);overflow:visible}
|
|
.shell-nav{flex-direction:row;flex-wrap:wrap}
|
|
.shell-nav-group{flex-direction:row;align-items:center}
|
|
.shell-stats{display:none}
|
|
.shell-hide-sm{display:none}
|
|
.workspace{grid-template-columns:1fr}
|
|
.workspace-rail,.workspace-inspector{border:0;border-bottom:1px solid var(--line)}
|
|
}
|