/*
 * design/themes/base-form.css —— 表单层结构基线（可引用样式层）
 *
 * 分工：本文件只写「结构与状态」——布局骨架、控件盒模型、状态类；
 * 颜色、字体、圆角、阴影等外观一律走 CSS 变量，由单一主题文件提供：
 *   <name>-form.css 在 body[data-style="<name>"] 上定义：
 *   --font --bg --surface --border --ink --ink-2 --ink-3
 *   --accent --accent-ink --danger --danger-ring
 *   --ctl-h --btn-h --ctl-radius --panel-radius --chip-radius
 *   --focus-ring --opt-hover --filter-row-bg --shadow-1 --shadow-2
 * 本文件不出现具体颜色（所有变量都带灰阶兜底，缺主题时可用但无风格）。
 *
 * 零 JS 契约：本层不含任何脚本依赖，不依赖任何演示内核（lab-core/shell-core）。
 * 交互（下拉开合、弹窗开合、校验触发）由消费方自行接线：把状态类
 * （.is-open/.is-invalid/.is-covered…）挂到对应节点即可。
 *
 * 命名空间契约：组件类统一 ui-* 前缀或领域前缀（kv- / q- / dd- / f- / tier-）。
 */

* { box-sizing: border-box; }

html, body { margin: 0; padding: 0; }

