/*@import '/_content/Microsoft.FluentUI.AspNetCore.Components/css/reboot.css';*/

/* DataGrid 定义选中行高光 */
.highlighted {
    background-color: var(--highlight-bg);
    color: #343434;
}

/* MainLayout 定义Content样式（原类选择器：content） */
.body-content {
    align-self: stretch;
    height: calc(100dvh - 80px) !important;
    display: flex;
    flex-direction: column;
    box-sizing: border-box;
}

/* EditPanelLayout 定义主布局样式*/
.panel-content {
    height: calc(100dvh - 142px) !important;
    display: flex;
}

.panel-tab-content {
    padding: 10px 20px;
    height: calc(100dvh - 186px);
    overflow: auto;
}

/* 重写样式 */
/* Tab 重写内容区域Padding */
.fluent-tab-panel {
    padding: 0 !important;
}

/* DataGrid 重写标题背景色 */
.fluent-data-grid tr[row-type=sticky-header] > th {
    background-color: var(--colorNeutralBackground1) !important;
}

/* ====== DataGrid 列头面板：列宽 / 列重排只用拖拽，隐藏面板里的两排按钮组 ====== */
/* 背景：列头面板 [col-header-ui] 由 FluentUI 自动拼装，顺序固定为
   「排序菜单 → ColumnOptions（本项目的筛选输入框）→ 调整列宽 → 重排序列」，
   其中后两块是「键盘/一键」辅助 UI。本项目要求列宽、列重排一律靠拖拽，故把这两块整块隐藏。
   拖拽能力不受影响（与这两块 UI 无关，由前端脚本独立驱动）：
     · 调宽 = ResizableColumns="true" ⇒ 每个 th 内的 [resize-handle] 可拖
     · 重排 = ReorderableColumns="true" ⇒ th[reorderable=true] 被脚本设为 draggable
   ⚠️ 隐藏钩子取自 FluentUI 5.0.1 的 ColumnResizeOptions / ColumnReorderOptions 标记
      （两者根节点都带 Class="my-3-o"）；升级 FluentUI 后需复核该 class 是否仍在。
   ⚠️ 若将来重新给 <FluentDataGrid> 设 ResizeType，「Column width」也会被本规则一并隐藏。 */
.fluent-data-grid [col-header-ui] .my-3-o {
    display: none;
}

/* 紧随这两块的分隔线一并隐藏，否则面板底部会残留一条空线
   （面板首尾分隔线的出现条件含「调整列宽或重排存在」，隐藏块后它就成了悬空分隔线）。 */
.fluent-data-grid [col-header-ui] > fluent-divider:has(+ .my-3-o) {
    display: none;
}

/* RadioGroup 重写边距 */
fluent-radio-group {
    margin: 0!important
}

.fluent-paginator {
    margin: 0 !important;
    padding: 0 !important;
}

body {
    --body-font: "Segoe UI Variable", "Segoe UI", sans-serif;
    font-family: var(--body-font);
    font-size: var(--type-ramp-base-font-size);
    line-height: var(--type-ramp-base-line-height);
    margin: 0;
}

.navmenu-icon {
  display: none;
}

.main {
  min-height: calc(100dvh - 80px);
  color: var(--neutral-foreground-rest);
  align-items: stretch !important;
}

.nav {
  align-self: stretch;
  height: calc(100dvh - 80px) !important;
  display: flex;
}

.content {
  padding: 0.5rem 1.5rem;
  align-self: stretch !important;
  width: 100%;
}

.manage {
  width: 100dvw;
}

.fluent-layout-item[area="footer"] {
  background: var(--neutral-layer-4);
  color: var(--neutral-foreground-rest);
  align-items: center;
  padding: 10px 10px;
}

  .fluent-layout-item[area="footer"] fluent-link {
    color: var(--neutral-foreground-rest);
    text-decoration: none;
  }

    .fluent-layout-item[area="footer"] fluent-link:focus {
      outline: 1px dashed;
      outline-offset: 3px;
    }

    .fluent-layout-item[area="footer"] fluent-link:hover {
      text-decoration: underline;
    }


