/* 工作区壳体、目录、账户菜单与画布浮动标题;CSS Module 负责显示,账号/画布生命周期和侧栏开关由组件管理。 */ /* 侧栏宽度变量供侧栏本体和浮动标题共同消费,根容器至少占满动态视口高度。 */ .shell { --sidebar-width: 270px; display: flex; min-height: 100dvh; background: #fffefb; color: #37352f; } /* 侧栏插槽 sticky 固定在滚动视口顶部;裁剪展开过渡期间的内容,层级高于画布。 */ .sidebarSlot { position: sticky; top: 0; height: 100dvh; max-width: calc(100vw - 40px); flex: 0 0 auto; overflow: hidden; z-index: 30; } /* 侧栏采用纵向 flex,导航区可滚动、账户区留在底部;最大宽度给主区域保留至少 40px。 */ .sidebar { display: flex; flex-direction: column; width: var(--sidebar-width); max-width: calc(100vw - 40px); height: 100dvh; padding: 10px 10px 6px; background: #f8f7f5; border-right: 1px solid #edece9; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 14px; line-height: 20px; letter-spacing: -0.15px; color: #37352f; } /* 顶行按钮分居两端;搜索框 focus-within 让输入聚焦时整个框有反馈。 */ .topRow { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; color: #85817b; } .search { display: flex; align-items: center; gap: 7px; min-height: 32px; border: 1px solid #e6e3df; border-radius: 7px; padding: 4px 8px; color: #97938d; } .search:focus-within { border-color: #b2a292; box-shadow: 0 0 0 2px #b2a29218; } .search input { min-width: 0; width: 100%; padding: 0; background: transparent; border: 0; outline: none; font: inherit; color: #37352f; } .search input::placeholder { color: #9a9690; } /* flex:1 配合 min-height:0 才允许长目录在侧栏内部滚动。 */ .navigation { flex: 1; min-height: 0; overflow-y: auto; padding-top: 10px; } /* 首页与目录链接共用行高/图标间距,长标题省略;aria-current 对当前页提供选中背景。 */ .home, .pageLink { display: flex; align-items: center; gap: 8px; padding: 4px 8px; min-height: 30px; border-radius: 6px; font-weight: 450; } .home { width: fit-content; font-weight: 600; background: #ecebe8; } .pageLink { margin: 1px 0; } .pageLink svg { flex-shrink: 0; color: #87837c; } .pageLink span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .pageLink:hover, .pageLink[aria-current="page"] { background: #eae7e2; } /* 分组名称、空态提示和错误分别排版;错误允许在任意位置折行。 */ .sectionLabel { display: flex; justify-content: space-between; padding: 18px 7px 6px; color: #9b9690; font-size: 11px; font-weight: 400; letter-spacing: 0; } .hint { padding: 4px 8px; color: #9a948c; line-height: 1.6; font-size: 12px; } .error { margin: 6px 4px; font-size: 12px; color: #b14b3c; overflow-wrap: anywhere; } /* 账户区域向侧栏底部靠齐,按钮占满宽度以便整行点击。 */ .accountArea { margin-top: auto; padding-top: 6px; } .accountButton { display: flex; align-items: center; gap: 8px; padding: 6px 7px; min-height: 36px; width: 100%; border-radius: 6px; text-align: left; color: #37352f; } .accountButton:hover { background: #edeae5; } /* 头像固定尺寸并裁成圆形,图片 object-fit:cover;缺图时容纳首字占位。 */ .avatar { display: grid; place-items: center; flex: 0 0 24px; width: 24px; height: 24px; overflow: hidden; border-radius: 50%; background: #e8e0d6; color: #705844; font-size: 12px; font-weight: 600; } .avatar img { display: block; width: 100%; height: 100%; object-fit: cover; } .avatarLarge { flex-basis: 36px; width: 36px; height: 36px; font-size: 16px; } /* 账户文字允许收缩和省略,副文字在此布局隐藏。 */ .accountText { display: flex; flex: 1; flex-direction: column; min-width: 0; } .accountText strong { font-size: 13px; font-weight: 550; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .accountText small { display: none; } /* 原生 popover 的面板位置/宽度约束;自身可滚动且从左下角进入,不用 CSS 切换 open 状态。 */ .accountPopup { position: fixed; inset: auto auto 50px 8px; margin: 0; width: 300px; max-width: calc(100vw - 16px); max-height: calc(100dvh - 66px); overflow-y: auto; padding: 5px; color: #37352f; background: #fff; border: 1px solid #e9e7e3; border-radius: 11px; box-shadow: 0 4px 16px #19140d14, 0 12px 40px #19140d0a; font-family: inherit; font-size: 14px; line-height: 20px; letter-spacing: -0.15px; transform-origin: bottom left; } /* 仅 popover 打开时播放进入动画;backdrop 保持透明,但是否可交互仍由 popover 行为决定。 */ .accountPopup:popover-open { animation: account-enter 130ms ease-out; } .accountPopup::backdrop { background: transparent; } /* 菜单头、工作区字母头像及身份行共用纵向文字布局,长名称省略。 */ .accountHeading { display: flex; align-items: center; gap: 10px; padding: 8px 7px 10px; } .workspaceAvatar { display: grid; place-items: center; flex: 0 0 36px; height: 36px; border-radius: 7px; color: #72533e; background: #eee8df; font-size: 19px; font-weight: 600; } .accountHeading > div, .popupIdentity > div { display: flex; flex-direction: column; min-width: 0; gap: 1px; } .accountHeading strong { font-size: 14px; font-weight: 600; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .accountHeading small { color: #8b8780; font-size: 12px; } /* 菜单分组和身份区域提供内间距,邮箱允许断行;工作区列表限制高度后独立滚动。 */ .menuGroup { padding: 1px 0; } .popupIdentity { display: flex; align-items: center; gap: 8px; padding: 8px 7px 7px; } .popupIdentity strong { font-size: 12px; font-weight: 500; } .popupIdentity small { color: #8b8780; font-size: 11px; overflow-wrap: anywhere; letter-spacing: 0; } .workspaceList { max-height: min(220px, 30dvh); overflow-y: auto; } /* 菜单项整行可点,文字可收缩,图标保持宽度;disabled 态显式降低透明度。 */ .menuItem { display: flex; align-items: center; gap: 9px; width: 100%; min-height: 31px; padding: 5px 8px; border-radius: 5px; text-align: left; font-size: 13px; line-height: 20px; font-weight: 450; } .menuItem > span:not(.workspaceMini) { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .menuItem > svg { flex-shrink: 0; } .menuItem:hover { background: #f1f0ed; } .menuItem:disabled { opacity: 0.45; cursor: not-allowed; } /* 工作区小头像与新建/登出颜色区分,separator 分隔组而不引入额外布局容器。 */ .workspaceMini { display: grid; place-items: center; flex: 0 0 20px; height: 20px; border-radius: 4px; color: #82634c; background: #f1ebe3; font-size: 11px; font-weight: 600; } .newWorkspace { color: #2383e2; } .logout { color: #78746d; font-size: 12px; } .separator { height: 1px; margin: 6px 7px; background: #eeece8; } /* 左上浮动条以 --floating-left 定位;侧栏展开时偏移到侧栏右侧,位置和宽度作 240ms 过渡。 */ .floating { --floating-left: 12px; position: fixed; left: var(--floating-left); top: 12px; max-width: calc(100vw - var(--floating-left) - 12px); z-index: 40; transition: left 240ms cubic-bezier(0.22, 1, 0.36, 1), max-width 240ms cubic-bezier(0.22, 1, 0.36, 1); } /* 展开侧栏时使用实际受视口约束的侧栏宽度计算偏移;账户 popover 也继承同一偏移变量。 */ .floating[data-sidebar-collapsed="false"], .accountPopup[data-sidebar-collapsed="false"] { --floating-left: calc(min(var(--sidebar-width), calc(100vw - 40px)) + 12px); } /* 浮动条错误绝对定位于条下方,账户设置面板则沿用对话框容器。 */ .floatingError { position: absolute; left: 0; top: 42px; width: 240px; padding: 10px; background: white; border: 1px solid #e7e2db; border-radius: 8px; color: #b14b3c; font-size: 12px; } .settingsPanel { color: #37352f; border-color: #e6e2dc; border-radius: 12px; } /* 设置表单纵向排布身份、字段及操作;提交按钮区分主动作,禁用时保留位置。 */ .settingsForm { display: flex; flex-direction: column; gap: 16px; padding-top: 4px; } .settingsIdentity { display: flex; align-items: center; gap: 10px; font-size: 13px; color: #89837b; overflow-wrap: anywhere; } .settingsForm label { display: flex; flex-direction: column; gap: 6px; font-size: 13px; font-weight: 500; } .settingsForm input { padding: 8px 10px; width: 100%; border: 1px solid #e2ddd6; border-radius: 6px; background: #fff; color: #37352f; font: inherit; } .settingsActions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; } .settingsActions button { padding: 6px 12px; border: 1px solid #e2ddd6; border-radius: 6px; font-size: 13px; } .settingsActions button[type="submit"] { background: #37352f; color: white; border-color: #37352f; } .settingsActions button:disabled { opacity: 0.5; cursor: not-allowed; } /* 固定全视口画布置于底层;点阵背景与加载/错误状态由后续类分别承担。 */ .graph { position: fixed; inset: 0; z-index: 0; display: flex; width: 100%; height: 100dvh; background: #fffefb; } .graphSurface { width: 100%; height: 100%; background-image: radial-gradient(#b8aea245 1px, transparent 1px); background-size: 22px 22px; } .graphStatus { position: absolute; left: 50%; top: 72px; transform: translateX(-50%); max-width: calc(100vw - 48px); padding: 8px 12px; border-radius: 6px; background: #fffefbe6; color: #9a948c; text-align: center; font-size: 13px; } /* 账户菜单从轻微下移/缩小过渡到正常位置与不透明状态。 */ @keyframes account-enter { from { opacity: 0; transform: translateY(4px) scale(0.985); } to { opacity: 1; transform: translateY(0) scale(1); } } /* 较窄视口将侧栏目标宽度收为 240px;仍受上方 max-width 约束。 */ @media (max-width: 600px) { .shell { --sidebar-width: 240px; } } /* 减少动态效果偏好下关闭菜单进入动画;浮动条过渡在文件后部单独关闭。 */ @media (prefers-reduced-motion: reduce) { .accountPopup:popover-open { animation: none; } } /* 浮动条 logo 链接沿用 Toolbar 控件尺寸与键盘焦点样式,保证和旁边按钮对齐。 */ .logoLink { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; box-sizing: border-box; width: var(--toolbar-control-width, 32px); height: var(--toolbar-control-height, 32px); padding: 4px 6px; border-radius: 5px; } .logoLink img { display: block; width: var(--toolbar-icon-size, 20px); height: var(--toolbar-icon-size, 20px); } .logoLink:hover { background: #e9e7e3; } .logoLink:focus-visible { outline: 2px solid #9d7d66; outline-offset: 2px; } /* 浮动头像按钮同样使用共享尺寸;从浮动条打开的账户面板改为顶端定位。 */ .floatingAvatarButton { display: grid; place-items: center; flex: 0 0 auto; box-sizing: border-box; width: var(--toolbar-control-width, 32px); height: var(--toolbar-control-height, 32px); border-radius: 5px; } .floatingAvatarButton:hover { background: #e9e7e3; } /* clamp 把账户面板左边界限制在视口内;transform-origin 随顶部锚点改为左上。 */ .accountPopup[data-floating="true"] { inset: 62px auto auto clamp(8px, var(--floating-left, 12px), max(8px, calc(100vw - 308px))); max-height: calc(100dvh - 76px); transform-origin: top left; } /* 浮动头像采用图标尺寸,标题允许 flex 收缩但保留溢出区域给编辑错误提示。 */ .floatingAvatarButton .avatar { flex-basis: var(--toolbar-icon-size, 20px); width: var(--toolbar-icon-size, 20px); height: var(--toolbar-icon-size, 20px); font-size: 14px; } .floatingTitle { flex: 1 1 auto; min-width: 0; max-width: 240px; margin: 0; color: #37352f; font-size: 14px; line-height: var(--toolbar-control-height, 32px); font-weight: 500; overflow: visible; } /* 中等窄屏降低标题最大宽度,不改变标题内容或编辑状态。 */ @media (max-width: 700px) { .floatingTitle { max-width: 180px; } } /* 极窄且侧栏仍展开时隐藏 logo/标题/分隔,保留浮动条其余控件。 */ @media (max-width: 420px) { .floating[data-sidebar-collapsed="false"] .logoLink, .floating[data-sidebar-collapsed="false"] .floatingTitle, .floating[data-sidebar-collapsed="false"] > span[aria-hidden="true"] { display: none; } } /* 按用户偏好关闭浮动条位移/宽度过渡。 */ @media (prefers-reduced-motion: reduce) { .floating { transition: none; } } /* 递归目录清除列表默认缩进,层级缩进由组件布局提供;行本身允许标题收缩。 */ .directoryList { list-style: none; padding: 0; margin: 0; } .directoryRow { display: flex; align-items: center; min-width: 0; } .directoryRow .pageLink { flex: 1; min-width: 0; padding-left: 3px; } /* 可折叠项按钮与叶项占位共享 20px 列宽,保持各行标题对齐;焦点内描边不扩尺寸。 */ .directoryToggle, .directorySpacer { flex: 0 0 20px; width: 20px; height: 26px; } .directoryToggle { display: grid; place-items: center; border: 0; border-radius: 4px; background: transparent; color: #87837c; cursor: pointer; } .directoryToggle:hover { background: #eae7e2; } .directoryToggle:focus-visible { outline: 2px solid #9b877a; outline-offset: -2px; } .directoryToggle svg { transition: transform 120ms ease; }