body {
  font-family: var(--font, system-ui, sans-serif);
  background: var(--bg, #f5f5f5);
  color: var(--ink, #222);
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* 页面标题（可选契约：消费方页面 h1 直接挂此类） */
.ui-page-title { margin: 0 0 6px; font-size: 24px; line-height: 1.25; }

/* ---------- 面板（表面卡） ---------- */
.ui-panel {
  background: var(--surface, #fff);
  border: 1px solid var(--border, #e0e0e0);
  border-radius: var(--panel-radius, 8px);
  padding: 16px;
  box-shadow: var(--shadow-1, none);
  margin-bottom: 14px;
}

.ui-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 920px) { .ui-grid2 { grid-template-columns: 1fr; } }

.ui-panel-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.ui-panel-head h3 { margin: 0; font-size: 15px; }
.ui-panel-head > div { display: flex; align-items: center; gap: 8px; }
.ui-panel-sub { margin: 0; color: var(--ink-2, #666); font-size: 13px; }

.ui-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 12px 0 0; }
.ui-note { margin: 8px 0 0; font-size: 12.5px; color: var(--ink-2, #666); }

.ui-banner {
  margin: 0 0 12px;
  padding: 8px 12px;
  border: 1px dashed var(--border, #ccc);
  border-radius: 6px;
  font-size: 12.5px;
  color: var(--ink-2, #555);
  background: transparent;
}
.ui-banner--lock { border-style: solid; }

.ui-readonly-chip { font-size: 12px; padding: 3px 10px; border-radius: 999px; border: 1px solid var(--border, #ccc); color: var(--ink-2, #666); white-space: nowrap; }

/* ---------- 按钮骨架（皮肤在主题里） ---------- */
.ui-btn {
  display: inline-flex; align-items: center; justify-content: center;
  height: var(--btn-h, 32px);
  padding: 0 16px;
  border-radius: var(--ctl-radius, 4px);
  border: 1px solid transparent;
  font: inherit; font-weight: 600; font-size: 14px;
  cursor: pointer;
  white-space: nowrap;
}
.ui-btn-sm { height: calc(var(--btn-h, 32px) - 4px); padding: 0 12px; font-size: 13px; }
/* 变体皮肤（ui-btn-primary / ui-btn-secondary）由主题文件提供 */

/* ---------- kv 键值块（只读呈现的统一形态） ---------- */
.kv-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px 16px; margin: 0 0 10px; }
@media (max-width: 900px) { .kv-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .kv-grid { grid-template-columns: 1fr; } }
.kv { min-width: 0; }
.kv--wide { grid-column: 1 / -1; }
.kv-k { display: block; font-size: 12px; color: var(--ink-3, #888); margin-bottom: 1px; }
.kv-v { display: block; font-weight: 600; font-size: 14px; color: var(--ink, #222); word-break: break-all; }

/* ---------- 表头筛选表 ---------- */
.q-table-wrap { overflow-x: auto; border: 1px solid var(--border, #e0e0e0); border-radius: var(--ctl-radius, 4px); }
.q-table { border-collapse: separate; border-spacing: 0; width: 100%; min-width: 880px; }
.q-table th, .q-table td { text-align: left; padding: 8px 10px; font-size: 13px; vertical-align: middle; }
.q-head-row th { font-weight: 700; white-space: nowrap; }
.q-filter-row th { padding: 6px 8px; background: var(--filter-row-bg, rgba(0, 0, 0, .03)); }
.q-fcell { position: relative; display: flex; align-items: center; min-width: 132px; }
.q-fcell input[type="text"], .q-fcell input[type="date"] {
  width: 100%; height: var(--ctl-h, 32px);
  padding-right: 28px; padding-left: 8px;
}
.q-fcell .dd { flex: 1; width: 100%; }
.q-x {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  width: 20px; height: 20px; border-radius: 50%;
  border: none; background: transparent; color: var(--ink-3, #888);
  font-size: 13px; line-height: 1; cursor: pointer; display: none;
  align-items: center; justify-content: center; padding: 0;
}
.q-fcell--dd .q-x { right: 30px; } /* 下拉那支：× 在三角命中条带左侧 */
.q-x.is-on { display: inline-flex; }
.q-x:hover { color: var(--danger, #c00); }
.q-empty { text-align: center; color: var(--ink-3, #888); padding: 22px 10px; }
.q-amount b { display: block; }
.q-amount small { color: var(--ink-3, #888); font-size: 12px; }

.q-table-meta { margin-top: 8px; }

/* ---------- 状态徽标（三态皮肤在主题里：is-draft / is-sent / is-expired） ---------- */
.q-badge {
  display: inline-block; padding: 2px 10px;
  font-size: 12px; font-weight: 600; border-radius: 999px;
  white-space: nowrap;
}

/* ---------- 下拉（零 JS：面板默认锚定本体下方，纯 CSS 即可呈现） ---------- */
.dd { position: relative; width: 100%; }
.dd-body {
  display: flex; align-items: stretch; justify-content: space-between;
  width: 100%; height: var(--ctl-h, 32px);
  padding: 0 0 0 10px; margin: 0;
  font: inherit; font-size: 13.5px; color: var(--ink, #222);
  background: var(--surface, #fff);
  border: 1px solid var(--border, #ccc);
  border-radius: var(--ctl-radius, 4px);
  cursor: pointer;
}
.dd-value { flex: 1; min-width: 0; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: calc(var(--ctl-h, 32px) - 2px); }
.dd-value.is-placeholder { color: var(--ink-3, #999); font-weight: 400; }
.dd-tri { display: flex; align-items: center; justify-content: center; width: 28px; flex: none; font-size: 11px; color: var(--ink-2, #666); }

/* 面板默认锚定本体（left:0 + min-width:100%＝面板可宽于本体）。
 *
 * ⚠ 已知边界（滚动容器裁剪）：absolute 面板会被 overflow:auto/scroll 的祖先容器
 * （.q-table-wrap、弹窗 body、任何滚动盒）按其可视范围裁剪——面板高度大于容器
 * 剩余空间时下半截不可见、容器内出现滚动条。原 style-lab 内核用「面板挂 body +
 * position:fixed」规避的正是这个；本层为保零 JS 默认形态放弃了自动 fixed，消费方必须知情：
 *   - 短表 / 贴近容器底的 dd 必裁（长表因筛选行下方有表体让位而不易察觉），
 *     复现用例见 demos/dd-clipping.html（预期表现已标注）；
 *   - 不想裁剪：给面板加 data-dd-portal（见下方钩子规则）并接入自己的定位脚本，
 *     可整段复制的最小配方见 README「已知问题 1」。
 */
.dd-panel {
  position: absolute; top: calc(100% + 4px); left: 0;
  z-index: 1200;
  display: flex; flex-direction: column;
  min-width: 100%; max-width: min(420px, 92vw);
  background: var(--surface, #fff);
  border: 1px solid var(--border, #ccc);
  border-radius: var(--ctl-radius, 6px);
  box-shadow: var(--shadow-2, 0 8px 20px rgba(0, 0, 0, .14));
  overflow: hidden;
}
/* 逃生舱钩子：面板转 fixed 脱离滚动容器的裁剪（面板可原地留在 .dd 内，fixed 相对视口定位；
   也可由脚本把面板挂到 body）。坐标与 min-width 由定位脚本给——最小配方见 README「已知问题 1」。 */
.dd-panel[data-dd-portal] { position: fixed; min-width: 0; }
.dd-panel[hidden] { display: none; }
.dd-search {
  height: 34px; border: none; outline: none; background: transparent;
  border-bottom: 1px solid var(--border, #eee);
  padding: 0 12px; font: inherit; font-size: 13px; color: var(--ink, #222);
}
.dd-list { list-style: none; margin: 0; padding: 4px; max-height: 236px; overflow-y: auto; }
.dd-opt {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  height: 32px; padding: 0 10px; border-radius: calc(var(--ctl-radius, 6px) - 1px);
  cursor: pointer; font-size: 13.5px;
}
.dd-opt:hover { background: var(--opt-hover, rgba(0, 0, 0, .05)); }
.dd-check { opacity: 0; font-weight: 700; color: var(--accent, #06c); }
.dd-opt.is-sel .dd-check { opacity: 1; }
.dd-empty { padding: 10px; color: var(--ink-3, #999); font-size: 13px; text-align: center; }
/* 检索光晕压住本体：面板被检索框聚焦时套主色光晕，上沿叠在触发体上 */
.dd-panel.is-searching { box-shadow: 0 0 0 3px var(--focus-ring, rgba(0, 102, 204, .25)), var(--shadow-2, 0 8px 20px rgba(0, 0, 0, .14)); border-color: var(--accent, #06c); }

/* ---------- 表单骨架 ---------- */
.f-form { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 16px; margin: 0; }
@media (max-width: 720px) { .f-form { grid-template-columns: 1fr; } }
.f-field { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.f-field--tiers, .f-field:has(.f-radios), .f-field:has(.f-textarea), .f-field:has(.kv-grid) { grid-column: 1 / -1; }
.f-label { font-size: 12.5px; color: var(--ink-2, #555); font-weight: 600; }
.f-req { color: var(--danger, #d33); margin-left: 2px; }
.f-hint { margin: 0; font-size: 12px; color: var(--ink-3, #8a8a8a); }
.f-error { margin: 0; font-size: 12.5px; color: var(--danger, #d33); }

.f-form input[type="text"], .f-form input[type="number"], .f-form input[type="date"], .f-textarea,
.f-form .dd-body {
  width: 100%;
  font: inherit; font-size: 13.5px; color: var(--ink, #222);
  background: var(--surface, #fff);
  border: 1px solid var(--border, #bbb);
  border-radius: var(--ctl-radius, 4px);
}
.f-form input[type="text"], .f-form input[type="number"], .f-form input[type="date"] { height: var(--ctl-h, 32px); padding: 0 10px; }
.f-textarea { padding: 8px 10px; resize: none; font-family: inherit; line-height: 1.5; } /* 全站禁拖拽改大小 */

.f-radios { display: flex; gap: 18px; flex-wrap: wrap; min-height: var(--ctl-h, 32px); align-items: center; }
.f-radio { display: inline-flex; align-items: center; gap: 6px; font-size: 13.5px; cursor: pointer; }
.f-radio input { accent-color: var(--accent, #06c); width: 15px; height: 15px; margin: 0; }

/* 独立单行控件（不在 .f-form 网格内的输入框 / 筛选行 / 控件总览用） */
.ui-in, .ui-in-num, .q-fcell input[type="text"], .q-fcell input[type="date"] {
  font: inherit; font-size: 13.5px; color: var(--ink, #222);
  background: var(--surface, #fff);
  border: 1px solid var(--border, #bbb);
  border-radius: var(--ctl-radius, 4px);
}
.ui-in { width: 100%; height: var(--ctl-h, 32px); padding: 0 10px; }
.ui-in-num { width: 120px; height: var(--ctl-h, 32px); padding: 0 10px; text-align: center; }
select.ui-in { padding: 0 8px; }
.ui-in:disabled, .ui-in-num:disabled, select.ui-in:disabled {
  background: color-mix(in srgb, var(--ink, #222) 5%, var(--surface, #fff));
  color: var(--ink-3, #999);
  border-color: var(--border, #ddd);
  cursor: not-allowed;
}
.ui-in:disabled:focus { outline: none; box-shadow: none; }

.tier-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 8px; }
.tier-row { display: grid; grid-template-columns: 1fr 1fr auto; gap: 8px; }
.tier-row input {
  height: var(--ctl-h, 32px); padding: 0 10px;
  font: inherit; font-size: 13.5px; color: var(--ink, #222);
  background: var(--surface, #fff); border: 1px solid var(--border, #bbb);
  border-radius: var(--ctl-radius, 4px); width: 100%;
}
.tier-del {
  height: var(--ctl-h, 32px); padding: 0 12px;
  border: 1px solid var(--border, #ccc); background: transparent;
  border-radius: var(--ctl-radius, 4px); color: var(--ink-2, #666);
  font: inherit; font-size: 13px; cursor: pointer;
}

/* 校验态：红框 + 光晕同红（光晕颜色由主题给 --danger-ring）。
   行为契约：触发校验不自动聚焦；顶部出汇总，点汇总条目才允许定位。 */
.f-field.is-invalid input, .f-field.is-invalid .dd-body, .f-field.is-invalid .tier-row input { border-color: var(--danger, #d33) !important; }
.f-field.is-invalid input:focus, .f-field.is-invalid .dd-body:focus, .f-field.is-invalid input:focus-visible,
.f-field.is-invalid:focus-within .dd-body, .f-field.is-invalid:focus-within input {
  outline: none;
  box-shadow: 0 0 0 3px var(--danger-ring, rgba(211, 47, 47, .22));
}
.f-field--tiers.is-invalid .tier-row input { border-color: var(--danger, #d33); }

.ui-form-errors {
  grid-column: 1 / -1;
  border: 1px solid var(--danger, #d33);
  border-radius: 6px;
  padding: 10px 12px;
  background: color-mix(in srgb, var(--danger, #d33) 6%, transparent);
}
.ui-form-errors p { margin: 0 0 6px; font-weight: 600; font-size: 13px; color: var(--danger, #d33); }
.ui-form-errors ul { margin: 0; padding-left: 18px; }
.ui-form-errors li { font-size: 13px; }
.ui-summary-link {
  background: none; border: none; padding: 0; margin: 0;
  font: inherit; font-size: 13px; color: var(--danger, #d33);
  text-decoration: underline; cursor: pointer; text-align: left;
}

/* ---------- 弹窗 ---------- */
.ui-modal-backdrop {
  position: fixed; inset: 0;
  z-index: 600;
  background: rgba(0, 0, 0, .44);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 0 12px 24px;
  overflow-y: auto;
}
.ui-modal-backdrop[hidden] { display: none; }
.ui-modal {
  width: min(640px, 100%);
  max-height: calc(100vh - 12vh);
  display: flex; flex-direction: column;
  background: var(--surface, #fff);
  border-radius: var(--panel-radius, 8px);
  box-shadow: var(--shadow-2, 0 24px 48px rgba(0, 0, 0, .25));
  overflow: hidden;
}
.ui-modal-head {
  flex: none;
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border, #e5e5e5);
}
.ui-modal-head-main { min-width: 0; }
.ui-modal-kicker { margin: 0; font-size: 11px; letter-spacing: .1em; color: var(--ink-3, #999); text-transform: uppercase; }
.ui-modal-title { margin: 0; font-size: 17px; line-height: 1.3; }
.ui-modal-sub { margin: 2px 0 0; font-size: 12.5px; color: var(--ink-2, #666); }
.ui-modal-close {
  flex: none; width: 28px; height: 28px;
  border: none; background: transparent; cursor: pointer;
  font-size: 18px; line-height: 1; color: var(--ink-2, #666);
  border-radius: 50%;
}
.ui-modal-close:hover { color: var(--ink, #222); }
.ui-modal-body { flex: 1 1 auto; overflow-y: auto; padding: 16px; min-height: 0; }
.ui-modal-foot {
  flex: none;
  display: flex; justify-content: flex-end; gap: 10px; flex-wrap: wrap;
  padding: 12px 16px;
  border-top: 1px solid var(--border, #e5e5e5);
}
.ui-modal-foot [hidden] { display: none; }

/* 堆栈：入栈的下层收起只露头部条；点头部条回前台（状态类由消费方挂） */
.ui-modal-backdrop.is-covered { background: transparent; overflow: visible; pointer-events: none; }
.ui-modal-backdrop.is-covered .ui-modal { max-height: none; overflow: visible; box-shadow: none; border: 1px dashed var(--border, #bbb); pointer-events: auto; }
.ui-modal-backdrop.is-covered .ui-modal-body,
.ui-modal-backdrop.is-covered .ui-modal-foot { display: none; }
.ui-modal-backdrop.is-covered .ui-modal-head { cursor: pointer; border-bottom: none; }
.ui-modal-backdrop.is-covered .ui-modal-head::after { content: '已入栈 · 点此回到前台'; font-size: 12px; color: var(--ink-3, #999); align-self: center; white-space: nowrap; }

/* ---------- 芯片 / 药丸 ---------- */
.ui-chip {
  display: inline-flex; align-items: center; gap: 6px;
  height: 26px; padding: 0 10px; font-size: 12.5px;
  background: var(--opt-hover, #f5f5f5);
  border: 1px solid var(--border, #ccc);
  border-radius: var(--chip-radius, 16px);
  color: var(--ink, #222);
}
.ui-chip-x { font-style: normal; color: var(--ink-3, #999); }
.ui-pill {
  display: inline-flex; align-items: center; height: 22px; padding: 0 10px;
  font-size: 12px; border-radius: 999px;
  background: var(--opt-hover, #f0f0f0); color: var(--ink, #222);
  border: 1px solid var(--border, #ccc);
}

/* ---------- 分段切换 ---------- */
.ui-seg {
  display: inline-flex; width: max-content;
  border: 1px solid var(--border, #ccc);
  border-radius: var(--ctl-radius, 4px);
  overflow: hidden;
}
.ui-seg button {
  height: var(--ctl-h, 32px); padding: 0 14px; border: none;
  background: var(--surface, #fff); color: var(--ink, #222);
  font: inherit; font-size: 13px; cursor: pointer;
}
.ui-seg button + button { border-left: 1px solid var(--border, #ccc); }
.ui-seg button.is-on { background: var(--accent, #06c); color: var(--accent-ink, #fff); }

/* ---------- 数字步进 ---------- */
.ui-step-row { display: flex; align-items: center; gap: 10px 16px; flex-wrap: wrap; }
.ui-step-box { display: inline-flex; align-items: stretch; }
.ui-step-btn {
  width: 34px; height: var(--ctl-h, 32px); flex: none;
  border: 1px solid var(--border, #ccc); background: var(--surface, #fff);
  color: var(--ink, #222); font: inherit; font-size: 15px; cursor: pointer; padding: 0;
}
.ui-step-btn:hover { background: var(--opt-hover, #f5f5f5); }
.ui-step-box .ui-in-num { border-radius: 0; border-left: none; border-right: none; }
.ui-step-btn--minus { border-radius: var(--ctl-radius, 4px) 0 0 var(--ctl-radius, 4px); }
.ui-step-btn--plus { border-radius: 0 var(--ctl-radius, 4px) var(--ctl-radius, 4px) 0; }