.alert {
  border: 1px dashed var(--accent-fill-rest);
  padding: 5px;
}


#blazor-error-ui {
  background: lightyellow;
  bottom: 0;
  box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
  display: none;
  left: 0;
  padding: 0.6rem 1.25rem 0.7rem 1.25rem;
  position: fixed;
  width: 100%;
  z-index: 1000;
  margin: 20px 0;
}

  #blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
  }

.blazor-error-boundary {
  background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
  padding: 1rem 1rem 1rem 3.7rem;
  color: white;
}

  .blazor-error-boundary::before {
    content: "An error has occurred. "
  }

.loading-progress {
  position: relative;
  display: block;
  width: 8rem;
  height: 8rem;
  margin: 20vh auto 1rem auto;
}

  .loading-progress circle {
    fill: none;
    stroke: #e0e0e0;
    stroke-width: 0.6rem;
    transform-origin: 50% 50%;
    transform: rotate(-90deg);
  }

    .loading-progress circle:last-child {
      stroke: #1b6ec2;
      stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
      transition: stroke-dasharray 0.05s ease-in-out;
    }

.loading-progress-text {
  position: absolute;
  text-align: center;
  font-weight: bold;
  inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
}

  .loading-progress-text:after {
    content: var(--blazor-load-percentage-text, "Loading");
  }

code {
  color: #c02d76;
}

@media (max-width: 600px) {
  .header-gutters {
    margin: 0.5rem 3rem 0.5rem 1.5rem !important;
  }

  [dir="rtl"] .header-gutters {
    margin: 0.5rem 1.5rem 0.5rem 3rem !important;
  }

  .main {
    flex-direction: column !important;
    row-gap: 0 !important;
  }

  nav.sitenav {
    width: 100%;
    height: 100%;
  }

  #main-menu {
    width: 100% !important;
  }

    #main-menu > div:first-child:is(.expander) {
      display: none;
    }

  .navmenu {
    width: 100%;
  }

  #navmenu-toggle {
    appearance: none;
  }

    #navmenu-toggle ~ nav {
      display: none;
    }

    #navmenu-toggle:checked ~ nav {
      display: block;
    }

  .navmenu-icon {
    cursor: pointer;
    z-index: 10;
    display: block;
    position: absolute;
    top: 15px;
    left: unset;
    right: 20px;
    width: 20px;
    height: 20px;
    border: none;
  }

  [dir="rtl"] .navmenu-icon {
    left: 20px;
    right: unset;
  }
}

/* ============ 横向标签带：MenuBar 顶部菜单条 与 MainLayout 底部页签条 共用 ============ */
/* 活动态下划线一律画在【外层元素】上：FluentButton 是 Web Component，
   内部 shadow DOM 固化了字体/颜色，从外部改不动，指示器只能落在宿主或外层 div 上。 */
.tab-strip {
  display: flex;
  align-items: stretch;
  gap: 2px;
  flex: 0 0 auto;
}

/* 单个标签 */
.tab-strip-item {
  display: flex;
  align-items: center;
  border-bottom: 2px solid transparent;
}

.tab-strip-item.is-active {
  border-bottom-color: var(--colorBrandBackground);
}

.tab-strip-btn {
  white-space: nowrap;
  font-size: var(--fontSizeBase300);
  min-width: 0;
}

/* 活动标签加粗 + 品牌色（best-effort：若 shadow DOM 内部固化了字体，则仅剩上方下划线生效） */
.tab-strip-item.is-active .tab-strip-btn {
  font-weight: var(--fontWeightSemibold);
  color: var(--colorBrandForeground1);
}

/* ==================== MenuBar 专属：容器装饰 ==================== */
.menu-bar {
  padding: 0 6px;
  background-color: var(--colorNeutralBackground2);
  overflow-x: auto;
  overflow-y: hidden;
}

