/* MIXXIN Links — a quiet workspace for everyday marketing work. */
:root {
  --bg: #fafbfa; --panel: #fff; --line: #e7eae7; --line-strong: #cdd4cf;
  --ink: #202a25; --ink-soft: #69756e; --accent: #204c3a; --accent-ink: #fff;
  --focus: #32785c; --ok-bg: #edf7f0; --ok-ink: #287044;
  --warn-bg: #fff7e8; --warn-ink: #78551a; --err-bg: #fff0ee; --err-ink: #a03a32;
  --info-bg: #f0f4f2; --info-ink: #4a6154; --radius: 10px;
}
* { box-sizing: border-box; }
[hidden] { display: none !important; }
html { background: var(--bg); color: var(--ink); }
body { margin: 0; min-height: 100vh; font: 14px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans TC", "PingFang TC", sans-serif; -webkit-font-smoothing: antialiased; }
a { color: var(--accent); text-underline-offset: 3px; }
button, input, select, textarea { font: inherit; }
button, summary, a, input, select { -webkit-tap-highlight-color: transparent; }
button, a, summary { touch-action: manipulation; }
code, .mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .92em; overflow-wrap: anywhere; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; border-radius: 6px; }
.visually-hidden { position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.skip-link { position: absolute; left: 16px; top: -60px; background: var(--panel); padding: 12px 20px; border: 1px solid var(--line-strong); border-radius: var(--radius); z-index: 100; }
.skip-link:focus { top: 12px; }

/* Shell */
.topbar { min-height: 76px; display: flex; align-items: center; gap: 24px; padding: 0 32px 0 24px; border-bottom: 1px solid var(--line); background: var(--panel); }
.brand { display: flex; align-items: center; gap: 11px; flex: 0 0 216px; }
.brand-mark { display: grid; place-items: center; width: 34px; height: 34px; color: #fff; background: var(--accent); border-radius: 10px; }
.brand-mark svg { width: 20px; height: 20px; }
.brand-title { font-size: 19px; font-weight: 750; letter-spacing: -.7px; white-space: nowrap; }
.brand-title > span { font-weight: 450; letter-spacing: -.4px; color: #6d7971; }
.workspace-label { display: flex; gap: 16px; color: var(--ink-soft); font-size: 12px; }
.workspace-label > span { color: #b2bcb5; }
.identity { margin-left: auto; display: flex; align-items: center; gap: 10px; min-width: 0; }
.identity-avatar { display: grid; place-items: center; flex: 0 0 30px; height: 30px; border-radius: 50%; background: #eaf0eb; color: var(--accent); font-size: 12px; font-weight: 650; }
.identity-text { max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
.identity-nav { display: flex; align-items: center; gap: 12px; padding-left: 10px; }
.identity-nav a { color: var(--ink-soft); font-size: 12px; text-decoration: none; }
.identity-nav a:hover { color: var(--ink); }
.mobile-project-toggle { display: none !important; }
.layout { display: grid; grid-template-columns: 240px minmax(0, 1fr); min-height: calc(100vh - 76px); }
.sidebar { background: #f5f7f5; border-right: 1px solid var(--line); padding: 26px 16px 20px; display: flex; flex-direction: column; gap: 0; align-self: stretch; min-width: 0; }
.workspace-card { display: flex; align-items: center; gap: 10px; padding: 0 10px 28px; }
.workspace-monogram { display: grid; place-items: center; width: 34px; height: 34px; border: 1px solid #dce2dc; border-radius: 9px; background: white; color: #3c4a40; font-weight: 700; }
.workspace-card strong { display: block; font-size: 12px; font-weight: 650; letter-spacing: .3px; }
.workspace-card div > span { display: block; color: var(--ink-soft); font-size: 11px; margin-top: 1px; }
.sidebar-head { display: flex; align-items: center; justify-content: space-between; padding: 0 10px; margin-bottom: 8px; }
.sidebar h2 { font-size: 11px; font-weight: 550; color: var(--ink-soft); margin: 0; letter-spacing: .6px; }
.customer-group { margin: 0 0 22px; }
.customer-head { display: flex; align-items: center; justify-content: space-between; padding: 0 10px 6px; gap: 4px; }
.customer-name { margin: 0; font-size: 12px; font-weight: 600; color: #657168; overflow-wrap: anywhere; }
.customer-tools { display: flex; align-items: center; flex-shrink: 0; gap: 0; }
.customer-tools .btn { padding: 0; min-width: 25px; min-height: 28px; font-size: 17px; color: #6f7d73; }
.customer-empty { color: var(--ink-soft); margin: 0 10px; font-size: 12px; }
.project-list { list-style: none; margin: 0; padding: 0; }
.project-list li + li { margin-top: 3px; }
.project-button { display: flex; align-items: center; gap: 10px; width: 100%; padding: 10px 12px; border-radius: 8px; text-align: left; border: 1px solid transparent; color: #5e6a62; background: transparent; cursor: pointer; }
.project-button::before { content: ''; width: 7px; height: 7px; flex: 0 0 7px; border: 1.5px solid #a8b3aa; border-radius: 2px; }
.project-button:hover { background: #eaf0eb; }
.project-button[aria-current="true"] { color: #254d38; background: #e5ede6; font-weight: 600; }
.project-button[aria-current="true"]::before { background: #49755a; border-color: #49755a; }
.project-name-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.project-button .badge { display: none; }
.sidebar-footer { margin-top: auto; padding: 40px 4px 0; display: flex; flex-direction: column; gap: 3px; }
.sidebar-footer .btn { justify-content: flex-start; text-align: left; color: #657168; font-size: 12px; gap: 10px; }
.sidebar-footer p { margin: 20px 10px 0; font-size: 10px; color: #69756e; }
.content { min-width: 0; padding: 40px clamp(24px, 3.4vw, 60px) 32px; }
#project-panel { max-width: 1320px; margin: 0 auto; }
.project-head { display: flex; justify-content: space-between; align-items: center; gap: 20px; margin-bottom: 30px; }
.project-heading { min-width: 0; }
.project-context { display: flex; gap: 10px; align-items: center; color: #78847b; font-size: 11px; margin-bottom: 10px; flex-wrap: wrap; }
.crumb { margin: 0; }
.project-head h1 { font-size: clamp(26px, 2.5vw, 34px); line-height: 1.3; font-weight: 650; letter-spacing: -.8px; margin: 0; overflow-wrap: anywhere; }
.project-description { color: var(--ink-soft); font-size: 13px; margin: 10px 0 0; }
.project-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.project-settings { position: relative; }
.project-settings summary { list-style: none; }
.project-settings summary::-webkit-details-marker { display: none; }
.settings-menu { position: absolute; right: 0; top: calc(100% + 8px); z-index: 5; width: 170px; padding: 6px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); box-shadow: 0 12px 35px #182a2020; }
.settings-menu .btn { display: flex; width: 100%; justify-content: flex-start; font-size: 12px; }
.section-nav { display: flex; align-items: stretch; gap: 28px; border-bottom: 1px solid var(--line); margin-bottom: 24px; }
.section-current, .section-button { min-height: 48px; display: flex; align-items: center; gap: 8px; padding: 0 2px 13px; margin-bottom: -1px; border: 0; border-bottom: 2px solid transparent; background: transparent; color: var(--ink-soft); font-size: 13px; cursor: pointer; }
.section-current { font-weight: 600; color: var(--accent); border-bottom-color: var(--accent); cursor: default; }
.section-button:hover { color: var(--ink); }
.link-workspace { background: var(--panel); border: 1px solid var(--line); border-radius: 14px; overflow: hidden; }
.workspace-note { font-size: 11px; color: #69756e; text-align: center; margin: 24px 0 0; }
.welcome-state { padding: 90px 20px; text-align: center; max-width: 640px; margin: auto; }
.welcome-symbol { display: grid; place-items: center; width: 68px; height: 68px; font-size: 36px; color: var(--accent); background: #e8f1e9; border-radius: 20px; margin: 0 auto 28px; }
.welcome-state h1 { font-size: 30px; font-weight: 600; letter-spacing: -.6px; }
.welcome-state p:not(.eyebrow) { color: var(--ink-soft); }
.eyebrow { font-size: 10px; letter-spacing: 1.6px; font-weight: 600; color: #69756e; margin: 0 0 8px; }
.panel { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 20px; }
.muted { color: var(--ink-soft); }

/* Quiet controls and status */
.btn { display: inline-flex; justify-content: center; align-items: center; gap: 7px; font: inherit; font-weight: 500; min-height: 38px; padding: 8px 14px; border-radius: 8px; cursor: pointer; border: 1px solid var(--line-strong); background: var(--panel); color: #405046; white-space: nowrap; transition: background 140ms, border-color 140ms; }
.btn:hover { background: #f1f5f1; border-color: #bfcac2; }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn-primary { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); padding: 11px 19px; min-height: 44px; }
.btn-primary:hover { background: #153d2c; border-color: #153d2c; }
.btn-primary > span { font-size: 20px; font-weight: 400; line-height: 1; }
.btn-quiet { background: transparent; border-color: transparent; }
.btn-quiet:hover { border-color: transparent; }
.btn-small { padding: 6px 10px; min-height: 32px; font-size: 12px; }
.btn-tiny { font-size: 11px; padding: 3px 8px; }
.icon-button { width: 36px; height: 36px; min-height: 36px; padding: 0; font-size: 21px; flex-shrink: 0; }
.badge { display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px; border-radius: 6px; border: 1px solid var(--line); background: #f7f9f7; color: var(--ink-soft); font-size: 11px; white-space: nowrap; }
.badge-active { background: var(--ok-bg); color: var(--ok-ink); border-color: transparent; }
.badge-active::before { content: ''; width: 5px; height: 5px; background: #42925e; border-radius: 50%; }
.badge-disabled { background: #f0f2f0; color: #6e7871; border-color: transparent; }
.role-badge { border: 0; padding: 1px 6px; background: #ecf0ec; font-size: 10px; }
.status { margin: 12px 0; padding: 12px 16px; border-radius: var(--radius); border: 1px solid var(--line); background: var(--panel); font-size: 13px; }
.status-inline { margin: 4px 0 10px; padding: 8px 10px; font-size: 12px; }
.status-info { background: var(--info-bg); color: var(--info-ink); border-color: #dfe8e1; }
.status-ok { background: var(--ok-bg); color: var(--ok-ink); border-color: #d5e9dc; }
.status-warn { background: var(--warn-bg); color: var(--warn-ink); border-color: #eedebf; }
.status-error { background: var(--err-bg); color: var(--err-ink); border-color: #efd7d4; }
#global-status { margin: 12px 24px; }
#links-status { margin: 0 20px 16px; }
.notice { margin: 0 0 24px; padding: 12px 16px; border-radius: var(--radius); background: var(--info-bg); color: var(--info-ink); font-size: 12px; }
.dev-banner { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; padding: 12px 24px; background: var(--warn-bg); color: var(--warn-ink); border-bottom: 1px solid #ecd9b8; font-size: 11px; }
.dev-banner p { margin: 2px 0 0; }
.dev-select { display: flex; align-items: center; gap: 8px; }

/* Link list */
.toolbar { display: flex; gap: 16px; align-items: center; justify-content: space-between; padding: 20px 20px 12px; }
.field { display: flex; flex-direction: column; gap: 8px; min-width: 0; font-size: 12px; font-weight: 500; color: #48584e; }
.field-grow { flex: 1 1 14rem; }
.field input, .field select, .field textarea, .dev-select select, .page-size-label select { font: inherit; color: var(--ink); min-height: 40px; padding: 10px 12px; border: 1px solid var(--line-strong); border-radius: 8px; background: var(--panel); min-width: 0; width: 100%; }
.field input::placeholder, .field textarea::placeholder { color: #69756e; font-weight: 400; }
.field textarea { resize: vertical; min-height: 100px; }
.field input:disabled, .field select:disabled, .field textarea:disabled { background: #f3f5f3; color: var(--ink-soft); }
/* 選填的修改原因（第二十切片）：兩行高就夠，不要把表單撐開；沒有卡片、沒有額外標題。
   緊接其後的說明文字留窄一點的間距，讓「輸入框＋說明」讀起來是同一件事。 */
.field-reason textarea { min-height: 4.5rem; overflow-wrap: anywhere; }
.field-reason + .hint { margin-top: 6px; }
/* 確認步驟回讀使用者寫的那句話：保留換行，長字串照樣換行，不橫向溢出。 */
.reason-echo { white-space: pre-wrap; overflow-wrap: anywhere; }
.search-field { position: relative; flex: 1 1 340px; max-width: 430px; }
.search-field input { padding-left: 37px; background: #f8faf8; border-color: #e4e9e4; font-weight: 400; font-size: 12px; }
.search-icon { position: absolute; left: 12px; top: 12px; width: 17px; height: 17px; color: #7b897f; pointer-events: none; }
.filter-controls { display: flex; align-items: center; gap: 8px; }
.filter-controls select { font-size: 12px; background: #fff; min-height: 38px; border-color: #e2e8e2; padding: 8px 10px; }
.filter-controls .btn { font-size: 12px; min-height: 38px; }
.btn-search { border-color: #e2e8e2; }
.list-caption { display: flex; justify-content: space-between; padding: 0 22px 16px; gap: 12px; color: var(--ink-soft); font-size: 11px; }
.count { margin: 0; }
.list-caption-hint { color: #69756e; }
.table-wrap { overflow-x: auto; }
.links { width: 100%; border-collapse: collapse; table-layout: fixed; }
.links th { text-align: left; font-size: 10px; font-weight: 550; letter-spacing: .3px; background: #f8faf8; color: #69756e; padding: 12px 22px; border-top: 1px solid #eef1ee; border-bottom: 1px solid #eef1ee; }
.links th.col-link { width: auto; }
.links th.col-status { width: 148px; }
.links th.col-updated { width: 162px; }
.links th.col-actions { width: 176px; }
.links td { padding: 20px 22px; border-bottom: 1px solid #eef1ee; vertical-align: middle; }
.links tbody tr:last-child td { border-bottom: 0; }
.links tbody tr:hover { background: #fcfdfb; }
.link-item { display: flex; align-items: center; gap: 13px; min-width: 0; }
.link-mark { display: grid; place-items: center; flex: 0 0 40px; width: 40px; height: 40px; border: 1px solid #e2e9e2; border-radius: 11px; background: #f6f9f5; color: #69816c; }
.link-mark svg { width: 18px; height: 18px; }
.link-content { min-width: 0; }
.cell-short { display: flex; align-items: center; gap: 8px; min-width: 0; }
.short-address { font-size: 13px; font-weight: 600; letter-spacing: -.15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.destination-address { font-size: 11px; color: #69756e; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin: 4px 0 0; }
.copy-button { width: 28px; height: 28px; min-height: 28px; padding: 5px; color: #87938a; flex-shrink: 0; }
.copy-button svg { width: 14px; height: 14px; }
.cell-updated { color: #69756e; font-size: 11px; font-variant-numeric: tabular-nums; }
.row-actions { display: flex; align-items: center; justify-content: flex-end; gap: 2px; }
.cell-actions .btn { color: #77867c; }
.links .cell-actions { padding-left: 0; }
.list-footer { display: flex; align-items: center; justify-content: space-between; gap: 16px; border-top: 1px solid var(--line); padding: 14px 22px; color: var(--ink-soft); font-size: 11px; }
.page-size-label { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.page-size-label select { width: auto; min-height: 32px; padding: 5px 8px; font-size: 11px; border-color: #e2e8e2; }
.pager { display: flex; align-items: center; gap: 8px; }
.pager-info { font-size: 11px; margin: 0 8px 0 0; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.pager .btn { min-height: 32px; padding: 5px 9px; font-size: 11px; }

/* Dialogs: comfortable forms and focused secondary tools */
.dialog { border: 1px solid #dfe6df; border-radius: 18px; padding: 0; width: min(480px, calc(100vw - 32px)); max-height: calc(100dvh - 48px); background: var(--panel); color: var(--ink); box-shadow: 0 25px 100px #16332126; }
.dialog-wide { width: min(780px, calc(100vw - 32px)); }
.dialog::backdrop { background: #15271f65; backdrop-filter: blur(3px); }
.dialog form, .dialog-body { padding: 28px; display: flex; flex-direction: column; gap: 16px; }
.dialog-body form { padding: 0; }
.dialog h2 { font-size: 23px; line-height: 1.35; font-weight: 650; letter-spacing: -.5px; margin: 0; }
.dialog h3 { font-weight: 600; }
.dialog-sub { margin: -4px 0 4px; color: var(--ink-soft); font-size: 12px; overflow-wrap: anywhere; }
.dialog fieldset { border: 0; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.dialog input, .dialog select { min-height: 44px; }
.hint { margin: -6px 0 0; color: var(--ink-soft); font-size: 11px; line-height: 1.7; font-weight: 400; }
.optional-label { font-size: 10px; color: #69756e; font-weight: 400; }
.dialog-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 8px; border-top: 1px solid var(--line); padding-top: 20px; margin-top: 6px; }
.dialog-heading { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; }
.link-facts { margin: 0; display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 7px 16px; font-size: 12px; padding: 16px; background: #f7f9f7; border-radius: 10px; }
.link-facts dt { color: var(--ink-soft); }
.link-facts dd { margin: 0; overflow-wrap: anywhere; }
.review { border: 1px solid var(--line); border-radius: 10px; padding: 16px; background: #f6f9f5; }
.review h3 { margin: 0 0 8px; font-size: 14px; }
.review ul { margin: 0; padding-left: 18px; }
.review li { margin: 6px 0; }
.change-old { color: var(--ink-soft); text-decoration: line-through; }
.change-new { font-weight: 600; }
.actions-dialog { width: min(480px, calc(100vw - 32px)); }
.action-link-url { padding: 12px 14px; background: #f5f8f4; border-radius: 8px; color: var(--accent); }
.link-actions-grid { display: grid; gap: 4px; }
.link-tool { display: flex; align-items: center; gap: 14px; padding: 14px 10px; text-align: left; color: var(--ink); background: transparent; border: 0; border-radius: 10px; cursor: pointer; }
.link-tool:hover { background: #f5f8f4; }
.tool-symbol { display: grid; place-items: center; width: 40px; height: 40px; color: #61816b; border-radius: 10px; background: #f0f5ee; flex-shrink: 0; }
.tool-symbol svg { width: 20px; height: 20px; }
.tool-words { display: flex; flex-direction: column; gap: 3px; }
.tool-words strong { font-size: 13px; font-weight: 600; }
.tool-words > span { color: var(--ink-soft); font-size: 11px; }
.tool-arrow { margin-left: auto; color: #8f9b92; }

/* ---------- 成員管理 ---------- */
.members { width: 100%; border-collapse: collapse; }
.members th, .members td { padding: .5rem .6rem; border-bottom: 1px solid var(--line); text-align: left; vertical-align: middle; }
.members th { font-size: .82rem; color: var(--ink-soft); font-weight: 600; background: #faf7f2; }
.members tbody tr:last-child td { border-bottom: 0; }
.members select { font: inherit; color: var(--ink); padding: .3rem .5rem; border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--panel); }
.members select:disabled { background: #efebe4; color: var(--ink-soft); }
/* 專案成員名單（桌機）：email 要能完整讀出來，所以給它最寬的欄；角色、狀態與操作各自夠用就好。
   被擋下的原因是一整句話，放在按鈕同一行會把 email 擠到一次只剩幾個字，所以讓它換自己一行。 */
.members-dialog-table col.members-col-name { width: 22%; }
.members-dialog-table col.members-col-email { width: 34%; }
.members-dialog-table col.members-col-role { width: 14%; }
.members-dialog-table col.members-col-status { width: 12%; }
.members-dialog-table col.members-col-actions { width: 18%; }
.members-dialog-table td { vertical-align: top; }
.members-dialog-table .cell-actions { display: flex; flex-wrap: wrap; gap: .35rem; align-items: flex-start; }
.members-dialog-table .cell-actions .hint { flex-basis: 100%; margin: 0; }
.member-add { border-top: 1px solid var(--line); padding-top: .7rem; display: flex; flex-direction: column; gap: .5rem; }
.member-add h3 { margin: 0; font-size: 1rem; }
.member-add-row { display: flex; flex-wrap: wrap; gap: .6rem .8rem; align-items: flex-end; }
.member-add-row .btn { align-self: flex-end; }

/* ---------- 網域管理 ---------- */
.domains { width: 100%; border-collapse: collapse; }
.domains th, .domains td { padding: .5rem .6rem; border-bottom: 1px solid var(--line); text-align: left; vertical-align: middle; }
.domains th { font-size: .82rem; color: var(--ink-soft); font-weight: 600; background: #faf7f2; }
.domains tbody tr:last-child td { border-bottom: 0; }
.dialog-body section { display: flex; flex-direction: column; gap: .5rem; }
.dialog-body section h3 { margin: 0; font-size: 1rem; }
.section-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: .5rem 1rem; }
.section-head .field { min-width: 12rem; }

/* ---------- 成效報表 ---------- */
.analytics-controls { display: flex; flex-direction: column; gap: .6rem; border-bottom: 1px solid var(--line); padding-bottom: .7rem; }
.analytics-scope { border: 0; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: .4rem 1rem; }
.analytics-scope legend { font-size: .9rem; color: var(--ink-soft); padding: 0; margin-bottom: .2rem; }
.analytics-scope label { display: inline-flex; align-items: center; gap: .35rem; }
.analytics-dates { display: flex; flex-wrap: wrap; gap: .6rem .8rem; align-items: flex-end; }
.analytics-quick { display: flex; gap: .35rem; flex-wrap: wrap; align-self: flex-end; }
.analytics-cards { margin: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .5rem; }
.analytics-card { border: 1px solid var(--line); border-radius: var(--radius); padding: .55rem .7rem; background: #faf7f2; }
.analytics-card dt { font-size: .82rem; color: var(--ink-soft); }
.analytics-card dd { margin: .1rem 0 .2rem; font-size: 1.4rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.analytics-card .hint { font-size: .78rem; }
.analytics-card-primary { border-color: var(--accent); background: #f6ebdd; }
.analytics-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: .8rem 1rem; }
.trend, .breakdown { width: 100%; border-collapse: collapse; }
.trend th, .trend td, .breakdown th, .breakdown td { padding: .35rem .5rem; border-bottom: 1px solid var(--line); text-align: left; vertical-align: middle; font-size: .9rem; }
.trend th, .breakdown th { font-size: .8rem; color: var(--ink-soft); font-weight: 600; background: #faf7f2; }
.trend tbody tr:last-child td, .breakdown tbody tr:last-child td { border-bottom: 0; }
.trend .num, .breakdown .num { text-align: right; font-variant-numeric: tabular-nums; }
.trend-bar { width: 100%; min-width: 6rem; height: 1rem; }
#analytics-report { display: flex; flex-direction: column; gap: .7rem; }
#analytics-trend-section .table-wrap { max-height: 40vh; overflow: auto; }

/* ---------- 行銷活動／UTM 範本／QR ---------- */
.dialog-toolbar { display: flex; flex-wrap: wrap; gap: .5rem; }
.campaigns, .channels, .templates, .preview { width: 100%; border-collapse: collapse; }
.campaigns th, .campaigns td, .channels th, .channels td, .templates th, .templates td, .preview th, .preview td {
  padding: .5rem .6rem; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; font-size: .92rem;
}
.campaigns th, .channels th, .templates th, .preview th { font-size: .82rem; color: var(--ink-soft); font-weight: 600; background: #faf7f2; }
.campaigns tbody tr:last-child td, .channels tbody tr:last-child td, .templates tbody tr:last-child td, .preview tbody tr:last-child td { border-bottom: 0; }
.campaigns .num, .channels .num, .templates .num, .preview .num { text-align: right; font-variant-numeric: tabular-nums; }
.channels-section { display: flex; flex-direction: column; gap: .5rem; border-top: 1px solid var(--line); padding-top: .7rem; }
.channel-list { display: flex; flex-direction: column; gap: .6rem; }
.channel-row { border: 1px solid var(--line); border-radius: var(--radius); padding: .6rem .75rem; background: #faf7f2; display: flex; flex-direction: column; gap: .5rem; }
.channel-row-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: .5rem .8rem; }
.channel-row-head .field-grow { flex: 1 1 12rem; }
.utm-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); gap: .5rem .8rem; }
.utm-grid .field input { width: 100%; }
.badge-warn { background: var(--warn-bg); color: var(--warn-ink); border-color: #ead49a; }
.hint-list { margin: 0; padding-left: 1.1rem; color: var(--ink-soft); font-size: .85rem; }
.hint-list li { margin: .15rem 0; }
/* 成員變更確認框的「權限變化」小節：與其他小節一樣只靠留白分隔，不加卡片或底色。 */
.member-confirm-access { display: grid; gap: .3rem; }
.member-confirm-access h3 { margin: 0; font-size: 1rem; }
.member-confirm-access .hint-list li.is-gain { color: var(--ok-ink); }
.qr-preview { display: flex; justify-content: center; min-height: 6rem; }
.qr-preview img { width: min(264px, 100%); height: auto; border: 1px solid var(--line); background: #fff; image-rendering: pixelated; }
#campaign-preview .table-wrap { max-height: 40vh; overflow: auto; }

/* ---------- 分享預覽 ---------- */
.check { display: flex; gap: .5rem; align-items: flex-start; font-size: .95rem; }
.check input { margin-top: .3rem; }
.share-image, .share-import { border-top: 1px solid var(--line); padding-top: .6rem; }
.share-image-row { display: flex; flex-wrap: wrap; gap: .8rem; align-items: flex-start; }
.share-image-row img { max-width: 16rem; max-height: 10rem; border: 1px solid var(--line); background: #fff; }
.share-image-actions { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }
.share-upload-label { display: inline-block; cursor: pointer; }
.share-upload-label:focus-within { outline: 3px solid var(--focus); outline-offset: 2px; }
#share-fields:disabled .share-upload-label { opacity: .55; cursor: not-allowed; }
.share-card-section { border-top: 1px solid var(--line); padding-top: .6rem; }
.share-card { border: 1px solid var(--line-strong); border-radius: var(--radius); overflow: hidden; background: #fff; max-width: 32rem; }
.share-card-image { background: #efebe4; min-height: 6rem; display: flex; align-items: center; justify-content: center; }
.share-card-image img { display: block; width: 100%; max-height: 16rem; object-fit: cover; }
.share-card-noimage { color: var(--ink-soft); font-size: .85rem; padding: .5rem; }
.share-card-body { padding: .6rem .8rem; display: flex; flex-direction: column; gap: .2rem; }
.share-card-host { margin: 0; font-size: .78rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .02em; }
.share-card-title { margin: 0; font-weight: 600; word-break: break-word; }
.share-card-desc { margin: 0; font-size: .9rem; color: var(--ink-soft); word-break: break-word; }
.review h4 { margin: 0 0 .35rem; font-size: .92rem; }

/* ---------- 智慧分流 ---------- */
.routing-url { word-break: break-all; overflow-wrap: anywhere; }
.routing-schedule { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: .5rem .8rem; }
.routing-rows { display: flex; flex-direction: column; gap: .6rem; }
.routing-row { border: 1px solid var(--line); border-radius: var(--radius); padding: .6rem .75rem; background: #faf7f2; display: flex; flex-direction: column; gap: .5rem; }
.routing-row-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .35rem .8rem; }
.routing-row-tools { display: flex; flex-wrap: wrap; gap: .35rem; }
.routing-grid { display: grid; grid-template-columns: minmax(10rem, 1fr) minmax(14rem, 2fr) minmax(6rem, .6fr); gap: .5rem .8rem; }
.routing-grid .field input { width: 100%; }
.routing-conds { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: .5rem .8rem; }
/* `.dialog fieldset`（0,1,1）比 `.routing-checks`（0,1,0）強，會把 flex-direction:column + gap:16px 蓋回來，
   讓每個勾選框各佔一整列、規則列因此長到快 750px，進階條件被推到一整螢幕的空白底下。
   這裡用 `.dialog .routing-checks` 明確指定兩欄格線與緊湊間距；每一列仍保有 44px 的命中區。 */
.dialog .routing-checks { border: 1px solid var(--line); border-radius: var(--radius); padding: .4rem .6rem .5rem;
  margin: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 .8rem; }
.routing-checks legend { font-size: .85rem; color: var(--ink-soft); padding: 0 .2rem; }
.routing-checks .check-inline { min-height: 44px; margin: 0; }
.routing-checks .check-inline input { min-width: 20px; min-height: 20px; }
.check-inline { display: inline-flex; align-items: center; gap: .3rem; font-size: .9rem; }
.routing-sim, .routing-report { border-top: 1px solid var(--line); padding-top: .6rem; }
.routing-sim-controls { display: flex; flex-wrap: wrap; gap: .6rem .8rem; align-items: flex-end; }
.routing-sim-controls .field { flex: 1 1 10rem; }
.routing-sim-controls .btn { align-self: flex-end; }
.routing-report-body { display: flex; flex-direction: column; gap: .7rem; }
.routing-report-revision h4 { margin: 0; font-size: .95rem; }
.routing-table td .badge { margin-left: .4rem; }
#routing-fields:disabled .routing-row { opacity: .8; }

/* 第廿七–廿九切片：參數轉發與 App 開啟頁是兩個獨立的設定區塊（各有自己的開關），
   所以視覺上與上面的分流設定分開，但沿用同一套邊框／間距，不另外發明一種樣式。
   規則列的進階條件是可讀的多行輸入（語言／來源網域／key=value），不是 JSON 編輯器。 */
/* `.dialog fieldset`（0,1,1）比單一 class（0,1,0）強，會把 flex-direction:column + gap:16px 蓋回來。
   這兩個區塊自己控制間距，所以要用 `.dialog .routing-block` 才壓得過去（與 CSS 700 附近的
   analytics scope 是同一個老問題）。 */
.dialog .routing-block { display: flex; flex-direction: column; gap: .35rem;
  border: 1px solid var(--line); border-radius: var(--radius); padding: .7rem .8rem .8rem; margin: .8rem 0 0; }
.routing-block > legend { font-size: .95rem; font-weight: 600; padding: 0 .3rem; }
.routing-block .field { display: block; margin-top: .5rem; }
.routing-block .field textarea, .routing-block .field input, .routing-block .field select { width: 100%; }
.routing-block .check { display: flex; align-items: flex-start; gap: .4rem; margin-top: .5rem; line-height: 1.5; }
.routing-block .check input { margin-top: .2rem; flex: 0 0 auto; }
.routing-choice { display: flex; flex-direction: column; gap: .1rem; }
.routing-inline-actions { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem .7rem; margin-top: .4rem; }
.routing-inline-actions .hint { margin: 0; flex: 1 1 14rem; min-width: 0; }
.routing-app-os { border-left: 3px solid var(--line); padding-left: .7rem; margin: .2rem 0 .4rem; }
.routing-conds-advanced { margin-top: .1rem; }
.routing-conds-advanced .field { display: block; }
.routing-conds-advanced textarea { min-height: 3.4rem; width: 100%; font-family: inherit; }
/* 條件說明緊跟在輸入底下，不要被 `.hint` 的負上緣拉到輸入框裡。 */
.routing-row > .hint { margin-top: .2rem; }
.routing-sim-links { margin-top: .5rem; }
.routing-sim-links p { margin: .25rem 0; word-break: break-all; }
.routing-sim-links a { display: inline-block; min-height: 44px; line-height: 44px; }
#routing-query-fields:disabled, #routing-app-fields:disabled { opacity: .75; }

/* 分流對話框現在很長（分流＋參數轉發＋App＋模擬＋報表）。標題列黏上緣、動作列黏下緣，
   任何捲動位置都看得到「關閉」與「儲存」；手機沒有 Esc，不能只在捲到底的地方才有出口。
   負的水平 margin ＋ padding 讓底色蓋滿對話框內距，捲動的內容不會從底下透出來。 */
.routing-head { position: sticky; top: 0; z-index: 3; align-items: center;
  margin: -28px -28px 0; padding: 20px 28px 12px; background: var(--panel);
  border-bottom: 1px solid var(--line); border-radius: 18px 18px 0 0; }
.routing-head h2 { margin: 0; }
.routing-head-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.routing-actions { position: sticky; bottom: 0; z-index: 3;
  margin: 6px -28px -28px; padding: 14px 28px 20px; background: var(--panel);
  border-radius: 0 0 18px 18px; }

/* 版本歷史：左邊是緊湊的時間線，右邊是同一份內容。純量欄位用「標籤／值」的細列加分隔線，
   不是一張一張的卡片——十幾個欄位堆卡片會把主要動作推到畫面外。 */
.dialog-history { width: min(1000px, calc(100vw - 32px)); }
.history-layout { display: grid; grid-template-columns: minmax(0, 260px) minmax(0, 1fr); gap: .9rem 1.4rem; align-items: start; }
.history-side { display: flex; flex-direction: column; gap: .5rem; min-width: 0; }
.history-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .3rem; max-height: 56vh; overflow: auto; }
.history-entry { width: 100%; text-align: left; display: flex; flex-direction: column; gap: .1rem; padding: .45rem .6rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); color: inherit; cursor: pointer; }
.history-entry:hover { border-color: var(--line-strong); }
.history-entry[aria-current="true"] { border-color: var(--accent); box-shadow: inset 3px 0 0 var(--accent); }
.history-entry-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem .45rem; }
.history-entry-version { font-weight: 600; }
.history-entry-origin { font-size: .86rem; }
.history-entry-meta, .history-entry-summary { color: var(--ink-soft); font-size: .8rem; overflow-wrap: anywhere; }
.history-pager { margin: 0; }
.history-detail { min-width: 0; display: flex; flex-direction: column; gap: .55rem; }
.history-detail-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .4rem .8rem; }
.history-detail-head h3 { margin: 0; }
.history-detail h4 { margin: .5rem 0 0; font-size: .95rem; }
.history-facts { margin: 0; }
/* 標籤／值的細列：靠分隔線分組，不給每個欄位一個外框。 */
.history-fields { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.history-fields li { display: grid; grid-template-columns: minmax(7rem, 11rem) minmax(0, 1fr); gap: .2rem .9rem; padding: .35rem .1rem; border-bottom: 1px solid var(--line); font-size: .9rem; }
.history-fields .history-field-label { color: var(--ink-soft); font-size: .84rem; }
.history-fields .history-field-value { overflow-wrap: anywhere; }
.history-more { border: 1px solid var(--line); border-radius: var(--radius); padding: .35rem .6rem; }
.history-more[open] { padding-bottom: .5rem; }
.history-more > summary { cursor: pointer; font-size: .88rem; color: var(--ink-soft); padding: .25rem 0; }
.history-more .history-fields { border-top: 0; }
/* 差異保留卡片：那是要一眼看清「前 → 後」的重點，數量也少。 */
.history-diff { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .35rem; }
.history-diff li { border: 1px solid var(--line); border-radius: var(--radius); padding: .4rem .6rem; font-size: .9rem; }
.history-diff .history-field-label { display: block; color: var(--ink-soft); font-size: .82rem; }
.history-change { display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem .4rem; }
.history-change .change-old, .history-change .change-new { overflow-wrap: anywhere; }
.history-arrow { color: var(--ink-soft); }
.history-restore-actions { margin-top: .2rem; }

/* 兩版比較（第十八切片）：挑選在清單旁邊，結果在版面下方**獨立**一段，和還原完全分開。 */
.history-pick-buttons { display: flex; flex-wrap: wrap; gap: .3rem; margin: .2rem 0 .1rem; }
.history-pick-button[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); font-weight: 600; }
.history-pick { border: 1px solid var(--line); border-radius: var(--radius); padding: .5rem .65rem; display: flex; flex-direction: column; gap: .35rem; }
.history-pick h3 { margin: 0; font-size: .95rem; }
.history-pick .hint { margin: 0; }
.history-pick-slots { margin: 0; display: grid; grid-template-columns: 2rem minmax(0, 1fr); gap: .15rem .5rem; font-size: .88rem; }
.history-pick-slots dt { color: var(--ink-soft); }
.history-pick-slots dd { margin: 0; overflow-wrap: anywhere; }
.history-pick-actions { display: flex; flex-wrap: wrap; gap: .35rem; }
/* 比較結果在右側主工作區的最上面（與清單並排），下面才是「版本內容」與還原。 */
.history-compare { padding-bottom: .7rem; margin-bottom: .2rem; border-bottom: 1px solid var(--line); display: flex; flex-direction: column; gap: .45rem; min-width: 0; }
.history-compare h3 { margin: 0; }
.history-compare .hint { margin: 0; }
.history-compare-heads { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: .2rem .9rem; }
/* 一行一邊：不用巢狀卡片，手機上才不會被兩塊高高的方框佔滿。 */
.history-compare-side { margin: 0; display: flex; align-items: baseline; gap: .4rem; font-size: .86rem; min-width: 0; overflow-wrap: anywhere; }
.history-compare-side-label { flex: 0 0 auto; color: var(--ink-soft); border: 1px solid var(--line); border-radius: 6px; padding: 0 .3rem; font-size: .78rem; }

/* 補充註解：時間順序的討論串，用分隔線而不是一則一個方框；串本身有高度上限，
   所以翻頁與輸入框永遠在看得到的地方，不會被二十則註解推到幾千像素以下。 */
.history-notes { margin-top: .6rem; padding-top: .6rem; border-top: 1px solid var(--line); display: flex; flex-direction: column; gap: .45rem; min-width: 0; }
.history-notes h4 { margin: 0; font-size: .95rem; }
.history-notes .hint { margin: 0; }
.history-notes-list { list-style: none; margin: 0; padding: 0; max-height: 34vh; overflow: auto; }
.history-notes-list:not(:empty) { border-top: 1px solid var(--line); }
.history-note { padding: .45rem .1rem; border-bottom: 1px solid var(--line); }
.history-note-fresh { background: var(--info-bg); padding-left: .4rem; padding-right: .4rem; }
.history-note-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .5rem; font-size: .8rem; color: var(--ink-soft); }
.history-note-label { color: var(--accent); font-weight: 600; }
.history-note-text { margin: .2rem 0 0; white-space: pre-wrap; overflow-wrap: anywhere; font-size: .92rem; }
.history-notes-pager { margin: 0; }
.history-note-form { display: flex; flex-direction: column; gap: .3rem; }
/* 對話框裡的表單樣式：特異度要高過單一 class，才不會被通用的 form 規則蓋掉。 */
.dialog .history-note-form label { font-size: .86rem; color: var(--ink-soft); }
.dialog .history-note-form textarea { width: 100%; max-width: 100%; min-height: 4.5rem; padding: .45rem .55rem; border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--panel); color: inherit; resize: vertical; overflow-wrap: anywhere; }
.dialog .history-note-form .dialog-actions { margin-top: .1rem; }

@media (max-width: 760px) {
  .history-layout { grid-template-columns: minmax(0, 1fr); }
  .history-list { max-height: 32vh; }
  .history-fields li { grid-template-columns: minmax(0, 1fr); }
  /* 窄螢幕：左右並排改成上下堆疊，不要橫向捲動。 */
  .history-compare-heads { grid-template-columns: minmax(0, 1fr); }
  /* 手機上螢幕短：註解串給得更少，讓輸入框與翻頁留在視野內。 */
  .history-notes-list { max-height: 40vh; }
  /* 觸控目標：時間線的每一版與版本歷史的按鈕都留到 44px。 */
  .history-entry { min-height: 44px; padding: .6rem .7rem; }
  .history-detail-head .btn, .history-pager .btn, .history-restore-actions .btn { min-height: 44px; }
  .history-pick-actions .btn, .history-pick-buttons .btn,
  .history-notes-pager .btn, .history-note-actions .btn { min-height: 44px; }
  /* 標籤本身就是可點區（不是靠 margin 撐出來的空白）。 */
  .dialog .history-note-form label { min-height: 44px; display: flex; align-items: center; }
  .history-more > summary { min-height: 44px; display: flex; align-items: center; }
}

.audit { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .5rem; max-height: 60vh; overflow: auto; }
.audit li { border: 1px solid var(--line); border-radius: var(--radius); padding: .5rem .7rem; font-size: .9rem; }
.audit-head { display: flex; flex-wrap: wrap; gap: .3rem .75rem; align-items: center; }
.audit-time { color: var(--ink-soft); }
.audit-diff { margin: .3rem 0 0; padding-left: 1rem; }

/* ---------- 窄螢幕（390px 起可用） ---------- */
@media (max-width: 760px) {
  .members thead { display: none; }
  .members, .members tbody, .members tr, .members td { display: block; }
  .members tr { border-bottom: 1px solid var(--line); padding: .4rem 0; }
  .members tr:last-child { border-bottom: 0; }
  .members td { border: 0; padding: .25rem .6rem; }
  .members td[data-label]::before { content: attr(data-label); display: block; font-size: .78rem; color: var(--ink-soft); }
  /* 窄螢幕改成卡片式之後欄寬沒有意義；操作區的按鈕維持 44px 可點區，原因仍然自己一行。 */
  .members-dialog-table col { width: auto; }
  .members-dialog-table .cell-actions .btn { min-height: 44px; }
  .domains thead { display: none; }
  .domains, .domains tbody, .domains tr, .domains td { display: block; }
  .domains tr { border-bottom: 1px solid var(--line); padding: .4rem 0; }
  .domains tr:last-child { border-bottom: 0; }
  .domains td { border: 0; padding: .25rem .6rem; }
  .domains td[data-label]::before { content: attr(data-label); display: block; font-size: .78rem; color: var(--ink-soft); }
  .dialog form, .dialog-body { padding: 22px; }
  .dialog-body form { padding: 0; }
  .analytics-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .analytics-grid { grid-template-columns: 1fr; }
  .analytics-dates .field { flex: 1 1 100%; }
  .trend thead { display: none; }
  .trend, .trend tbody, .trend tr, .trend td { display: block; }
  .trend tr { border-bottom: 1px solid var(--line); padding: .3rem 0; }
  .trend td { border: 0; padding: .15rem .5rem; }
  .trend td[data-label]::before { content: attr(data-label); display: inline-block; min-width: 5rem; font-size: .78rem; color: var(--ink-soft); }
  .trend .num { text-align: left; }
  .campaigns thead, .channels thead, .templates thead, .preview thead { display: none; }
  .campaigns, .campaigns tbody, .campaigns tr, .campaigns td,
  .channels, .channels tbody, .channels tr, .channels td,
  .templates, .templates tbody, .templates tr, .templates td,
  .preview, .preview tbody, .preview tr, .preview td { display: block; }
  .campaigns tr, .channels tr, .templates tr, .preview tr { border-bottom: 1px solid var(--line); padding: .4rem 0; }
  .campaigns tr:last-child, .channels tr:last-child, .templates tr:last-child, .preview tr:last-child { border-bottom: 0; }
  .campaigns td, .channels td, .templates td, .preview td { border: 0; padding: .25rem .6rem; }
  .campaigns td[data-label]::before, .channels td[data-label]::before, .templates td[data-label]::before, .preview td[data-label]::before {
    content: attr(data-label); display: block; font-size: .78rem; color: var(--ink-soft);
  }
  .campaigns .num, .channels .num, .templates .num, .preview .num { text-align: left; }
  .utm-grid { grid-template-columns: 1fr; }
  .share-image-row img { max-width: 100%; }
  .share-card { max-width: none; }
  .routing-grid, .routing-conds, .routing-schedule { grid-template-columns: 1fr; }
  .routing-sim-controls .field { flex: 1 1 100%; }
  /* 窄畫面：黏住的標題／動作列要跟著對話框縮小的內距走，否則底色會蓋不滿或溢出圓角。 */
  .routing-head { margin: -22px -22px 0; padding: 14px 22px 10px; border-radius: 16px 16px 0 0; }
  .routing-actions { margin: 6px -22px -22px; padding: 12px 22px 18px; border-radius: 0 0 16px 16px; }
  .routing-actions .btn { min-height: 44px; }
  /* 三顆按鈕在 390px 排不下就換行；儲存永遠獨佔一行，長標籤（「重新載入最新版本」）不會被擠成兩個字。 */
  .routing-actions .btn-primary { flex: 1 1 100%; }
  #routing-reload { flex: 1 1 100%; }
  .routing-table thead { display: none; }
  .routing-table, .routing-table tbody, .routing-table tr, .routing-table td { display: block; }
  .routing-table tr { border-bottom: 1px solid var(--line); padding: .3rem 0; }
  .routing-table td { border: 0; padding: .15rem .5rem; }
  .routing-table td[data-label]::before { content: attr(data-label); display: block; font-size: .78rem; color: var(--ink-soft); }
  .routing-table .num { text-align: left; }
}

.routing-table th.num, .routing-table td.num { white-space: nowrap; }

@media (max-width: 1180px) {
  .workspace-label { display: none; }
  .content { padding: 32px 24px; }
  .toolbar { flex-wrap: wrap; }
  .search-field { max-width: none; flex-basis: 100%; }
  .filter-controls { width: 100%; }
  .filter-controls .field { flex: 1; }
  .links th.col-updated { width: 135px; }
  .links td, .links th { padding-left: 16px; padding-right: 16px; }
  .link-mark { display: none; }
}
@media (max-width: 880px) {
  .topbar { min-height: 68px; padding: 0 18px; gap: 12px; flex-wrap: wrap; }
  .brand { flex-basis: auto; }
  .mobile-project-toggle { display: inline-flex !important; margin-left: 4px; }
  .identity-nav { gap: 8px; padding-left: 0; }
  .identity-text { max-width: 110px; }
  .identity-avatar { display: none; }
  .layout { grid-template-columns: minmax(0, 1fr); min-height: calc(100vh - 68px); }
  .sidebar { display: none; border-right: 0; border-bottom: 1px solid var(--line); padding: 20px; }
  .sidebar.is-open { display: flex; }
  .sidebar-footer { padding-top: 16px; }
  .sidebar-footer p { display: none; }
  .workspace-card { padding-bottom: 16px; }
  .content { padding: 28px 22px; }
  .project-head { margin-bottom: 20px; }
  .link-mark { display: grid; }
}
@media (max-width: 600px) {
  .topbar { gap: 6px; padding: 12px 16px; }
  .brand-mark { width: 30px; height: 30px; border-radius: 9px; }
  .brand-title { font-size: 17px; }
  .brand { gap: 8px; }
  .identity { gap: 6px; }
  .identity-text, .identity-nav #account-link { display: none; }
  .identity-nav .btn { padding: 4px 6px; font-size: 11px; }
  .content { padding: 26px 16px; }
  .project-head { flex-wrap: wrap; gap: 20px; }
  .project-head h1 { font-size: 28px; }
  .project-description { font-size: 12px; }
  .project-actions { width: 100%; justify-content: space-between; }
  .project-actions .btn-primary { flex: 1; }
  .project-actions .icon-button { width: 44px; height: 44px; }
  .section-nav { gap: 24px; margin-bottom: 18px; }
  .section-current, .section-button { font-size: 12px; }
  .link-workspace { border-radius: 12px; }
  .toolbar { padding: 16px 14px 12px; gap: 10px; }
  .search-field input, .filter-controls select, .filter-controls .btn { min-height: 44px; }
  .search-icon { top: 14px; }
  .filter-controls { flex-wrap: wrap; gap: 6px; }
  .filter-controls .field { flex: 1 1 38%; }
  .filter-controls .btn { flex: 1; }
  .list-caption { padding: 0 16px 14px; font-size: 10px; }
  .list-caption-hint { display: none; }
  .links, .links tbody { display: block; width: 100%; }
  .links thead { display: none; }
  .links tr { display: grid; grid-template-columns: 1fr auto; padding: 18px 16px; gap: 12px 8px; border-bottom: 1px solid var(--line); }
  .links tr:last-child { border-bottom: 0; }
  .links td { display: block; border: 0; padding: 0; min-width: 0; }
  .links .cell-link { grid-column: 1 / -1; }
  .links .cell-status { grid-column: 1; grid-row: 2; align-self: center; }
  .links .cell-updated { grid-column: 1; grid-row: 3; font-size: 10px; }
  .links .cell-actions { grid-column: 2; grid-row: 2 / 4; align-self: center; padding: 0; }
  .link-item { gap: 10px; }
  .link-mark { flex-basis: 36px; width: 36px; height: 36px; }
  .short-address { font-size: 12px; }
  .copy-button, .row-actions .btn { min-width: 44px; min-height: 44px; }
  .destination-address { font-size: 10px; }
  .list-footer { padding: 14px; flex-wrap: wrap; justify-content: center; }
  .page-size-label { width: 100%; justify-content: center; }
  .page-size-label select { min-height: 44px; }
  .pager { justify-content: center; flex-wrap: wrap; }
  .pager .btn { min-height: 44px; padding: 6px 12px; }
  .pager-info { margin-right: 0; }
  .dialog { max-height: calc(100dvh - 24px); width: calc(100vw - 24px); border-radius: 16px; }
  .dialog .btn, .sidebar .btn, .project-button, .mobile-project-toggle, .identity-nav .btn { min-height: 44px; }
  .dialog h2 { font-size: 22px; }
  .dialog-actions .btn-primary { flex: 1; }
  .link-facts { grid-template-columns: minmax(0, 1fr); gap: 3px; }
  .link-facts dd { margin-bottom: 8px; }
  .welcome-state { padding: 55px 8px; }
  .welcome-state h1 { font-size: 24px; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; transition: none !important; animation: none !important; }
}

.sidebar-footer .btn, .settings-menu .btn { border-color: transparent; background: transparent; }
.sidebar-footer .btn:hover, .settings-menu .btn:hover { background: #eaf0eb; }

.links th { font-size: 11px; }
.short-address { font-size: 14px; }
.destination-address, .cell-updated { font-size: 12px; }
.list-caption { font-size: 12px; }
.toolbar input, .filter-controls select, .filter-controls .btn { font-size: 13px; }
@media (max-width: 600px) {
  .short-address { font-size: 13px; }
  .destination-address { font-size: 11px; }
  .list-caption { font-size: 11px; }
}

@media (max-width: 600px) {
  .filter-controls { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 44px; }
  .filter-controls .btn-search { display: none; }
  .filter-controls #clear-filters { padding: 0; }
}
.project-context .crumb { min-width: 0; max-width: 100%; overflow-wrap: anywhere; }


/* ---------- 第十六切片：全站成員總覽與離職交接 ----------
   左邊是安靜、緊湊的人員清單，右邊是被選到那個人的完整權限。刻意不用一人一張卡片：
   名單是用來掃描與切換的，卡片只會讓「目前選到誰」變模糊，也把主要動作推到畫面外。
   交接的前／後角色用一般表格：那是要逐列比對的資料，表格比卡片好讀。 */
.dialog-staff { width: min(1040px, calc(100vw - 32px)); }
/* 交接對話框放寬到和總覽差不多：五欄的前後角色表在 780px 下太擠。 */
.dialog-handoff { width: min(1000px, calc(100vw - 32px)); }
.staff-layout { display: grid; grid-template-columns: minmax(0, 300px) minmax(0, 1fr); gap: .9rem 1.4rem; align-items: start; }
.staff-side { display: flex; flex-direction: column; gap: .5rem; min-width: 0; }
/* 這三塊都是 <form>，會吃到 `.dialog form { flex-direction: column }`。
   那條規則的權重是 (0,1,1)（一個類別 + 一個元素），只寫 `.staff-filters`（0,1,0）**蓋不過去**，
   `flex: 1 1 10rem` 的 basis 就會變成**高度**，整列撐出一大片空白。
   所以一律用 `.dialog .staff-*`（0,2,0）把權重拉高，確保 flex-direction 真的是 row。 */
.dialog .staff-filters { display: flex; flex-direction: row; flex-wrap: wrap; gap: .4rem; align-items: end; }
.dialog .staff-filters .field-grow { flex: 1 1 10rem; min-width: 0; }
.staff-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .3rem; max-height: 52vh; overflow: auto; }
.staff-entry { width: 100%; text-align: left; display: flex; flex-direction: column; gap: .1rem; padding: .45rem .6rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); color: inherit; cursor: pointer; }
.staff-entry:hover { border-color: var(--line-strong); }
.staff-entry[aria-current="true"] { border-color: var(--accent); box-shadow: inset 3px 0 0 var(--accent); }
.staff-entry-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .25rem .45rem; }
.staff-entry-name { font-weight: 600; overflow-wrap: anywhere; }
.staff-entry-email, .staff-entry-meta { color: var(--ink-soft); font-size: .8rem; overflow-wrap: anywhere; }
.staff-pager { margin: 0; }
.staff-detail { min-width: 0; display: flex; flex-direction: column; gap: .55rem; }
.staff-detail-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .4rem .8rem; }
.staff-detail-head h3 { margin: 0; }
.staff-detail h4 { margin: .5rem 0 0; font-size: .95rem; }
.staff-facts { margin: 0; }
.staff-access { font-size: .9rem; }
.staff-actions { margin-top: .2rem; }
.dialog .staff-handoff-form,
.dialog .staff-successor-search { display: flex; flex-direction: row; flex-wrap: wrap; gap: .5rem; align-items: end; }
.dialog .staff-handoff-form .field-grow { flex: 1 1 14rem; min-width: 0; }
.dialog .staff-successor-search .field-grow { flex: 1 1 12rem; min-width: 0; }
.staff-successor-pager { margin: 0; }
.staff-handoff-table { font-size: .9rem; }
/* 桌面寬度下，三個角色欄不要把「專案管理者」拆成兩行；客戶／專案名稱仍然可以折行。
   ≤760px 會疊成有標籤的列（見下方 media query），那裡不套用這條。 */
@media (min-width: 761px) {
  .dialog .staff-handoff-table th:nth-child(n+3),
  .dialog .staff-handoff-table td:nth-child(n+3) { white-space: nowrap; }
}
/* 交接後的角色是這張表要回答的問題，稍微強調；保留原角色的那一列用柔和色標示「沒有被降級」。 */
.staff-role-after { font-weight: 600; }
.staff-role-kept { color: var(--ink-soft); }

@media (max-width: 760px) {
  .staff-layout { grid-template-columns: minmax(0, 1fr); }
  .staff-list { max-height: 34vh; }
  /* 觸控目標：名單每一列與所有按鈕都留到 44px。 */
  .staff-entry { min-height: 44px; padding: .6rem .7rem; }
  .staff-filters .btn, .staff-pager .btn, .staff-actions .btn,
  .staff-handoff-form .btn, .staff-successor-search .btn, .staff-successor-pager .btn { min-height: 44px; }
  .staff-handoff-table thead { display: none; }
  .staff-handoff-table, .staff-handoff-table tbody, .staff-handoff-table tr, .staff-handoff-table td { display: block; }
  .staff-handoff-table tr { border-bottom: 1px solid var(--line); padding: .4rem 0; }
  .staff-handoff-table tr:last-child { border-bottom: 0; }
  .staff-handoff-table td { border: 0; padding: .25rem .6rem; }
  .staff-handoff-table td[data-label]::before { content: attr(data-label); display: block; font-size: .78rem; color: var(--ink-soft); }
}


/* ---------- 第十七切片：批次連結變更 ----------
   工具列在「這一頁可以修改連結」時就出現（不必先選到東西），因為手機版的表頭是隱藏的，
   「選取本頁」只放在表格裡會完全點不到。逐列結果用一般表格：那是要一列一列比對前後的資料。 */
.batch-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px;
  margin: 0 22px 14px; padding: 8px 14px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--info-bg); }
.batch-count { margin: 0; font-size: 13px; font-weight: 600; color: var(--info-ink); }
.batch-bar-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-left: auto; }
.batch-select-all { display: inline-flex; align-items: center; gap: .4rem; font-size: 13px; color: var(--info-ink); cursor: pointer; }
/* 真正可點的命中區（不是靠 margin 撐開——margin 不會接受點擊）：label 本身就是 44×44 的目標，
   裡面的勾選框維持 18px 的視覺大小並置中。 */
.select-hit { display: inline-flex; align-items: center; justify-content: center; min-width: 32px; min-height: 32px; cursor: pointer; }
.batch-select-all.select-hit { justify-content: flex-start; padding-right: 4px; }
.links th.cell-select, .links td.cell-select { width: 48px; padding-right: 0; text-align: center; }
.links .cell-select input, .batch-select-all input { width: 18px; height: 18px; margin: 0; cursor: pointer; }
.dialog-batch { width: min(1000px, calc(100vw - 32px)); }
/* `.dialog form { flex-direction: column }` 的權重是 (0,1,1)，單寫 `.batch-form` (0,1,0) 蓋不過去。
   表單本身本來就要直向排列，所以只調間距；**選項列**必須橫排，所以用 `.dialog .batch-choices`
   (0,2,0) 把權重拉到 `.dialog fieldset` (0,1,1) 之上——只寫 `.analytics-scope` 會被
   `.dialog fieldset { flex-direction: column; gap: 16px }` 蓋掉，選項之間會撐出很高的空白。 */
.dialog .batch-form { gap: .8rem; }
.dialog .batch-choices { display: flex; flex-direction: row; flex-wrap: wrap; gap: .35rem 1.1rem; margin: 0; }
.dialog .batch-choices legend { font-size: .9rem; color: var(--ink-soft); padding: 0; margin-bottom: .15rem; }
.dialog .batch-choices label { display: inline-flex; align-items: center; gap: .35rem; }
.batch-summary { margin: 0; font-size: .9rem; }
/* 固定欄寬：不讓某一格的長文字把「修改前／修改後」擠成不能比對的寬度。 */
.batch-table { table-layout: fixed; width: 100%; font-size: .9rem; }
.batch-table .col-link { width: 24%; }
.batch-table .col-state { width: 22%; }
.batch-table .col-before, .batch-table .col-after { width: 27%; }
.batch-table td { vertical-align: top; overflow-wrap: anywhere; }
.batch-table .mono { font-size: .82rem; overflow-wrap: anywhere; }
.batch-link-code { font-weight: 600; overflow-wrap: anywhere; }
.batch-row-note { margin: .15rem 0 0; color: var(--ink-soft); font-size: .78rem; }
/* 影響說明自己佔一整列：塞在「修改後」欄裡會讓兩邊的欄寬完全不對稱，沒辦法比對。 */
.batch-notes td { padding-top: 0; border-top: 0; }
.batch-row-warnings { margin: 0; padding-left: 1.1rem; color: var(--ink-soft); font-size: .78rem; }
/* 逐列狀態：綠＝會套用／已套用，灰＝略過，紅＝被擋下或沒有修改。只是標示，權威仍是後端回傳的文字。 */
.batch-state { font-weight: 600; }
.batch-state-ok { color: var(--ok-ink); }
.batch-state-skip { color: var(--ink-soft); }
.batch-state-blocked { color: var(--err-ink); }

/* 匯入（第十九切片）沿用 .batch-table 的版面，只換欄寬：這裡沒有「修改前／修改後」，
   而是「第幾列／結果／短網址／目的網址」。第一欄刻意很窄——那只是個序號，
   使用者真正要看的是短網址與目的網址。 */
.import-table .col-row { width: 9%; }
.import-table .col-state { width: 24%; }
.import-table .col-link { width: 33%; }
.import-table .col-dest { width: 34%; }
/* 100 列全部畫出來，不截斷、不分頁；高度有界，靠捲動而不是隱藏資料。
   選擇器刻意只鎖匯入的兩個區塊：第十七切片的批次對話框版面不受影響。 */
#import-preview .table-wrap, #import-result .table-wrap { max-height: 46vh; overflow-y: auto; }
.import-row-number { color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.dialog .import-file-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .6rem; }
.dialog .import-file-field { flex: 1 1 16rem; min-width: 0; }
.dialog #import-csv { font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-size: .82rem; }
.dialog .import-copy-row { align-items: center; gap: .6rem; flex-wrap: wrap; }

/* 連結表格在 600px 以下會變成 grid（見上面那段 media query）。加了勾選欄之後欄位會全部位移，
   所以只有「真的顯示勾選欄」時（JS 會加上 .links-selectable）才重新指定每一格的位置。 */
@media (max-width: 600px) {
  .batch-bar { margin: 0 16px 12px; }
  .batch-bar .btn { min-height: 44px; }
  .select-hit { min-width: 44px; min-height: 44px; }
  .links.links-selectable tr { grid-template-columns: auto minmax(0, 1fr) auto; }
  .links.links-selectable .cell-select { grid-column: 1; grid-row: 1 / 4; align-self: center; width: auto; padding: 0; }
  .links.links-selectable .cell-link { grid-column: 2 / -1; grid-row: 1; }
  .links.links-selectable .cell-status { grid-column: 2; grid-row: 2; }
  .links.links-selectable .cell-updated { grid-column: 2; grid-row: 3; }
  .links.links-selectable .cell-actions { grid-column: 3; grid-row: 2 / 4; }
}

@media (max-width: 760px) {
  .dialog .batch-form .btn, .dialog-batch .dialog-actions .btn { min-height: 44px; }
  .batch-table { table-layout: auto; }
  .batch-table thead { display: none; }
  .batch-table, .batch-table tbody, .batch-table tr, .batch-table td { display: block; }
  .batch-table tr { border-bottom: 1px solid var(--line); padding: .4rem 0; }
  .batch-table tr.batch-notes { border-bottom: 0; padding-top: 0; }
  .batch-table tr:last-child { border-bottom: 0; }
  .batch-table td { border: 0; padding: .25rem .6rem; }
  .batch-table td[data-label]::before { content: attr(data-label); display: block; font-size: .78rem; color: var(--ink-soft); }
  /* 手機版變成卡片，固定欄寬不再適用；檔案列改成單欄堆疊，觸控目標維持 44px。 */
  .import-table .col-row, .import-table .col-state,
  .import-table .col-link, .import-table .col-dest { width: auto; }
  .dialog .import-file-row { flex-direction: column; align-items: stretch; }
  /* 直排之後 flex-basis 16rem 會變成「最小高度 16rem」，把檔案欄位撐成一大塊空白。 */
  .dialog .import-file-field { flex: initial; width: 100%; }
  .dialog .import-file-row .btn { min-height: 44px; }
  .dialog #import-file { min-height: 44px; }
  .dialog .import-copy-row .btn { min-height: 44px; }
  /* 手機版變成卡片後每一列更高，100 列會變成一張捲不完的長頁、按鈕也按不到。
     所以仍然保留有界的捲動區（比桌機高一些），100 列全部都在裡面，不分頁也不截斷。 */
  #import-preview .table-wrap, #import-result .table-wrap { max-height: 60vh; }
  .import-table .import-row-number { font-size: .78rem; }
}

/* 檢查目的網址（第廿二切片）：結論 → 時間 → 原因的階層。
   最重要的一句話最大、最先，而且緊接在目的網址底下——不放任何前言把它推到摺線以下。
   顏色只用來分辨語氣，不是唯一的訊號：每一種狀態都有自己的文字結論，關掉顏色也讀得懂。
   刻意**不做**卡片套卡片：結果與明細同屬一個區塊，明細只用分隔線區隔。 */
.dialog-destcheck { width: min(560px, calc(100vw - 32px)); }
.destcheck-destination { margin: -8px 0 0; font-size: 13px; line-height: 1.6; overflow-wrap: anywhere; }
.destcheck-result { margin: 0; padding: 16px 18px; background: #f7f9f7; border: 1px solid var(--line); border-radius: 10px; }
.destcheck-verdict { margin: 0; font-size: 19px; font-weight: 650; line-height: 1.3; color: var(--ink); }
.destcheck-when { margin: 6px 0 0; font-size: 12px; color: var(--ink-soft); }
.destcheck-explain { margin: 10px 0 0; font-size: 13px; line-height: 1.65; color: var(--ink); }
/* 明細直接放在同一塊裡：沒有底色、沒有圓角、沒有第二層邊框。 */
.destcheck-facts { margin: 14px 0 0; padding: 12px 0 0; border-top: 1px solid var(--line); display: grid;
  grid-template-columns: auto minmax(0, 1fr); gap: 6px 16px; font-size: 12px; }
.destcheck-facts dt { color: var(--ink-soft); }
.destcheck-facts dd { margin: 0; overflow-wrap: anywhere; }
.destcheck-reachable { color: var(--ok-ink); }
.destcheck-not_found, .destcheck-server_error { color: var(--err-ink); }
.destcheck-client_error, .destcheck-restricted, .destcheck-rate_limited,
.destcheck-unreachable, .destcheck-inconclusive { color: var(--warn-ink); }
#destcheck-dialog .dialog-actions .btn { min-height: 44px; }
/* 重新載入是唯讀的次要動作，排在最左邊，和「開始檢查」拉開距離避免誤按。 */
#destcheck-reload { margin-right: auto; }

@media (max-width: 600px) {
  /* 小手機（390px）：結論仍然在第一屏，按鈕直排並維持 44px 命中區。 */
  .destcheck-result { padding: 14px; }
  .destcheck-verdict { font-size: 18px; }
  .destcheck-facts { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .destcheck-facts dd { margin: 0 0 8px; }
  .destcheck-facts dd:last-child { margin-bottom: 0; }
  #destcheck-dialog .dialog-actions { flex-direction: column-reverse; align-items: stretch; }
  #destcheck-dialog .dialog-actions .btn { width: 100%; }
  #destcheck-reload { margin-right: 0; }
}

/* ---------- 第廿三切片：活動排程總覽 ----------
   方向：安靜的工作區清單——結束時間先講，客戶／專案的來歷緊跟著，動作只有一個。
   刻意不用一列一張卡片：這個畫面是用來「掃描」的，卡片會讓時間的先後順序被邊框切碎，
   在手機上還會疊成一堆圓角盒子。所以每一列只有一條細分隔線，靠排版與字級建立層次。
   顏色只留給「已結束」一種狀態：同一列可能同時寫著「分流未啟用」或「連結已停用」，
   把「排程期間內」染成綠色會看起來像在替那條連結背書，所以它維持中性灰。 */
.dialog-schedule { width: min(960px, calc(100vw - 32px)); }
/* 標題列黏在上緣：一頁最多 20 列，關閉不能只在捲到底的地方（手機沒有 Esc）。
   負的水平 margin ＋ padding 讓底色蓋滿對話框內距，捲動時列不會從標題底下透出來。 */
.schedule-head { position: sticky; top: 0; z-index: 2; align-items: center;
  margin: -28px -28px 0; padding: 20px 28px 12px; background: var(--panel);
  border-bottom: 1px solid var(--line); border-radius: 18px 18px 0 0; }
.schedule-head h2 { margin: 0; }
.schedule-head-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.schedule-head-actions .btn { min-height: 36px; }
.dialog .schedule-filters { display: flex; flex-direction: row; flex-wrap: wrap; gap: .4rem; align-items: end; }
.dialog .schedule-filters .field-grow { flex: 1 1 11rem; min-width: 0; }
.schedule-caption { padding: 0 0 10px; }

/* 分頁標籤沿用專案頁的底線樣式，不做成一排藥丸。
   桌機是一排；窄畫面改成 2×2 方格（見下方 media query），四個一定同時看得到，
   不用橫向捲動、也不會在標籤列裡長出捲軸。 */
.schedule-tabs { display: flex; gap: 22px; border-bottom: 1px solid var(--line); margin: 4px 0 14px; }
.schedule-tab { min-height: 44px; display: flex; align-items: center; gap: 7px; padding: 0 2px 11px; margin-bottom: -1px;
  border: 0; border-bottom: 2px solid transparent; background: transparent; color: var(--ink-soft); font-size: 13px;
  white-space: nowrap; cursor: pointer; }
.schedule-tab:hover { color: var(--ink); }
.schedule-tab.is-current { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }
.schedule-tab-count { min-width: 20px; padding: 1px 6px; border-radius: 999px; background: #eef2ef; color: #5d6b62;
  font-size: 11px; font-variant-numeric: tabular-nums; }
.schedule-tab-count:empty { display: none; }
.schedule-tab.is-current .schedule-tab-count { background: #e3ece5; color: var(--accent); }

.schedule-list { list-style: none; margin: 0; padding: 0; max-height: 54vh; overflow-y: auto; overflow-x: hidden; }
.schedule-row { display: flex; align-items: flex-start; gap: 16px; padding: 13px 2px; border-top: 1px solid var(--line); }
.schedule-row:first-child { border-top: 0; }
.schedule-main { display: flex; align-items: flex-start; gap: 18px; flex: 1 1 auto; min-width: 0; }
/* 結束時間是這個畫面的主角，所以放最前面、固定寬度，讓一整欄的時間可以垂直對齊掃視。 */
.schedule-when { flex: 0 0 clamp(120px, 16vw, 158px); min-width: 0; }
.schedule-when-label { display: block; font-size: 10px; letter-spacing: .5px; color: #8b968e; }
.schedule-when-time { display: block; font-size: 14px; font-weight: 650; line-height: 1.4; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.schedule-timing { display: inline-block; margin-top: 3px; font-size: 11px; color: var(--ink-soft); }
/* 只有「已結束」上色——那是一個確定的、不會再變的事實。「排程期間內」與「尚未開始」維持中性：
   它們只描述時間，不保證這條連結現在真的在分流。 */
.schedule-timing-ended { color: var(--err-ink); }
.schedule-body { min-width: 0; flex: 1 1 auto; }
.schedule-url { margin: 0; font-size: 13px; overflow-wrap: anywhere; }
.schedule-context { margin: 3px 0 0; font-size: 12px; color: var(--ink-soft); overflow-wrap: anywhere; }
.schedule-span { margin: 3px 0 0; font-size: 11px; color: #7d887f; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
/* 旗標是各自獨立的事實，只在為真時出現；用文字不用色塊，避免整排像警示燈。 */
.schedule-flags { display: flex; flex-wrap: wrap; gap: 4px 10px; margin: 6px 0 0; font-size: 11px; }
.schedule-flag { color: var(--warn-ink); }
.schedule-flag-off { color: var(--err-ink); }
.schedule-action { flex: 0 0 auto; min-height: 36px; align-self: center; }
.schedule-pager { margin: 12px 0 0; }
#schedule-reload { margin-right: auto; }

@media (max-width: 760px) {
  /* 390px：每一列疊成兩段（時間在上、內容在下），動作按鈕整行、44px 命中區。
     不加任何圓角盒子，維持同一條分隔線的節奏，也不會產生橫向捲動。 */
  .schedule-row { flex-direction: column; align-items: stretch; gap: 10px; padding: 14px 2px; }
  .schedule-main { flex-direction: column; gap: 6px; }
  .schedule-when { flex: 0 0 auto; }
  .schedule-when-label { display: inline; margin-right: 6px; }
  .schedule-when-time { display: inline; }
  .schedule-timing { margin-left: 8px; margin-top: 0; }
  .schedule-action { width: 100%; min-height: 44px; align-self: stretch; }
  .schedule-list { max-height: none; }
  /* 四個篩選排成 2×2：390px 下一排放不下，橫向捲動會把「全部排程」藏起來（而且會冒出捲軸）。
     方格讓四個同時看得見，每一格仍然是 44px 的命中區。 */
  .schedule-tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0;
    border-bottom: 0; border-top: 1px solid var(--line); margin: 4px 0 12px; }
  .schedule-tab { justify-content: space-between; padding: 0 10px; margin: 0;
    border-bottom: 1px solid var(--line); border-right: 1px solid var(--line); }
  .schedule-tab:nth-child(2n) { border-right: 0; }
  .schedule-tab.is-current { border-bottom-color: var(--accent); }
  .dialog .schedule-filters .btn { min-height: 44px; }
  .schedule-pager .btn { min-height: 44px; }
  #schedule-dialog .dialog-actions .btn { min-height: 44px; }
  /* 手機沒有 Esc：關閉與重新整理都要在第一屏就摸得到，而且是 44px 的命中區。 */
  .schedule-head { margin: -22px -22px 0; padding: 14px 22px 10px; }
  .schedule-head-actions .btn { min-height: 44px; min-width: 44px; }
}

/* ---------------------------------------------- 提醒中心（第廿六切片）
   版面完全沿用活動排程總覽（.dialog-schedule / .schedule-*），這裡只補三處差異：
   分類只有三個（所以窄畫面用三欄而不是 2×2）、左上角是「原因」而不是時間，
   以及覆蓋範圍那句說明。刻意沒有任何未讀徽章或紅點——這裡沒有已讀狀態。 */
#attention-reload { margin-right: auto; }
.attention-list { max-height: 54vh; }
/* 原因標籤固定寬度，讓一整欄的標籤可以垂直對齊掃視（和排程總覽的時間欄同一個作用）。 */
.attention-reason { display: block; font-size: 12px; font-weight: 650; line-height: 1.4; overflow-wrap: anywhere; }
/* 只有「確定有問題」上紅色。restricted／rate_limited／inconclusive 是**我們被擋下來**，
   不是連結壞掉，所以維持中性色——顏色也是一種說法，不能比文字更武斷。 */
.attention-reason-issue { color: var(--err-ink); }
.attention-reason-unclear { color: var(--warn-ink); }
.attention-reason-ending_soon { color: var(--ink); }
#attention-coverage { margin-top: 10px; }

/* ---------------------------------------------- 批次檢查目的網址（第廿五切片） */
.batch-check-list { list-style: none; margin: 0; padding: 0; max-height: 38vh; overflow-y: auto; overflow-x: hidden; }
.batch-check-row { padding: 10px 2px; border-top: 1px solid var(--line); }
.batch-check-row:first-child { border-top: 0; }
.batch-check-url { margin: 0; font-size: 13px; overflow-wrap: anywhere; }
.batch-check-dest { margin: 3px 0 0; font-size: 11px; color: var(--ink-soft); overflow-wrap: anywhere; }
.batch-check-outcome { margin: 5px 0 0; }
.batch-check-verdict { margin: 5px 0 0; font-size: 13px; overflow-wrap: anywhere; }
/* 只有「無法完成」上紅色：completed 即使結果是 404 也只是「診斷完成」，
   那一條的健康度由它自己的結論文字說明，不由列的底色說。 */
.batch-check-error .batch-check-verdict { color: var(--err-ink); }
.batch-check-conflict .batch-check-verdict { color: var(--warn-ink); }

/* ---------------------------------------------- UTM 命名字典（第廿四切片） */
.utm-terms { margin-top: 22px; padding-top: 16px; border-top: 1px solid var(--line); }
.utm-terms h3 { margin: 0 0 4px; font-size: 15px; }
.utm-terms-list { list-style: none; margin: 0; padding: 0; max-height: 34vh; overflow-y: auto; overflow-x: hidden; }
.utm-term-row { display: flex; align-items: flex-start; gap: 14px; padding: 11px 2px; border-top: 1px solid var(--line); }
.utm-term-row:first-child { border-top: 0; }
/* 已封存的列降低對比但**不刪除線**：它沒有被刪掉，隨時可以還原。 */
.utm-term-row.is-archived { opacity: .62; }
.utm-term-main { flex: 1 1 auto; min-width: 0; }
.utm-term-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin: 0; }
.utm-term-value { font-size: 13px; overflow-wrap: anywhere; }
.utm-term-aliases { margin: 4px 0 0; font-size: 11px; color: var(--ink-soft); overflow-wrap: anywhere; }
.utm-term-actions { flex: 0 0 auto; display: flex; gap: 6px; align-items: center; }

@media (max-width: 760px) {
  /* 三個分類排成**兩欄**，第三個橫跨整列。
     原本排三欄：390px 下每一格只有約 103px，而「排程即將結束」加上計數的實際寬度超過那個數字，
     文字與計數就會溢出到隔壁那一顆上（不是換行，因為 .schedule-tab 是 white-space: nowrap）。
     兩欄讓每一格有約 165px，最長的標籤加計數都放得下，而且每一格仍然是 44px 的命中區。 */
  #attention-kinds { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0;
    border-bottom: 0; border-top: 1px solid var(--line); margin: 4px 0 12px; }
  #attention-kinds .schedule-tab { justify-content: space-between; padding: 0 8px; margin: 0;
    min-width: 0; border-bottom: 1px solid var(--line); border-right: 1px solid var(--line); }
  /* 每一列最右邊那一顆不畫右框（兩欄＝第二顆）。 */
  #attention-kinds .schedule-tab:nth-child(2n) { border-right: 0; }
  /* 第三顆自己一列、橫跨兩欄；它也是該列最右邊，同樣不畫右框。 */
  #attention-kinds .schedule-tab:last-child { grid-column: 1 / -1; border-right: 0; }
  /* 計數永遠不被壓縮：標籤再長也只會擠到自己的空間，不會把數字推出格子外。 */
  #attention-kinds .schedule-tab-count { flex-shrink: 0; }
  .attention-list { max-height: none; }
  #attention-dialog .dialog-actions .btn { min-height: 44px; }
  #attention-pager .btn { min-height: 44px; }
  /* 每一列疊成兩段、動作按鈕整行（與排程總覽同一套節奏）。 */
  .attention-row .schedule-action { width: 100%; min-height: 44px; align-self: stretch; }
  /* 手機沒有 Esc：關閉與重新整理都要在第一屏就摸得到。 */
  #attention-dialog .schedule-head { margin: -22px -22px 0; padding: 14px 22px 10px; }
  #attention-dialog .schedule-head-actions .btn { min-height: 44px; min-width: 44px; }

  .batch-check-list { max-height: none; }
  #batch-check-dialog .dialog-actions .btn { min-height: 44px; }
  #batch-check-dialog .schedule-head { margin: -22px -22px 0; padding: 14px 22px 10px; }
  #batch-check-dialog .schedule-head-actions .btn { min-height: 44px; min-width: 44px; }

  /* 字典的每一列疊成兩段，兩顆操作按鈕各佔一半、都是 44px。 */
  .utm-term-row { flex-direction: column; align-items: stretch; gap: 8px; }
  .utm-term-actions { width: 100%; }
  .utm-term-actions .btn { flex: 1 1 0; min-height: 44px; }
  .utm-terms-list { max-height: none; }
  #utm-terms-pager .btn { min-height: 44px; }
  .utm-terms .schedule-filters .btn { min-height: 44px; }
}

/* 第廿四切片：範本對話框現在同時裝著範本與命名字典，內容很長，所以標題列改用 .schedule-head
   （已經是 sticky、有底色、窄畫面也已經是 44px 命中區），這裡只補對話框自己的按鈕高度。 */
@media (max-width: 760px) {
  #templates-dialog .dialog-actions .btn { min-height: 44px; }
  #templates-dialog .schedule-head-actions .btn { min-height: 44px; min-width: 44px; }
}

/* ------------------------------------------------------------------ 第三十切片：期間比較／報表分享／QR 樣式
   三個都住在既有的對話框語彙裡：中性面板、細邊框、綠色只用在「現在選到的」與主要動作。
   沒有新的顏色系統，也沒有任何純裝飾的容器。 */

/* 注意權重：`.dialog fieldset` 與 `.dialog form` 都是 (0,1,1)，單寫一個 class (0,1,0) 蓋不過去
   （會被 flex-direction: column + gap: 16px 蓋回來，欄位之間撐出很高的空白）。所以下面凡是要改
   fieldset／form 排版的規則一律寫成 `.dialog .x` (0,2,0)，與既有的 `.dialog .batch-choices` 同一套做法。
   同理，`.btn` 的 38px 與 `.btn-small` 的 32px 也要用 `.dialog #id` / `.dialog .class` 才蓋得過。

   可點高度：這一輪新增的控制項在**桌機與手機都**至少 44px。桌機本來沒有這個硬性要求，
   但這幾個對話框的動作列是黏在下緣的細長一條，44px 才不會在觸控筆電與外接觸控螢幕上難按。 */
.dialog .compare-toggle label,
.dialog .qr-presets label,
.dialog #analytics-compare-daily-section summary,
.dialog .analytics-actions .btn,
.dialog .report-share-actions .btn,
.dialog .qr-actions .btn,
.dialog #analytics-share-button,
.dialog #analytics-export,
.dialog #report-share-create,
.dialog #report-share-refresh,
.dialog #report-share-copy,
.dialog #report-share-list-body .btn,
.dialog #qr-apply,
.dialog #qr-download-png,
.dialog #qr-download-svg,
.dialog .qr-style-grid input { min-height: 44px; }

/* 期間比較。比較結果排在摘要卡正下方，因為那是使用者打開比較時真正想看的東西。
   差異欄用表格數字（tabular-nums）對齊，正負只靠顏色會讓色盲讀者看不懂，所以文字一定帶 + / − 符號。 */
.compare-toggle { display: flex; align-items: center; gap: .4rem; }
.compare-toggle label { display: inline-flex; align-items: center; gap: .4rem; }
.dialog .compare-fields { border: 1px solid var(--line); border-radius: var(--radius); padding: .7rem .8rem; margin: 0;
  display: flex; flex-direction: row; flex-wrap: wrap; gap: .6rem .9rem; align-items: flex-end; background: #f7f9f7; }
.dialog .compare-fields legend { font-size: .85rem; color: var(--ink-soft); padding: 0 .3rem; }
.dialog .compare-fields .hint { flex: 1 1 100%; margin: 0; }
#analytics-compare-section { border: 1px solid var(--line); border-radius: var(--radius); padding: .8rem .9rem; }
.compare-table td.num, .compare-table th.num { font-variant-numeric: tabular-nums; }
.compare-delta-up { color: var(--ok-ink); }
.compare-delta-down { color: var(--err-ink); }
.compare-delta-none { color: var(--ink-soft); }
.compare-daily-wrap { max-height: 34vh; overflow: auto; }
#analytics-compare-daily-section summary { cursor: pointer; color: var(--ink-soft); font-size: .88rem; display: flex; align-items: center; }
/* 表頭不換行：窄畫面上「對照期」被逐字拆成三行完全看不懂。表格本來就包在 .table-wrap
   （overflow-x: auto）裡，寧可讓那一塊橫向捲動，也不要把標題折成直書。 */
.dialog .compare-table th, .dialog .compare-table td,
.dialog #analytics-compare-daily-table th, .dialog #analytics-compare-daily-table td,
.dialog #report-share-preview-totals-table th,
.dialog #report-share-list-table th { white-space: nowrap; }
/* 表格不換行之後就一定比容器寬。`.dialog-body section` 是直向 flex，裡面每一塊都要允許收縮到
   比內容窄，才會由 .table-wrap 自己橫向捲動，而不是把整個對話框撐出水平捲軸。 */
#analytics-compare-section, #report-share-preview-section, #report-share-list-section { min-width: 0; }
#analytics-compare-section > *, #report-share-preview-section > *, #report-share-list-section > * { min-width: 0; max-width: 100%; }
#analytics-compare-section .table-wrap, #report-share-preview-section .table-wrap,
#report-share-list-section .table-wrap { max-width: 100%; }

/* 報表分享。公開內容的預覽排在表單**之前**：使用者要先看到會流出去什麼，才決定要不要按建立。 */
.dialog .report-share-form { display: flex; flex-direction: row; flex-wrap: wrap; gap: .6rem .9rem; align-items: flex-end;
  border-top: 1px solid var(--line); padding: .8rem 0 0; }
.dialog .report-share-form .field { flex: 1 1 14rem; }
.report-share-preview-head { margin: 0; }
.report-share-url { padding: .55rem .7rem; border: 1px solid var(--line-strong); border-radius: var(--radius);
  background: var(--info-bg); word-break: break-all; user-select: all; }
.report-share-result-actions { display: flex; gap: .4rem; flex-wrap: wrap; }
#report-share-result { border: 1px solid var(--accent); border-radius: var(--radius); padding: .8rem .9rem; }
.notice-warn { background: var(--warn-bg); color: var(--warn-ink); margin-bottom: .5rem; }
#report-share-dialog .notice { margin-bottom: 0; }
.share-state { display: inline-flex; align-items: center; gap: .3rem; font-size: .82rem; }
.share-state-public { color: var(--ok-ink); }
.share-state-expired, .share-state-revoked, .share-state-invalidated { color: var(--ink-soft); }

/* QR 樣式。色票用原生 <input type="color">（不必自己做選色器），數字用 number 欄位。
   「更新預覽」是明確的動作，不即時重算：每改一個字就打一次 API 只會讓人看到一連串閃動的圖。 */
.dialog .qr-style { border: 1px solid var(--line); border-radius: var(--radius); padding: .7rem .8rem; margin: 0;
  display: flex; flex-direction: column; gap: .6rem; background: #f7f9f7; }
.dialog .qr-style legend { font-size: .85rem; color: var(--ink-soft); padding: 0 .3rem; }
.qr-presets { display: flex; flex-wrap: wrap; gap: .4rem 1rem; }
.qr-presets label { display: inline-flex; align-items: center; gap: .35rem; }
/* 固定 2×2：auto-fit 在這個寬度會排成 3＋1，最後一個欄位孤零零掉到下一行，看起來像壞掉。 */
.dialog .qr-style-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .5rem .7rem; }
.dialog .qr-style-grid input[type="color"] { width: 100%; padding: 2px; }
.dialog #qr-apply { align-self: flex-start; }

/* 三個對話框的動作列都黏在下緣：這些內容都很長（比較表、每日對照、公開內容預覽、每日趨勢），
   捲到一半找不到「關閉」是最糟的情況，手機上又沒有 Esc。負的水平 margin ＋ padding 讓底色蓋滿
   對話框內距；margin 必須跟著 .dialog-body 的內距走，否則會多出水平捲軸。 */
.analytics-actions, .report-share-actions, .qr-actions { position: sticky; bottom: 0; z-index: 3;
  margin: 6px -28px -28px; padding: 14px 28px 20px; background: var(--panel); border-radius: 0 0 18px 18px; }

@media (max-width: 640px) {
  .dialog .compare-fields, .dialog .report-share-form { flex-direction: column; align-items: stretch; }
  .dialog .compare-fields .field, .dialog .report-share-form .field { flex: 1 1 100%; }
  #analytics-compare-toggle, #qr-preset-bw, #qr-preset-green, #qr-preset-navy, #qr-preset-custom { min-width: 22px; min-height: 22px; }
  /* 黏住的動作列要跟著對話框縮小的內距走（與 .routing-actions 同一套）。 */
  .analytics-actions, .report-share-actions, .qr-actions { margin: 6px -22px -22px; padding: 12px 22px 18px; border-radius: 0 0 16px 16px; }
  /* 390px：動作列維持**一列**。三顆按鈕直排會吃掉將近 180px，把報表本身擠到看不見。
     等寬平分、縮小左右內距、字略小；文字仍然不換行，所以不會有半個字掉出按鈕。 */
  .dialog .analytics-actions, .dialog .report-share-actions, .dialog .qr-actions {
    flex-wrap: nowrap; justify-content: stretch; gap: 6px;
  }
  .dialog .analytics-actions .btn, .dialog .report-share-actions .btn, .dialog .qr-actions .btn {
    flex: 1 1 0; min-width: 0; padding-left: 8px; padding-right: 8px; font-size: 13px;
  }
  .report-share-url { font-size: .85rem; }
}

@media (prefers-reduced-motion: reduce) {
  #analytics-compare-section, #report-share-result, .qr-style { transition: none; }
}

/* ---------- 排程檢查、Webhook 通知與成效摘要（第卅一切片） ----------
   三個畫面共用既有的 .schedule-list／.schedule-row 節奏（同一條分隔線、同樣的留白），
   不引進新的卡片層級。顏色只用在「狀態」與「這裡有風險」兩件事上。 */

/* 排程設定與 Webhook 建立表單。
   **權重陷阱**：這兩塊都是 <form>，會吃到 `.dialog form { display: flex; flex-direction: column }`，
   而那條規則的權重是 (0,1,1)。單寫 `.schedule-form` 只有 (0,1,0)，蓋不過去——
   結果 `flex: 0 1 200px` 的 200px 會被當成**高度**，每個欄位各佔一列、右邊留一大塊空白。
   （662／730／1022 三處註解記的是同一個坑。）所以一律寫成 `.dialog .schedule-form` (0,2,0)。 */
.dialog .schedule-form { display: flex; flex-wrap: wrap; flex-direction: row; align-items: flex-end;
  gap: 12px 16px; margin: 0 0 18px; padding: 0; }
.dialog .schedule-form .field { flex: 0 1 200px; }
.dialog .schedule-form .field-grow { flex: 1 1 240px; }
.schedule-form-actions { display: flex; gap: 8px; margin-left: auto; }
.schedule-form-actions .btn { min-height: 44px; }
/* 勾選框與標籤同一行；命中區涵蓋整段文字，不是只有那個小方塊。 */
.checkbox-field { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; cursor: pointer; }
.checkbox-field input { width: 18px; height: 18px; }

/* 「下一次／最近一次」兩格並排；數字用等寬字，一欄掃下來對得齊。 */
.schedule-summary { display: flex; flex-wrap: wrap; gap: 10px 32px; margin: 0 0 14px; }
.schedule-summary div { min-width: 0; }
.schedule-summary dt { font-size: 10px; letter-spacing: .5px; color: #8b968e; }
.schedule-summary dd { margin: 2px 0 0; font-size: 14px; font-weight: 600;
  font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }

.section-title { margin: 22px 0 6px; font-size: 12px; font-weight: 650; letter-spacing: .4px; color: var(--ink-soft); }
/* 執行紀錄與投遞紀錄的列：標題 + 狀態徽章一行，細節一行。 */
.schedule-title { font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.schedule-detail { margin: 4px 0 0; font-size: 12px; color: var(--ink-soft); overflow-wrap: anywhere; }
.schedule-row > .btn { flex: 0 0 auto; align-self: center; min-height: 36px; }
.notice-error { background: var(--err-bg); color: var(--err-ink); }

/* Webhook 列表：一列一個接收端，主機名稱與指紋放細節那一行。 */
.webhook-list .schedule-row { align-items: center; }

/* 一次性祕密：整塊用警示底色，因為它真的只出現這一次。
   祕密本身用等寬字並允許在任何位置斷行，長字串不會撐出橫向捲動。 */
.secret-result { margin: 4px 0 18px; padding: 14px 16px; border-radius: var(--radius);
  background: var(--warn-bg); border: 1px solid #e9d9b4; }
.secret-result h3 { margin: 0 0 6px; font-size: 13px; color: var(--warn-ink); }
.secret-result .btn { min-height: 44px; margin-top: 10px; }
.secret-value { display: block; margin: 8px 0 0; padding: 10px 12px; border-radius: 8px;
  background: var(--panel); border: 1px solid var(--line-strong);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 13px;
  overflow-wrap: anywhere; word-break: break-all; user-select: all; }

/* 送出內容預覽：等寬、可捲動、永遠以純文字呈現（JS 只用 textContent 寫進去）。 */
.payload-preview { margin: 8px 0 0; padding: 12px 14px; max-height: 220px; overflow: auto;
  border-radius: 8px; background: #f4f6f4; border: 1px solid var(--line);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px;
  line-height: 1.6; white-space: pre-wrap; overflow-wrap: anywhere; }
.payload-headers { list-style: none; margin: 10px 0 0; padding: 0; font-size: 12px; color: var(--ink-soft); }
.payload-headers li { padding: 3px 0; overflow-wrap: anywhere;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.payload-headers li.hint { font-family: inherit; margin-top: 8px; }

/* 成效摘要：結論一句話在最上面，每一條事實各自帶著自己的限制。
   刻意不做成卡片，維持報表其他區段的閱讀節奏。 */
#analytics-summary-section { margin-top: 28px; padding-top: 20px; border-top: 1px solid var(--line); }
#analytics-summary-section h3 .muted { font-size: 11px; font-weight: 450; }
.summary-headline { margin: 6px 0 14px; font-size: 15px; font-weight: 600; line-height: 1.6; }
.summary-facts { list-style: none; margin: 0; padding: 0; }
.summary-fact { padding: 10px 0; border-top: 1px solid var(--line); }
.summary-fact:first-child { border-top: 0; }
.summary-fact-text { display: block; font-size: 13px; line-height: 1.6; overflow-wrap: anywhere; }
.summary-fact .hint { margin: 4px 0 0; }
.summary-caveats { margin: 14px 0 0; }
.summary-caveats summary { min-height: 44px; display: flex; align-items: center;
  font-size: 12px; color: var(--ink-soft); cursor: pointer; }
.summary-caveats ul { margin: 4px 0 0; padding-left: 20px; font-size: 12px; color: var(--ink-soft); }
.summary-caveats li { padding: 3px 0; }
.summary-copy-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin: 16px 0 8px; }
.summary-copy-row .btn { min-height: 44px; }
.summary-copy-row .hint { flex: 1 1 240px; margin: 0; }
/* 可複製的文字框：唯讀，但要看得出來是可以選取的內容，不是一個輸入欄位。 */
.summary-text { width: 100%; padding: 12px 14px; border: 1px solid var(--line);
  border-radius: 8px; background: #f8faf8; color: var(--ink);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px;
  line-height: 1.7; resize: vertical; }

@media (max-width: 760px) {
  /* 390px：設定欄位直排、儲存鍵整行；紀錄列沿用 .schedule-row 已有的直排規則。 */
  .dialog .schedule-form { flex-direction: column; align-items: stretch; gap: 12px; }
  .dialog .schedule-form .field, .dialog .schedule-form .field-grow { flex: 1 1 auto; }
  .schedule-form-actions { margin-left: 0; }
  .schedule-form-actions .btn { flex: 1 1 auto; }
  .schedule-summary { gap: 12px 20px; }
  .webhook-list .schedule-row { align-items: stretch; }
  .schedule-row > .btn { width: 100%; min-height: 44px; align-self: stretch; }
  /* 手機沒有 Esc：這兩個對話框的關閉與重新整理都要在第一屏、44px 命中區。 */
  #check-schedule-dialog .dialog-actions .btn, #webhook-dialog .dialog-actions .btn { min-height: 44px; }
  .summary-copy-row .btn { width: 100%; }
  .payload-preview { max-height: 160px; }
}

/* ---------- 第卅一切片的介面修正（依瀏覽器實測回饋） ---------- */
/* 排程設定在桌機排成兩欄：原本每個欄位各佔一行，一個只有三格的表單被拉成一整個畫面高。 */
/* 桌機排兩欄。同樣要 `.dialog` 前綴才蓋得過 `.dialog form`；`flex: initial` 讓 grid 決定尺寸，
   否則上面那條 `flex: 0 1 200px` 的基準值會在 grid 裡繼續干擾。 */
@media (min-width: 761px) {
  .dialog .schedule-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: end; gap: 14px 18px; }
  .dialog .schedule-form .field, .dialog .schedule-form .field-grow { flex: initial; min-width: 0; }
  .dialog .schedule-form .checkbox-field { grid-column: 1 / -1; }
  .dialog .schedule-form fieldset.field { grid-column: 1 / -1; }
  .dialog .schedule-form .schedule-form-actions { grid-column: 1 / -1; margin-left: auto; }
}
/* Webhook 的建立表單同理（id 選擇器權重夠，但仍寫明 flex: initial 讓 grid 說了算）。 */
#webhook-create-form { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  gap: 12px 16px; padding: 0; }
#webhook-create-form .field, #webhook-create-form .field-grow { flex: initial; min-width: 0; }
#webhook-create-form .schedule-form-actions { grid-column: 1 / -1; }
@media (max-width: 760px) {
  #webhook-create-form { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .dialog .schedule-form { display: flex; flex-direction: column; align-items: stretch; gap: 12px; }
  .dialog .schedule-form .field, .dialog .schedule-form .field-grow { flex: 1 1 auto; }
  /* 手機沒有 Esc：這幾個對話框的關閉列黏在底部，永遠摸得到。 */
  #check-schedule-dialog .dialog-actions,
  #webhook-dialog .dialog-actions,
  #qr-batch-dialog .dialog-actions {
    position: sticky; bottom: 0; z-index: 3; background: var(--panel);
    margin: 6px -22px -22px; padding: 12px 22px 18px; border-top: 1px solid var(--line);
    border-radius: 0 0 16px 16px;
  }
  #qr-batch-dialog .dialog-actions .btn { min-height: 44px; }
}
/* 批次 QR：格式是單選群組，清單只列短碼與短網址。 */
#qr-batch-form fieldset.field { border: 1px solid var(--line); border-radius: 8px; padding: 10px 14px 12px; }
#qr-batch-form fieldset.field legend { padding: 0 4px; font-size: 11px; color: var(--ink-soft); }
/* `.field input { width: 100%; min-height: 40px }` 會把單選圓鈕撐成一個巨大的圓，
   而且每個各佔一整列。圓鈕本身固定 16×16，44px 的命中區交給包在外面的 label。 */
#qr-batch-form fieldset.field label { display: flex; align-items: center; gap: 10px;
  min-height: 44px; cursor: pointer; }
#qr-batch-form fieldset.field input[type="radio"] {
  width: 16px; height: 16px; min-height: 0; flex: 0 0 16px; margin: 0; padding: 0;
}
#qr-batch-manifest { max-height: 34vh; }
#qr-batch-manifest .schedule-detail { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }

/* ================================ 第卅二切片：連結清單 CSV 匯出 ＋ 分享的期間比較 ============== */

/* 匯出對話框用的是 .dialog-schedule 的版面節奏（清單、列、行距），但**不要**它 960px 的寬度：
   這裡只有一個下拉、一顆按鈕和一份清單，撐到 960px 只會讓按鈕孤零零地飄在右邊，
   說明文字也被拉成很難讀的長行。720px 已經夠放下「狀態／時間／列數／檔名」那一列。 */
#link-export-dialog { width: min(720px, calc(100vw - 32px)); }
#link-export-dialog .schedule-list { max-height: 38vh; }
#link-export-dialog .dialog-toolbar .btn { min-height: 44px; }
#link-export-dialog .schedule-row > .btn { min-height: 44px; }
/* 這是 <form>，會吃到 `.dialog form { flex-direction: column }`。這裡要的是「下拉 ＋ 按鈕同一列」，
   所以用 `.dialog #link-export-form`（0,1,1 ＋ id）把權重拉到壓得過 `.dialog fieldset`／`.dialog form`
   的程度——與既有的 `.dialog .staff-filters`、`.dialog .routing-block` 是同一個理由、同一套寫法。 */
.dialog #link-export-form { display: flex; flex-direction: row; flex-wrap: wrap;
  align-items: flex-end; gap: 12px; padding: 0; }
.dialog #link-export-form .field { flex: 1 1 12rem; min-width: 0; }
.dialog #link-export-current { gap: .35rem; }
/* 狀態那一行是這個對話框最重要的一句話（「已排隊」與「沒有人在處理」是兩件事）。 */
.export-state { margin: 0; font-size: 13px; font-weight: 600; }
.export-state-ok { color: var(--ok, #1d6b45); }
.export-state-warn { color: var(--warn, #8a6116); }
.export-state-error { color: var(--danger, #a3402f); }
#link-export-list .schedule-row > .btn { align-self: center; }

/* 分享對話框的「一併公開期間比較」。整塊只有在報表本身已經開啟比較時才出現（hidden 由 JS 控制）。
   `.dialog fieldset`／`.dialog form` 的 flex 規則會把這裡的排版蓋掉，所以同樣用 id 提高權重。 */
.dialog #report-share-compare-block { display: flex; flex-direction: column; gap: 6px;
  border: 1px solid var(--line); border-radius: 8px; padding: 10px 14px 12px; }
.share-compare-toggle { display: flex; align-items: center; gap: 10px; min-height: 44px; cursor: pointer; }
.share-compare-toggle input[type="checkbox"] {
  width: 16px; height: 16px; min-height: 0; flex: 0 0 16px; margin: 0; padding: 0;
}
.share-periods { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin: 0; padding: 0; }
.share-period { border: 1px solid var(--line); border-radius: 8px; padding: 8px 12px; min-width: 0; }
.share-period dt { font-size: 11px; color: var(--ink-soft); }
.share-period dd { margin: 2px 0 0; font-size: 13px; font-weight: 600; overflow-wrap: anywhere; }

@media (max-width: 640px) {
  .share-periods { grid-template-columns: minmax(0, 1fr); }
  .dialog #link-export-form { flex-direction: column; align-items: stretch; }
  .dialog #link-export-form .field { flex: 1 1 auto; }
  #report-share-compare-toggle { min-width: 22px; min-height: 22px; }
  /* 手機沒有 Esc：關閉列黏在底部，永遠摸得到（與其他幾個對話框同一套）。 */
  #link-export-dialog .dialog-actions {
    position: sticky; bottom: 0; z-index: 3; background: var(--panel);
    margin: 6px -22px -22px; padding: 12px 22px 18px; border-top: 1px solid var(--line);
    border-radius: 0 0 16px 16px;
  }
  #link-export-dialog .dialog-actions .btn,
  #link-export-dialog .dialog-toolbar .btn { min-height: 44px; }
}

/* 全站保留盤點與交接資產：沿用工作區的字級、間距與狀態色。 */
.dialog-retention .retention-form { padding: 12px 0; display: flex; flex-direction: row; align-items: end; gap: 16px; border-block: 1px solid var(--line); }
.retention-overview, .retention-projects, .handoff-asset-impact { overflow-wrap: anywhere; }
.retention-overview p, .retention-projects p, .handoff-asset-impact p { margin: 8px 0; }
.retention-projects, .handoff-asset-impact { max-height: 260px; overflow-y: auto; }
.retention-ack, .handoff-automation-option { display: flex; align-items: center; gap: 10px; min-height: 44px; margin: 16px 0; }
.retention-ack input, .handoff-automation-option input { flex: 0 0 auto; width: 18px; height: 18px; }
.dialog-retention .dialog-actions { position: sticky; bottom: 0; background: var(--panel); padding-top: 12px; }
@media (max-width: 600px) {
  .dialog-retention .retention-form { align-items: stretch; flex-direction: column; }
  .dialog-retention button, .dialog-retention input { min-height: 44px; }
  .retention-ack input { min-height: 18px; }
}

.dialog-retention .btn-danger { background: var(--err-ink); color: #fff; border-color: var(--err-ink); }

.dialog-retention .dialog-body { gap: 12px; }
.dialog-retention .retention-overview p { margin: 4px 0; }

/* 連結工作台：先讀情境與摘要，再選擇操作。 */
.actions-dialog { width: min(900px, calc(100vw - 32px)); }
.workspace-link { border: 0; background: transparent; padding: 0; text-align: left; font: inherit; color: inherit; cursor: pointer; min-height: 32px; overflow-wrap: anywhere; }
.workspace-link:hover { text-decoration: underline; }
.workspace-destination { font-size: 12px; color: var(--ink-soft); overflow-wrap: anywhere; margin: 0 0 20px; }
.action-link-url { overflow-wrap: anywhere; }
.workspace-summary { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; padding: 20px 0; border-block: 1px solid var(--line); }
.workspace-metric { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.workspace-metric-label { color: var(--ink-soft); font-size: 12px; }
.workspace-metric > strong { font-size: 22px; font-variant-numeric: tabular-nums; }
.workspace-metric-note { font-size: 12px; line-height: 1.6; overflow-wrap: anywhere; color: var(--ink-soft); }
.workspace-measurement-note { font-size: 12px; line-height: 1.7; color: var(--ink-soft); margin: 12px 0 24px; }
.link-actions-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
.workspace-tool-section { min-width: 0; }
.workspace-tool-section h3 { margin: 0 0 10px; font-size: 13px; }
.workspace-tool-section .link-tool { width: 100%; gap: 10px; padding: 12px 4px; min-height: 64px; }
.workspace-tool-section .tool-symbol { width: 30px; height: 30px; background: transparent; }
.workspace-tool-section .tool-words { min-width: 0; }
.workspace-tool-section .tool-words > span { font-size: 12px; line-height: 1.5; }
.workspace-tool-section .tool-arrow { flex-shrink: 0; }
@media (max-width: 680px) {
  .workspace-summary, .link-actions-grid { grid-template-columns: 1fr; gap: 16px; }
  .workspace-metric { gap: 4px; }
  .workspace-metric > strong { font-size: 20px; }
  .workspace-tool-section + .workspace-tool-section { border-top: 1px solid var(--line); padding-top: 16px; }
  .workspace-link { min-height: 44px; }
}

/* 欄寬依欄位用途設定，避免選取欄插入後把網址欄錯當狀態欄。 */
.link-content { flex: 1 1 0; }
.cell-short .workspace-link { min-width: 0; flex: 1 1 0; white-space: normal; overflow-wrap: anywhere; }
.destination-address { white-space: normal; overflow-wrap: anywhere; }
@media (min-width: 601px) {
  .links { min-width: 820px; }
}

.link-name { font-size: 15px; font-weight: 600; overflow-wrap: anywhere; margin-bottom: 4px; }

.link-status-switch { display: inline-flex; align-items: center; gap: 8px; border: 0; background: transparent; color: var(--ink-soft); padding: 0; min-height: 44px; cursor: pointer; font: inherit; white-space: nowrap; }
.status-switch-track { width: 40px; height: 24px; border-radius: 16px; background: #a5ada8; padding: 3px; flex-shrink: 0; box-sizing: border-box; }
.status-switch-thumb { display: block; width: 18px; height: 18px; background: #fff; border-radius: 50%; transition: transform .15s ease; box-shadow: 0 1px 3px #0002; }
.link-status-switch[aria-checked="true"] .status-switch-track { background: #347653; }
.link-status-switch[aria-checked="true"] .status-switch-thumb { transform: translateX(16px); }
.status-switch-label { font-size: 12px; }
.link-status-switch:disabled { cursor: default; opacity: .55; }
@media (prefers-reduced-motion: reduce) { .status-switch-thumb { transition: none; } }

/* 同事試用回饋：日常指標優先，低頻設定按需展開。 */
.dialog .advanced-settings { border: 1px solid var(--line); border-radius: var(--radius); padding: 12px 16px; min-width: 0; }
.dialog .advanced-settings > summary { cursor: pointer; min-height: 44px; align-content: center; font-weight: 600; }
.dialog .advanced-settings[open] > summary { margin-bottom: 16px; }
.dialog .analytics-core { grid-template-columns: 1fr; }
.dialog .advanced-settings .analytics-cards { margin-top: 12px; }
