/** * demand-radar 樣式落點(商機雷達+成交 CRM)。 * * global.css 已經 6,000 多行,radar/crm 的樣式一律寫在這裡,不再往那邊加。 * 顏色、字級、間距只能引用 tokens.css 的 --hb-*,否則深淺模式會有一半畫面不跟著切 * (scripts/check-tokens.mjs 會擋)。 * * 分區:訂閱與服務檔案(M1)→ 統計列與商機卡(M2)→ 回覆(M3)→ CRM 階段與時間軸(M4) * → 追單(M5)→ 轉換統計(M6)。各 FE task 把細節補進對應分區。 */ /* ---------- 共用 ---------- */ .hb-radar-page { display: flex; flex-direction: column; gap: var(--hb-space-5); } .hb-radar-section { display: flex; flex-direction: column; gap: var(--hb-space-3); } .hb-radar-section__title { font-size: var(--hb-text-lg); font-weight: 600; color: var(--hb-ink); } .hb-radar-section__hint { font-size: var(--hb-text-sm); color: var(--hb-muted); } /** 空狀態一律要說「為什麼空」與「下一步做什麼」,不是只寫「沒有資料」。 */ .hb-radar-empty { display: flex; flex-direction: column; gap: var(--hb-space-2); padding: var(--hb-space-6); border: 1px dashed var(--hb-line-strong); border-radius: var(--hb-radius-lg); background: var(--hb-surface-muted); color: var(--hb-muted); font-size: var(--hb-text-sm); } .hb-radar-chip { display: inline-flex; align-items: center; gap: var(--hb-space-1); padding: var(--hb-space-1) var(--hb-space-3); border: 1px solid var(--hb-line-strong); border-radius: var(--hb-radius-pill); background: var(--hb-surface-solid); font-size: var(--hb-text-xs); color: var(--hb-ink-secondary); } .hb-radar-chip--exclude { border-color: color-mix(in srgb, var(--hb-danger) 45%, var(--hb-line-strong)); color: var(--hb-danger-deep); } /* ---------- M1:服務檔案/雷達訂閱 ---------- */ /** 服務/案例/FAQ 都是「幾個窄欄位+刪除鈕」,窄螢幕改成單欄疊起來。 */ .hb-radar-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); align-items: end; gap: var(--hb-space-3); padding: var(--hb-space-3); border: 1px solid var(--hb-line); border-radius: var(--hb-radius-lg); background: var(--hb-surface); } .hb-radar-area-grid { display: flex; flex-wrap: wrap; gap: var(--hb-space-2); } /** 選取狀態不能只靠顏色:aria-pressed 之外再加粗邊框。 */ .hb-radar-chip.is-active { border-color: var(--hb-brand); border-width: 2px; background: var(--hb-brand-soft); color: var(--hb-brand-deep); font-weight: 600; } .hb-radar-check { display: flex; align-items: center; gap: var(--hb-space-2); font-size: var(--hb-text-sm); color: var(--hb-ink-secondary); } .hb-radar-actions { display: flex; flex-wrap: wrap; gap: var(--hb-space-3); } .hb-radar-watch-list { display: flex; flex-direction: column; gap: var(--hb-space-3); } .hb-radar-watch { display: flex; flex-direction: column; gap: var(--hb-space-2); padding: var(--hb-space-4); border: 1px solid var(--hb-line); border-radius: var(--hb-radius-lg); background: var(--hb-surface); box-shadow: var(--hb-shadow-card); } .hb-radar-watch--paused { opacity: 0.72; } .hb-radar-watch__terms { display: flex; flex-wrap: wrap; gap: var(--hb-space-2); } .hb-radar-watch__meta { display: flex; flex-wrap: wrap; gap: var(--hb-space-3); font-size: var(--hb-text-xs); color: var(--hb-muted); } /** 配額用滿時要看得出是「上限」而不是「錯誤」。 */ .hb-radar-quota { display: flex; align-items: center; gap: var(--hb-space-2); font-size: var(--hb-text-sm); color: var(--hb-ink-secondary); } .hb-radar-quota--full { color: var(--hb-warning-deep); } .hb-radar-form { padding: var(--hb-space-4); border: 1px solid var(--hb-line-strong); border-radius: var(--hb-radius-lg); background: var(--hb-surface); } .hb-radar-suggest-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: var(--hb-space-3); list-style: none; padding: 0; } /** 建議一定要帶理由:沒有理由的關鍵字使用者無法判斷該不該採用。 */ .hb-radar-suggest { display: flex; flex-direction: column; gap: var(--hb-space-2); padding: var(--hb-space-3); border: 1px solid var(--hb-line); border-radius: var(--hb-radius-lg); background: var(--hb-surface-muted); } .hb-radar-suggest__head { display: flex; align-items: center; justify-content: space-between; gap: var(--hb-space-2); } .hb-radar-suggest__term { font-size: var(--hb-text-sm); font-weight: 600; color: var(--hb-ink); } .hb-radar-suggest__reason { font-size: var(--hb-text-xs); color: var(--hb-muted); } /* ---------- M2:今日雷達統計列與商機卡 ---------- */ .hb-radar-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr)); gap: var(--hb-space-3); } .hb-radar-stat { display: flex; flex-direction: column; gap: var(--hb-space-1); padding: var(--hb-space-4); border: 1px solid var(--hb-line); border-radius: var(--hb-radius-lg); background: var(--hb-surface); } .hb-radar-stat__value { font-size: var(--hb-text-2xl); font-weight: 700; color: var(--hb-ink); } .hb-radar-stat__label { font-size: var(--hb-text-xs); color: var(--hb-muted); } .hb-opp-card { display: flex; flex-direction: column; gap: var(--hb-space-3); padding: var(--hb-space-4); border: 1px solid var(--hb-line); border-left: 3px solid var(--hb-line-strong); border-radius: var(--hb-radius-lg); background: var(--hb-surface); box-shadow: var(--hb-shadow-card); } .hb-opp-card--high { border-left-color: var(--hb-success); } .hb-opp-card--mid { border-left-color: var(--hb-warning); } .hb-opp-card--low { border-left-color: var(--hb-subtle); } .hb-opp-card__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--hb-space-3); } .hb-opp-card__meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--hb-space-2); font-size: var(--hb-text-xs); color: var(--hb-muted); } .hb-radar-actions--toolbar { margin-bottom: var(--hb-space-3); } .hb-opp-card__text { font-size: var(--hb-text-base); color: var(--hb-ink); white-space: pre-wrap; } /** 五問判定:每個維度一列,理由是說服使用者的主體,不能折疊成一句總分。 */ .hb-opp-reasons { display: flex; flex-direction: column; gap: var(--hb-space-2); padding: var(--hb-space-3); border-radius: var(--hb-radius); background: var(--hb-surface-muted); } .hb-opp-reason { display: grid; grid-template-columns: 5rem 3rem 1fr; gap: var(--hb-space-2); font-size: var(--hb-text-xs); color: var(--hb-ink-secondary); } /** 地區判不出來不等於不符合,樣式要跟 mismatch 明顯不同。 */ .hb-opp-region--unknown { color: var(--hb-muted); } .hb-opp-region--mismatch { color: var(--hb-warning-deep); } /* ---------- M3:回覆草稿 ---------- */ .hb-reply-variants { display: flex; flex-direction: column; gap: var(--hb-space-3); } .hb-reply-variant { display: flex; flex-direction: column; gap: var(--hb-space-2); padding: var(--hb-space-3); border: 1px solid var(--hb-line); border-radius: var(--hb-radius); background: var(--hb-surface-solid); } .hb-reply-variant__kind { font-size: var(--hb-text-2xs); letter-spacing: 0.04em; text-transform: uppercase; color: var(--hb-muted); } .hb-reply-variant--used { border-color: color-mix(in srgb, var(--hb-success) 40%, var(--hb-line-strong)); } /* ---------- M4:CRM 階段板與時間軸 ---------- */ /** 七階段;needs_follow_up 是並存標記,不佔一格。 */ .hb-crm-stages { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: var(--hb-space-3); } .hb-crm-stage { display: flex; flex-direction: column; gap: var(--hb-space-1); padding: var(--hb-space-3); border: 1px solid var(--hb-line); border-radius: var(--hb-radius); background: var(--hb-surface); cursor: pointer; } .hb-crm-stage.is-active { border-color: var(--hb-brand); background: var(--hb-brand-soft); } .hb-crm-stage__count { font-size: var(--hb-text-xl); font-weight: 700; color: var(--hb-ink); } .hb-crm-stage__label { font-size: var(--hb-text-xs); color: var(--hb-muted); } .hb-crm-timeline { display: flex; flex-direction: column; gap: var(--hb-space-3); padding-left: var(--hb-space-4); border-left: 2px solid var(--hb-line-strong); } .hb-crm-touch { display: flex; flex-direction: column; gap: var(--hb-space-1); font-size: var(--hb-text-sm); color: var(--hb-ink-secondary); } .hb-crm-touch__at { font-size: var(--hb-text-2xs); color: var(--hb-muted); } /* ---------- M5:追單 ---------- */ .hb-followup-row { display: flex; align-items: center; justify-content: space-between; gap: var(--hb-space-3); padding: var(--hb-space-3) var(--hb-space-4); border: 1px solid var(--hb-line); border-radius: var(--hb-radius); background: var(--hb-surface); } .hb-followup-row--overdue { border-color: color-mix(in srgb, var(--hb-danger) 45%, var(--hb-line-strong)); } /* ---------- M6:轉換統計 ---------- */ .hb-crm-stats-table { width: 100%; border-collapse: collapse; font-size: var(--hb-text-sm); } .hb-crm-stats-table th, .hb-crm-stats-table td { padding: var(--hb-space-2) var(--hb-space-3); border-bottom: 1px solid var(--hb-line); text-align: left; color: var(--hb-ink-secondary); } /** 樣本 < 5:只能顯示絕對數,比率與排名要壓下去。 */ .hb-crm-stats-table td.is-insufficient { color: var(--hb-muted); font-style: italic; } /* ---------- CRM board / today cards (M3–M5) ---------- */ .radar-page { display: flex; flex-direction: column; gap: var(--hb-space-5); } .radar-page__header { display: flex; flex-wrap: wrap; gap: var(--hb-space-3); align-items: baseline; } .radar-page__header h1 { font-size: var(--hb-text-xl); font-weight: 600; color: var(--hb-ink); margin: 0; } .radar-stats { font-size: var(--hb-text-sm); color: var(--hb-muted); } .radar-error { color: var(--hb-danger); font-size: var(--hb-text-sm); } .radar-empty { display: flex; flex-direction: column; gap: var(--hb-space-2); padding: var(--hb-space-5); border: 1px dashed var(--hb-line); border-radius: var(--hb-radius); } .radar-card { border: 1px solid var(--hb-line); border-radius: var(--hb-radius); padding: var(--hb-space-3); margin-bottom: var(--hb-space-3); background: var(--hb-surface); color: var(--hb-ink); } .radar-card__head { display: flex; gap: var(--hb-space-2); align-items: center; margin-bottom: var(--hb-space-2); } .radar-card__text { font-size: var(--hb-text-sm); margin: 0 0 var(--hb-space-2); } .radar-card__meta { font-size: var(--hb-text-xs); color: var(--hb-muted); } .radar-card__actions { display: flex; flex-wrap: wrap; gap: var(--hb-space-2); margin-top: var(--hb-space-2); } .radar-card__reply { white-space: pre-wrap; font-size: var(--hb-text-sm); background: var(--hb-surface-muted); padding: var(--hb-space-2); border-radius: var(--hb-radius); } .radar-card__reasons { font-size: var(--hb-text-xs); color: var(--hb-muted); padding-left: var(--hb-space-4); } .radar-band { display: inline-block; padding: 0.1rem 0.45rem; border-radius: 999px; font-size: var(--hb-text-xs); background: var(--hb-surface-muted); color: var(--hb-ink); } .radar-band--high { background: var(--hb-brand-soft); color: var(--hb-brand); } .radar-band--mid { background: var(--hb-warning-soft); color: var(--hb-warning); } .radar-btn-muted { opacity: 0.8; } .crm-board { display: grid; grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); gap: var(--hb-space-3); } .crm-col h2 { font-size: var(--hb-text-sm); font-weight: 600; color: var(--hb-ink); margin: 0 0 var(--hb-space-2); } .crm-card { width: 100%; text-align: left; cursor: pointer; } .crm-detail { margin-top: var(--hb-space-4); padding: var(--hb-space-3); border: 1px solid var(--hb-line); border-radius: var(--hb-radius); background: var(--hb-surface); } .radar-list { list-style: none; margin: 0; padding: 0; } /* ---------- 手動匯入(P1,spec §4.11) ---------- */ .hb-radar-import { padding: var(--hb-space-4); border: 1px solid var(--hb-line); border-radius: var(--hb-radius-lg); background: var(--hb-surface); } .hb-radar-import__csv { display: flex; flex-direction: column; gap: var(--hb-space-2); } .hb-radar-import__row { display: grid; grid-template-columns: minmax(11rem, 1.4fr) minmax(14rem, 2fr) minmax(8rem, 1fr) auto; align-items: end; gap: var(--hb-space-3); padding: var(--hb-space-3) 0; border-top: 1px solid var(--hb-line); } .hb-radar-import__row:first-of-type { border-top: none; } .hb-radar-import__results { display: flex; flex-direction: column; gap: var(--hb-space-2); list-style: none; margin: 0; padding: 0; } .hb-radar-import__result { display: flex; flex-wrap: wrap; align-items: center; gap: var(--hb-space-2); padding: var(--hb-space-2) var(--hb-space-3); border: 1px solid var(--hb-line); border-radius: var(--hb-radius); background: var(--hb-surface-muted); } .hb-radar-import__resultUrl { font-size: var(--hb-text-sm); color: var(--hb-ink-secondary); word-break: break-all; } /* ---------- 立即探索面板 ---------- */ .hb-radar-explore { padding: var(--hb-space-4); border: 1px solid var(--hb-line); border-radius: var(--hb-radius); background: var(--hb-surface); } .hb-radar-explore__suggest { display: flex; flex-direction: column; gap: var(--hb-space-2); } .hb-radar-explore__chips { display: flex; flex-wrap: wrap; gap: var(--hb-space-2); min-height: var(--hb-space-8); } .hb-radar-explore__chip { display: inline-flex; align-items: center; gap: var(--hb-space-1); border: none; background: transparent; cursor: pointer; padding: 0; color: inherit; font: inherit; } .hb-radar-explore__chip:disabled { opacity: 0.6; cursor: not-allowed; } .hb-radar-explore__chip-x { font-size: var(--hb-text-sm); color: var(--hb-muted); } .hb-radar-explore__add { display: grid; grid-template-columns: minmax(12rem, 1fr) auto; gap: var(--hb-space-3); align-items: end; } .hb-radar-explore__result { padding: var(--hb-space-3); border-radius: var(--hb-radius); background: var(--hb-surface-muted); border: 1px solid var(--hb-line); font-size: var(--hb-text-sm); color: var(--hb-ink); }