/* ==================== 排产看板（ScheduleBoardView）：横向并排的中心列（左日期轴 / 右工单块） ==================== */
/* 版面：各工作中心横向并排成列（列宽固定，不铺满整宽）；列内左 = 只读日期轴、右 = 工单块堆叠。
   两栏共用同一 scale 与同一纵向起点，块首尾相接且无间隙 ⇒ 块边界与左侧刻度严格对齐。 */
.sb-board {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: 22px;
  padding: 6px 4px 14px;
  overflow-x: auto;

  /* 看板专属高亮色 —— ⚠️ 刻意【不】复用 DataGrid 的 --highlight-bg：那个变量的语义是「表格选中行」，
     与看板块命中是两码事，耦合在一起会导致以后想单独调看板配色却动到表格。
     变量挂在本容器上（只作用于看板子树，不污染 :root），要调色只改这三个值即可。 */
  --sb-match-background: #fff2b8;
  --sb-match-foreground: #1f1f1f;
  --sb-match-border: #d9a400;
}

/* 一个工作中心 = 一列：列宽固定（左轴 78 + 右块 168），不随容器拉伸 */
.sb-column {
  display: flex;
  flex-direction: column;
  flex: 0 0 auto;
  gap: 4px;
  width: 246px;
}

/* 「未分配」列：没有产能轴，宽度收缩为块宽，用虚线隔开 */
.sb-column-unassigned {
  width: auto;
  margin-left: 14px;
  padding-left: 14px;
  border-left: 1px dashed var(--colorNeutralStroke1);
}

.sb-column-head {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.sb-column-title,
.sb-column-meta {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sb-column-title {
  font-weight: 600;
}

.sb-column-meta {
  font-size: 12px;
  color: var(--colorNeutralForeground3);
}

/* 列体：高度由组件内联下发（= max(总产能, 排产总量) × scale + 列尾投放带） */
.sb-column-body {
  display: flex;
  align-items: stretch;
  position: relative;
}

/* 左栏：日期轴。刻度用 top 像素定位 —— 定位点就是该日的起点，与右侧块的分界线落在同一条 y 上。
   刻度读数 = 日期文字的【顶边】；日界线另由 .sb-tick::before 的 1px 顶线画出（两者同在 y=0，严格重合）。 */
.sb-axis {
  position: relative;
  flex: 0 0 78px;
  width: 78px;
}

.sb-tick {
  position: absolute;
  left: 0;
  width: 100%;
}

/* 日界线：1px 顶线，落在 .sb-tick 的定位点上（= 该日起点，与右侧块的分界同一 y）。
   ⚠️ 必须用【绝对定位伪元素】而不是 border-top —— 伪元素脱离文档流、不占高度、不挤压日期文字，
   加线前后文字位置零偏移；改用 border-top 会让盒子整体下移 1px，标签顶边就不再等于日界。
   画在所有刻度格上（含因过密而未显示文字的格）：线表达「日界」本身，与文字是否画得下无关。
   颜色 = .sb-block 的边框色（BrandStroke1）：线与块的顶边接成同一条，视觉上把「轴」和「块」串起来。 */
.sb-tick::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 1px;
  background-color: var(--colorBrandStroke1);
}

.sb-tick-date,
.sb-tick-cap {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
  line-height: 16px;
}

.sb-tick-date {
  color: var(--colorNeutralForeground1);
}

.sb-tick-cap {
  color: var(--colorNeutralForeground3);
}

/* 右栏：工单块堆叠。块高由组件内联下发（= 排产数量 × scale），块间无间隙以保住刻度对齐 */
.sb-blocks {
  display: flex;
  flex-direction: column;
  flex: 0 0 168px;
  width: 168px;
}

/* 工单块：块内只放 销售订单号 / 工单明细号 / 数量 / 交期 四行。
   ⚠️ 块高严格 = 排产数量 × scale（组件内联下发，不设 min-height，否则块与刻度错位），
   故行数超出块高时由 overflow:hidden 从【末行】开始裁 —— 查看全部信息请用悬停提示。 */
.sb-block {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  width: 100%;
  overflow: hidden;
  padding: 5px 8px;
  border: 1px solid var(--colorBrandStroke1);
  border-radius: 4px;
  background-color: var(--colorBrandBackground2);
  cursor: grab;
}

.sb-block-unassigned {
  border-style: dashed;
  border-color: var(--colorNeutralStroke1);
  background-color: var(--colorNeutralBackground3);
}

.sb-block-inner {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.sb-block-line {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
  line-height: 16px;
  color: var(--colorNeutralForeground1);
}

.sb-block-qty {
  font-weight: 600;
}

/* 命中右侧树所选订单的块：换背景 / 边框 / 文字色（比表格行高亮多一个描边，块密集堆叠时更跳得出来）。
   ⚠️ 只改颜色，不动任何尺寸（padding / min-height / border-width 都不能碰）—— 块高必须严格 = 数量 × scale，
   否则该块之后的全部块与左侧日期刻度会一起错位。
   配色变量定义在 .sb-board 上（见该规则内注释），主题无关：背景是浅黄、文字钉深色，故深浅主题都可读。 */
.sb-block.sb-match {
  background-color: var(--sb-match-background);
  border-color: var(--sb-match-border);
}

.sb-block.sb-match .sb-block-line {
  color: var(--sb-match-foreground);
}

/* 列尾投放区：纵向排在最后，flex 撑满剩余高度，承接「追加到本列末尾」 */
.sb-tail {
  box-sizing: border-box;
  flex: 1 1 auto;
  min-height: 18px;
  border-radius: 4px;
}

/* 落点预示：拖动悬停到某块 / 列尾投放区时，顶部粗线 = 「松手后插到它之前」
   （顺序由 ScheduleItemService.Reorder 决定：块拖到 B 上即插到 B 前；插到 B 后就拖到 B 的下一个块，或拖到列尾） */
.sb-block[dragged-over],
.sb-tail[dragged-over] {
  /* 覆盖 FluentUI 对 [dragged-over] 的全局默认：opacity .6 让整块发虚、blinker 闪烁干扰视线，
     且它把前景色改成 Foreground4（浅色主题下块内文字几乎看不见） */
  opacity: 1;
  animation: none;
  color: var(--colorNeutralForeground1);
}

.sb-block.sb-insert {
  box-shadow: inset 0 3px 0 var(--colorBrandStroke1);
  background-color: var(--colorBrandBackground2Hover);
}

.sb-tail.sb-insert {
  box-shadow: inset 0 3px 0 var(--colorBrandStroke1);
}

/* ====== 表单提交加载态：静态 SSR 下替代 FluentButton 的 Loading 参数 ======
   Login 等 Account 页面恒为静态 SSR（该目录 _Imports.razor 带 [ExcludeFromInteractiveRouting]），
   页面没有 Blazor 电路 ⇒ FluentButton 的 Loading / OnClick 永远不会翻转，点击后到表单 POST
   返回之前毫无反馈。改由 wwwroot/js/form-submit-loading.js 在 submit 时给被点按钮加 .btn-loading，
   这里只负责「按需把转圈显示出来」——按钮内需放 <span class="btn-spinner" aria-hidden="true"></span>，
   默认 display:none ⇒ 未提交时对现有布局零影响（display:none 的 flex 项不占位、不产生 gap）。 */
.btn-spinner {
  display: none;
  flex: none;
  align-self: center;
  vertical-align: middle;
  box-sizing: border-box;
  width: 15px;
  height: 15px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  opacity: 0.9;
  animation: btn-spinner-rotate 0.6s linear infinite;
}

fluent-button.btn-loading {
  pointer-events: none;
  opacity: 0.85;
}

fluent-button.btn-loading .btn-spinner {
  display: inline-block;
}

@keyframes btn-spinner-rotate {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

/* ==================== 电路控制台：会话监测页的整页控制台视图 ==================== */
/* 刻意不模拟真实终端配色：全部走 Fluent 主题 token ⇒ 深色主题自动反白、浅色主题白底黑字。 */
.circuit-console {
  height: 100%;
  overflow: auto;
  padding: 8px 12px;
  background-color: var(--colorNeutralBackground1);
  color: var(--colorNeutralForeground1);
  font-family: var(--fontFamilyMonospace);
  font-size: var(--fontSizeBase200);
  line-height: 1.5;
}

.circuit-console-line {
  display: flex;
  gap: 8px;
  white-space: pre-wrap;
  word-break: break-word;
}

.circuit-console-time {
  flex: none;
  color: var(--colorNeutralForeground3);
  user-select: none;
}

.circuit-console-text {
  flex: 1 1 auto;
  min-width: 0;
}

/* EF Core 的数据库日志（含真正的 SQL）单独着色 ⇒ 一眼看出每一步的读写 */
.circuit-console-line.is-db .circuit-console-text {
  color: var(--colorBrandForeground1);
}

.circuit-console-line.is-error .circuit-console-text,
.circuit-console-line.is-error .circuit-console-time {
  color: var(--colorPaletteRedForeground1);
}

.circuit-console-note {
  color: var(--colorNeutralForeground3);
  font-style: italic;
}

/* ====== 语言切换：Header 右上角「语言」图标按钮的浮层（CultureSelector / FluentPopover） ====== */
/* 浮层内容 = 一列语言项。fluent-anchor-button 是 Web Component，宿主默认 inline-flex + 主轴居中；
   外层文档针对「宿主元素」的声明优先于其 shadow 里的 :host 规则，故这里直接改宽度与对齐即可生效。 */
.lang-menu {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.lang-menu fluent-anchor-button {
  width: 100%;
  justify-content: flex-start;
}

/* 文字与对勾同处 content 槽位：先把槽位撑满再靠左，语言名才能贴着左侧对齐 */
.lang-menu fluent-anchor-button::part(content) {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  width: 100%;
  text-align: start;
}

/* 对勾槽位固定 16px：有无对勾都不改变文字起点，切换语言后文字不会横向跳动 */
.lang-menu-check {
  display: inline-flex;
  flex: none;
  justify-content: center;
  width: 16px;
  margin-inline-end: 6px;
}

/* ====== 图片预览视图（OssImagePreviewView）：100% 缩放基准 = 控件（主数据区）高度 ====== */
.oip-viewport {
  display: flex;
  align-items: flex-start;
  width: 100%;
  height: 100%;
  overflow: auto;
}

/* FluentImage 的根元素（fluent-image；v5.0.0 未随包附带该元素样式）= 缩放后的「画布」：
   height 由 Style 参数下发（Zoom% × 显示区高度 ⇒ Zoom=100 时画布高 = 主数据区高），
   宽度取 max-content 让画布恰好裹住图片，且 flex 不收缩 ⇒ 【溢出体就是滚动容器的直接子元素】，
   滚动条由它的 box 撑出，不依赖「内层 img 溢出定高 flex 容器」的跨轴溢出传播
   （那类传播在不同引擎/版本上表现不一致，曾出现放大后没有滚动条）。 */
.oip-image {
  flex: 0 0 auto;
  display: block;
  width: max-content;
  min-width: 100%;
  margin: 0 auto;
}

/* 内部 img（FluentImage 固定类名 fluent-image-item）：高度填满画布，宽度按原始纵横比自适应；
   margin:0 auto 让比画布窄的图片（如竖长图）水平居中。 */
.oip-image .fluent-image-item {
  display: block;
  width: auto;
  height: 100%;
  max-width: none;
  margin: 0 auto;
}

/* 加载态 / 错误提示：容器 align-items 取 flex-start（防溢出时起始侧滚不到），
   这两个状态靠 auto 外边距在两个方向居中 */
.oip-viewport fluent-spinner,
.oip-error {
  margin: auto;
}

.oip-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 24px;
  color: var(--error, #d13438);
}
/* ====== 规章制度（HrRegulation）：Markdown 预览纸张 ====== */
/* 预览态 = 主数据区里放一张「纸」：外层滚动、纸张定宽居中。
   纸张宽度取 min(880px, 100% - 32px)：窄屏时留 16px 边距，宽屏时保持接近 A4 的阅读行宽。 */
.rgd-scroll {
  width: 100%;
  height: 100%;
  overflow: auto;
  background: var(--colorNeutralBackground3);
}

.rgd-paper {
  box-sizing: border-box;
  width: min(880px, calc(100% - 32px));
  margin: 16px auto;
  padding: 36px 48px 48px;
  background: var(--colorNeutralBackground1);
  border: 1px solid var(--colorNeutralStroke1);
  border-radius: 6px;
  box-shadow: 0 2px 8px rgb(0 0 0 / 8%);
  color: var(--colorNeutralForeground1);
}

/* 文档头：编号小字 → 名称大字居中 → 元信息一行；下沿用双线模仿受控文件的表头分隔 */
.rgd-head {
  padding-bottom: 14px;
  margin-bottom: 22px;
  border-bottom: 3px double var(--colorNeutralStroke1);
}

.rgd-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}

/* 正文为空时的占位：只在纸张里留一句灰字，不套 MarkdownView（空串渲染出来是空 div，看不出是「没内容」） */
.rgd-empty {
  padding: 40px 0;
  text-align: center;
  font-size: 13px;
  color: var(--colorNeutralForeground3);
}

.rgd-head-code {
  font-size: var(--fontSizeBase200);
  letter-spacing: .04em;
  color: var(--colorNeutralForeground3);
}

.rgd-head-title {
  margin: 6px 0 10px;
  font-size: 24px;
  font-weight: 600;
  line-height: 1.3;
  text-align: center;
}

.rgd-head-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 18px;
  font-size: var(--fontSizeBase200);
  color: var(--colorNeutralForeground3);
}

/* ====== Markdown 正文（MarkdownView）：制度文档排版 ====== */
/* 1.8 行距 + 14px 字号：制度正文以中文长段为主，行距偏宽便于逐条核对；
   首末子元素去掉外边距，让纸张内边距成为唯一留白来源（不在纸内出现双倍空白）。 */
.md-body {
  font-size: 14px;
  line-height: 1.8;
  overflow-wrap: break-word;
}

.md-body > :first-child {
  margin-top: 0;
}

.md-body > :last-child {
  margin-bottom: 0;
}

.md-body h1,
.md-body h2,
.md-body h3,
.md-body h4,
.md-body h5,
.md-body h6 {
  margin: 1.6em 0 .6em;
  font-weight: 600;
  line-height: 1.35;
}

.md-body h1 { font-size: 20px; }
.md-body h2 { font-size: 18px; }
.md-body h3 { font-size: 16px; }
.md-body h4 { font-size: 15px; }
.md-body h5,
.md-body h6 { font-size: 14px; }

.md-body p {
  margin: .7em 0;
}

.md-body ul,
.md-body ol {
  margin: .7em 0;
  padding-left: 1.8em;
}

.md-body li {
  margin: .2em 0;
}

/* 嵌套列表不再叠加段间距，否则多级条款之间会散开 */
.md-body li > ul,
.md-body li > ol,
.md-body li > p {
  margin: .2em 0;
}

/* 表格：制度正文的主角（职责矩阵 / 修订记录 / 评分表），全宽 + 单元格竖向居中，
   表头底色用 neutralBackground3，与正文区分但不抢眼。 */
.md-body table {
  width: 100%;
  margin: .9em 0;
  border-collapse: collapse;
  font-size: 13px;
}

.md-body th,
.md-body td {
  padding: 6px 10px;
  border: 1px solid var(--colorNeutralStroke1);
  vertical-align: top;
  text-align: left;
}

.md-body thead th {
  background: var(--colorNeutralBackground3);
  font-weight: 600;
}

.md-body blockquote {
  margin: .9em 0;
  padding: .2em .9em;
  border-left: 3px solid var(--colorBrandStroke1);
  color: var(--colorNeutralForeground3);
}

.md-body code {
  padding: 1px 4px;
  border-radius: 3px;
  background: var(--colorNeutralBackground3);
  font-family: var(--fontFamilyMonospace);
  font-size: 12px;
}

.md-body pre {
  overflow: auto;
  margin: .9em 0;
  padding: 10px 12px;
  border-radius: 4px;
  background: var(--colorNeutralBackground3);
}

.md-body pre code {
  padding: 0;
  background: none;
}

.md-body hr {
  margin: 20px 0;
  border: none;
  border-top: 1px solid var(--colorNeutralStroke1);
}

.md-body a {
  color: var(--colorBrandForeground1);
}

.md-body img {
  max-width: 100%;
}

/* ====== BOM 重新排序：SortableList 行版式 + 序号计数器 ====== */
/* 序号不存进数据再渲染，而由 CSS 计数器跟随 DOM：拖动过程中 SortableJS 直接挪节点，
   计数器即时跟随，不会出现「松手才跳号」的空窗；提交时以 C# 侧列表位置重新编号，二者同序。 */
.bom-sort-list {
  counter-reset: bom-sort;
  --fluent-sortable-list-item-padding: 0;
  --fluent-sortable-list-item-background-color: var(--colorNeutralBackground1);
  width: 100%;
  padding: 6px 10px;
  box-sizing: border-box;
}

.bom-sort-list .sortable-item {
  counter-increment: bom-sort;
}

.bom-sort-row {
  display: grid;
  /* 左侧信息簇：拖柄 | 序号 | 编码 | 名称（固定）| 规格（吃满余量）| 颜色 | 用量。
     余量只给规格，让它尽量宽；颜色与用量同为右侧固定窄列并右对齐。 */
  grid-template-columns: 24px 40px 120px 180px minmax(160px, 1fr) 100px 110px;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 32px;
  padding: 0 8px;
  box-sizing: border-box;
  font-size: 13px;
  color: var(--colorNeutralForeground1);
}

.bom-sort-grab {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--colorNeutralForeground3);
  cursor: grab;
}

.bom-sort-grab:active {
  cursor: grabbing;
}

.bom-sort-seq {
  font-variant-numeric: tabular-nums;
  text-align: right;
  color: var(--colorNeutralForeground3);
}

.bom-sort-seq::before {
  content: counter(bom-sort) ".";
}

.bom-sort-code,
.bom-sort-name,
.bom-sort-spec,
.bom-sort-color,
.bom-sort-qty {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bom-sort-code {
  font-family: var(--fontFamilyMonospace);
}

.bom-sort-color,
.bom-sort-qty {
  color: var(--colorNeutralForeground2);
  text-align: right;
}

/* ====== 无访问权限（NotAuthorizedView）：已登录但缺角色时的页内提示 ======
   同一套类服务两处，故这里不写死高度、不写死定位：
   · 交互式路由（Routes.razor 的 NotAuthorized + MainLayout）—— 父级 .body-content 内
     那一格是 flex 伸展出来的确定高度，min-height:100% 即可在内容区垂直居中；
   · 静态 SSR 的 /Account/AccessDenied（LoginLayout）—— 页面级居中由布局自身完成，
     此处 min-height 退化为 0，不影响排布。 */

.not-authorized {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100%;
    padding: 24px;
    box-sizing: border-box;
}