refactor(sf-19): BestLayouts inline hex → Tailwind tokens #296
1 changed files with 130 additions and 77 deletions
|
|
@ -14,13 +14,10 @@ import type {
|
|||
|
||||
// ── Constants ─────────────────────────────────────────────────────────────────
|
||||
|
||||
const CONFIDENCE_STYLES: Record<
|
||||
Confidence,
|
||||
{ bg: string; fg: string; label: string }
|
||||
> = {
|
||||
high: { bg: "#dcfce7", fg: "#166534", label: "Высокое" },
|
||||
medium: { bg: "#fef3c7", fg: "#854d0e", label: "Среднее" },
|
||||
low: { bg: "#fee2e2", fg: "#991b1b", label: "Низкое" },
|
||||
const CONFIDENCE_STYLES: Record<Confidence, { cls: string; label: string }> = {
|
||||
high: { cls: "bg-emerald-100 text-emerald-800", label: "Высокое" },
|
||||
medium: { cls: "bg-amber-100 text-amber-800", label: "Среднее" },
|
||||
low: { cls: "bg-rose-100 text-rose-800", label: "Низкое" },
|
||||
};
|
||||
|
||||
const TIME_WINDOW_LABELS: Record<TimeWindow, string> = {
|
||||
|
|
@ -40,17 +37,16 @@ const ROOM_BUCKET_LABELS: Record<string, string> = {
|
|||
// ── Sub-components ────────────────────────────────────────────────────────────
|
||||
|
||||
function DataQualityCard({ dq }: { dq: BestLayoutsResponse["data_quality"] }) {
|
||||
const style = CONFIDENCE_STYLES[dq.confidence];
|
||||
const conf = CONFIDENCE_STYLES[dq.confidence];
|
||||
return (
|
||||
<div className="border border-gray-200 rounded-xl px-[18px] py-[14px] bg-white flex items-center gap-4 flex-wrap">
|
||||
<span className="font-semibold text-[13px] text-gray-700 mr-1">
|
||||
Качество данных:
|
||||
</span>
|
||||
<span
|
||||
style={{ background: style.bg, color: style.fg }}
|
||||
className="px-[10px] py-[2px] rounded-md text-xs font-semibold"
|
||||
className={`px-[10px] py-[2px] rounded-md text-xs font-semibold ${conf.cls}`}
|
||||
>
|
||||
{style.label}
|
||||
{conf.label}
|
||||
</span>
|
||||
<span className="text-xs text-gray-500">
|
||||
Покрытие {dq.velocity_coverage_pct.toFixed(0)}% (
|
||||
|
|
@ -68,7 +64,7 @@ function salesPeriodMonths(supply: number, velocity: number): number | null {
|
|||
}
|
||||
|
||||
function SalesPeriodCell({ months }: { months: number | null }) {
|
||||
if (months === null) return <span style={{ color: "#9ca3af" }}>—</span>;
|
||||
if (months === null) return <span className="text-gray-400">—</span>;
|
||||
if (months < 12)
|
||||
return (
|
||||
<span className="text-emerald-600 font-semibold tabular-nums">
|
||||
|
|
@ -92,7 +88,7 @@ function CompetitorDrillIn({
|
|||
const hidden = ids.length - COMPETITOR_PREVIEW_LIMIT;
|
||||
|
||||
return (
|
||||
<tr style={{ background: "#f0f4ff" }}>
|
||||
<tr className="bg-blue-50">
|
||||
<td colSpan={colSpan} style={{ padding: "8px 16px" }}>
|
||||
<div
|
||||
style={{
|
||||
|
|
@ -103,7 +99,10 @@ function CompetitorDrillIn({
|
|||
fontSize: 11,
|
||||
}}
|
||||
>
|
||||
<span style={{ color: "#6b7280", fontWeight: 600, marginRight: 4 }}>
|
||||
<span
|
||||
className="text-gray-500 font-semibold"
|
||||
style={{ marginRight: 4 }}
|
||||
>
|
||||
ЖК-источники:
|
||||
</span>
|
||||
{visible.map((id) => (
|
||||
|
|
@ -186,7 +185,7 @@ function TopLayoutsTable({ rows }: { rows: TopLayoutRow[] }) {
|
|||
style={{ width: "100%", borderCollapse: "collapse", fontSize: 12 }}
|
||||
>
|
||||
<thead>
|
||||
<tr style={{ background: "#f6f7f9" }}>
|
||||
<tr className="bg-gray-50">
|
||||
{headers.map((h, idx) => (
|
||||
<th
|
||||
key={idx}
|
||||
|
|
@ -225,8 +224,11 @@ function TopLayoutsTable({ rows }: { rows: TopLayoutRow[] }) {
|
|||
role={hasCompetitors ? "button" : undefined}
|
||||
aria-expanded={hasCompetitors ? isExpanded : undefined}
|
||||
style={{
|
||||
background: i % 2 === 0 ? "#fff" : "#fafbfc",
|
||||
borderBottom: isExpanded ? "none" : "1px solid #f3f4f6",
|
||||
background:
|
||||
i % 2 === 0 ? "var(--bg-card)" : "var(--bg-card-alt)",
|
||||
borderBottom: isExpanded
|
||||
? "none"
|
||||
: "1px solid var(--border-soft)",
|
||||
cursor: hasCompetitors ? "pointer" : "default",
|
||||
}}
|
||||
title={
|
||||
|
|
@ -239,7 +241,7 @@ function TopLayoutsTable({ rows }: { rows: TopLayoutRow[] }) {
|
|||
style={{
|
||||
padding: "7px 12px",
|
||||
fontWeight: 700,
|
||||
color: "#1d4ed8",
|
||||
color: "var(--accent)",
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
}}
|
||||
>
|
||||
|
|
@ -249,18 +251,23 @@ function TopLayoutsTable({ rows }: { rows: TopLayoutRow[] }) {
|
|||
style={{
|
||||
padding: "7px 12px",
|
||||
fontWeight: 500,
|
||||
color: "#111827",
|
||||
color: "var(--fg-primary)",
|
||||
}}
|
||||
>
|
||||
{ROOM_BUCKET_LABELS[row.room_bucket] ?? row.room_bucket}
|
||||
</td>
|
||||
<td style={{ padding: "7px 12px", color: "#374151" }}>
|
||||
<td
|
||||
style={{
|
||||
padding: "7px 12px",
|
||||
color: "var(--fg-secondary)",
|
||||
}}
|
||||
>
|
||||
{row.area_bin} м²
|
||||
</td>
|
||||
<td
|
||||
style={{
|
||||
padding: "7px 12px",
|
||||
color: "#374151",
|
||||
color: "var(--fg-secondary)",
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
}}
|
||||
>
|
||||
|
|
@ -270,7 +277,7 @@ function TopLayoutsTable({ rows }: { rows: TopLayoutRow[] }) {
|
|||
style={{
|
||||
padding: "7px 12px",
|
||||
textAlign: "right",
|
||||
color: "#374151",
|
||||
color: "var(--fg-secondary)",
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
}}
|
||||
>
|
||||
|
|
@ -280,7 +287,7 @@ function TopLayoutsTable({ rows }: { rows: TopLayoutRow[] }) {
|
|||
style={{
|
||||
padding: "7px 12px",
|
||||
textAlign: "right",
|
||||
color: "#374151",
|
||||
color: "var(--fg-secondary)",
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
}}
|
||||
>
|
||||
|
|
@ -302,7 +309,7 @@ function TopLayoutsTable({ rows }: { rows: TopLayoutRow[] }) {
|
|||
style={{
|
||||
padding: "7px 12px",
|
||||
textAlign: "right",
|
||||
color: "#374151",
|
||||
color: "var(--fg-secondary)",
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
}}
|
||||
>
|
||||
|
|
@ -339,7 +346,7 @@ function TopLayoutsTable({ rows }: { rows: TopLayoutRow[] }) {
|
|||
<td
|
||||
style={{
|
||||
padding: "7px 10px",
|
||||
color: "#9ca3af",
|
||||
color: "var(--fg-tertiary)",
|
||||
width: 24,
|
||||
}}
|
||||
>
|
||||
|
|
@ -379,12 +386,12 @@ function TopLayoutsTable({ rows }: { rows: TopLayoutRow[] }) {
|
|||
|
||||
function UnitMixBar({ mix }: { mix: LayoutTzMixRow[] }) {
|
||||
const COLORS = [
|
||||
"#1d4ed8",
|
||||
"#7c3aed",
|
||||
"#059669",
|
||||
"#d97706",
|
||||
"#dc2626",
|
||||
"#0891b2",
|
||||
"var(--viz-1)",
|
||||
"var(--viz-5)",
|
||||
"var(--viz-3)",
|
||||
"var(--viz-4)",
|
||||
"var(--viz-2)",
|
||||
"var(--viz-3)",
|
||||
];
|
||||
|
||||
return (
|
||||
|
|
@ -396,7 +403,7 @@ function UnitMixBar({ mix }: { mix: LayoutTzMixRow[] }) {
|
|||
height: 24,
|
||||
borderRadius: 6,
|
||||
overflow: "hidden",
|
||||
border: "1px solid #e5e7eb",
|
||||
border: "1px solid var(--border-card)",
|
||||
marginBottom: 10,
|
||||
}}
|
||||
>
|
||||
|
|
@ -428,7 +435,7 @@ function UnitMixBar({ mix }: { mix: LayoutTzMixRow[] }) {
|
|||
flexShrink: 0,
|
||||
}}
|
||||
/>
|
||||
<span style={{ fontSize: 11, color: "#374151" }}>
|
||||
<span style={{ fontSize: 11, color: "var(--fg-secondary)" }}>
|
||||
{ROOM_BUCKET_LABELS[row.room_bucket] ?? row.room_bucket} {row.pct}
|
||||
%
|
||||
</span>
|
||||
|
|
@ -443,7 +450,7 @@ function MixTable({ mix }: { mix: LayoutTzMixRow[] }) {
|
|||
return (
|
||||
<table style={{ width: "100%", borderCollapse: "collapse", fontSize: 12 }}>
|
||||
<thead>
|
||||
<tr style={{ background: "#f6f7f9" }}>
|
||||
<tr className="bg-gray-50">
|
||||
{["Тип", "Доля, %", "Кол-во квартир", "Ср. площадь, м²"].map((h) => (
|
||||
<th
|
||||
key={h}
|
||||
|
|
@ -459,12 +466,16 @@ function MixTable({ mix }: { mix: LayoutTzMixRow[] }) {
|
|||
<tr
|
||||
key={row.room_bucket}
|
||||
style={{
|
||||
background: i % 2 === 0 ? "#fff" : "#fafbfc",
|
||||
borderBottom: "1px solid #f3f4f6",
|
||||
background: i % 2 === 0 ? "var(--bg-card)" : "var(--bg-card-alt)",
|
||||
borderBottom: "1px solid var(--border-soft)",
|
||||
}}
|
||||
>
|
||||
<td
|
||||
style={{ padding: "7px 12px", fontWeight: 500, color: "#111827" }}
|
||||
style={{
|
||||
padding: "7px 12px",
|
||||
fontWeight: 500,
|
||||
color: "var(--fg-primary)",
|
||||
}}
|
||||
>
|
||||
{ROOM_BUCKET_LABELS[row.room_bucket] ?? row.room_bucket}
|
||||
</td>
|
||||
|
|
@ -472,7 +483,7 @@ function MixTable({ mix }: { mix: LayoutTzMixRow[] }) {
|
|||
style={{
|
||||
padding: "7px 12px",
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
color: "#374151",
|
||||
color: "var(--fg-secondary)",
|
||||
}}
|
||||
>
|
||||
{row.pct}%
|
||||
|
|
@ -481,7 +492,7 @@ function MixTable({ mix }: { mix: LayoutTzMixRow[] }) {
|
|||
style={{
|
||||
padding: "7px 12px",
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
color: "#374151",
|
||||
color: "var(--fg-secondary)",
|
||||
}}
|
||||
>
|
||||
{row.abs_units != null
|
||||
|
|
@ -492,7 +503,7 @@ function MixTable({ mix }: { mix: LayoutTzMixRow[] }) {
|
|||
style={{
|
||||
padding: "7px 12px",
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
color: "#374151",
|
||||
color: "var(--fg-secondary)",
|
||||
}}
|
||||
>
|
||||
{row.avg_target_area_m2 != null
|
||||
|
|
@ -517,9 +528,9 @@ function RecommendationCard({
|
|||
return (
|
||||
<div
|
||||
style={{
|
||||
border: "1px solid #e5e7eb",
|
||||
border: "1px solid var(--border-card)",
|
||||
borderRadius: 10,
|
||||
background: "#fff",
|
||||
background: "var(--bg-card)",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
|
|
@ -545,7 +556,12 @@ function RecommendationCard({
|
|||
|
||||
{/* Rationale text — plain text only, no dangerouslySetInnerHTML */}
|
||||
<p
|
||||
style={{ fontSize: 13, color: "#374151", margin: 0, lineHeight: 1.6 }}
|
||||
style={{
|
||||
fontSize: 13,
|
||||
color: "var(--fg-secondary)",
|
||||
margin: 0,
|
||||
lineHeight: 1.6,
|
||||
}}
|
||||
>
|
||||
{rec.rationale_text}
|
||||
</p>
|
||||
|
|
@ -557,7 +573,7 @@ function RecommendationCard({
|
|||
style={{
|
||||
fontSize: 12,
|
||||
fontWeight: 600,
|
||||
color: "#6b7280",
|
||||
color: "var(--fg-tertiary)",
|
||||
marginBottom: 8,
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: "0.04em",
|
||||
|
|
@ -573,7 +589,7 @@ function RecommendationCard({
|
|||
{rec.mix.length > 0 && (
|
||||
<div
|
||||
style={{
|
||||
border: "1px solid #e5e7eb",
|
||||
border: "1px solid var(--border-card)",
|
||||
borderRadius: 8,
|
||||
overflow: "hidden",
|
||||
}}
|
||||
|
|
@ -590,16 +606,18 @@ function RecommendationCard({
|
|||
alignItems: "center",
|
||||
gap: 8,
|
||||
padding: "10px 14px",
|
||||
background: "#eff6ff",
|
||||
background: "var(--accent-soft)",
|
||||
borderRadius: 8,
|
||||
fontSize: 13,
|
||||
}}
|
||||
>
|
||||
<span style={{ color: "#6b7280" }}>Средневзвешенная цена:</span>
|
||||
<span style={{ color: "var(--fg-tertiary)" }}>
|
||||
Средневзвешенная цена:
|
||||
</span>
|
||||
<span
|
||||
style={{
|
||||
fontWeight: 700,
|
||||
color: "#1d4ed8",
|
||||
color: "var(--accent)",
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
}}
|
||||
>
|
||||
|
|
@ -612,7 +630,7 @@ function RecommendationCard({
|
|||
)}
|
||||
|
||||
{/* Meta */}
|
||||
<div style={{ fontSize: 11, color: "#9ca3af" }}>
|
||||
<div style={{ fontSize: 11, color: "var(--fg-tertiary)" }}>
|
||||
Основано на {rec.based_on_obj_count} ЖК ·{" "}
|
||||
{rec.based_on_total_deals.toLocaleString("ru-RU")} сделках · период{" "}
|
||||
{new Date(rec.data_window_start).toLocaleDateString("ru-RU")} —{" "}
|
||||
|
|
@ -695,9 +713,9 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
return (
|
||||
<div
|
||||
style={{
|
||||
border: "1px solid #e5e7eb",
|
||||
border: "1px solid var(--border-card)",
|
||||
borderRadius: 12,
|
||||
background: "#fff",
|
||||
background: "var(--bg-card)",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
|
|
@ -705,8 +723,8 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
<div
|
||||
style={{
|
||||
padding: "14px 20px",
|
||||
background: "#f9fafb",
|
||||
borderBottom: "1px solid #e5e7eb",
|
||||
background: "var(--bg-app)",
|
||||
borderBottom: "1px solid var(--border-card)",
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
|
|
@ -715,10 +733,18 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
}}
|
||||
>
|
||||
<div>
|
||||
<span style={{ fontWeight: 600, fontSize: 14, color: "#111827" }}>
|
||||
<span
|
||||
style={{
|
||||
fontWeight: 600,
|
||||
fontSize: 14,
|
||||
color: "var(--fg-primary)",
|
||||
}}
|
||||
>
|
||||
Анализ планировок
|
||||
</span>
|
||||
<span style={{ fontSize: 12, color: "#6b7280", marginLeft: 8 }}>
|
||||
<span
|
||||
style={{ fontSize: 12, color: "var(--fg-tertiary)", marginLeft: 8 }}
|
||||
>
|
||||
data-driven ТЗ на проектирование
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -732,8 +758,10 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
disabled={isPdfLoading}
|
||||
style={{
|
||||
padding: "7px 16px",
|
||||
background: isPdfLoading ? "#9ca3af" : "#1d4ed8",
|
||||
color: "#fff",
|
||||
background: isPdfLoading
|
||||
? "var(--fg-tertiary)"
|
||||
: "var(--accent)",
|
||||
color: "var(--fg-on-dark)",
|
||||
border: "none",
|
||||
borderRadius: 7,
|
||||
fontSize: 13,
|
||||
|
|
@ -755,7 +783,7 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
<div
|
||||
style={{
|
||||
padding: "16px 20px",
|
||||
borderBottom: "1px solid #f3f4f6",
|
||||
borderBottom: "1px solid var(--border-soft)",
|
||||
display: "flex",
|
||||
flexWrap: "wrap",
|
||||
gap: 20,
|
||||
|
|
@ -771,7 +799,13 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
minWidth: 160,
|
||||
}}
|
||||
>
|
||||
<label style={{ fontSize: 12, color: "#6b7280", fontWeight: 500 }}>
|
||||
<label
|
||||
style={{
|
||||
fontSize: 12,
|
||||
color: "var(--fg-tertiary)",
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
Радиус поиска: {radiusKm.toFixed(1)} км
|
||||
</label>
|
||||
<input
|
||||
|
|
@ -781,7 +815,7 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
step={0.1}
|
||||
value={radiusKm}
|
||||
onChange={(e) => setRadiusKm(parseFloat(e.target.value))}
|
||||
style={{ width: 160, accentColor: "#1d4ed8" }}
|
||||
style={{ width: 160, accentColor: "var(--accent)" }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -794,7 +828,13 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
minWidth: 160,
|
||||
}}
|
||||
>
|
||||
<label style={{ fontSize: 12, color: "#6b7280", fontWeight: 500 }}>
|
||||
<label
|
||||
style={{
|
||||
fontSize: 12,
|
||||
color: "var(--fg-tertiary)",
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
Мин. скорость: {minVelocity.toFixed(1)} кв/мес
|
||||
</label>
|
||||
<input
|
||||
|
|
@ -804,13 +844,19 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
step={0.1}
|
||||
value={minVelocity}
|
||||
onChange={(e) => setMinVelocity(parseFloat(e.target.value))}
|
||||
style={{ width: 160, accentColor: "#1d4ed8" }}
|
||||
style={{ width: 160, accentColor: "var(--accent)" }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Time window radio */}
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
|
||||
<span style={{ fontSize: 12, color: "#6b7280", fontWeight: 500 }}>
|
||||
<span
|
||||
style={{
|
||||
fontSize: 12,
|
||||
color: "var(--fg-tertiary)",
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
Период анализа
|
||||
</span>
|
||||
<div style={{ display: "flex", gap: 10, flexWrap: "wrap" }}>
|
||||
|
|
@ -823,7 +869,8 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
gap: 4,
|
||||
fontSize: 12,
|
||||
cursor: "pointer",
|
||||
color: timeWindow === tw ? "#1d4ed8" : "#374151",
|
||||
color:
|
||||
timeWindow === tw ? "var(--accent)" : "var(--fg-secondary)",
|
||||
fontWeight: timeWindow === tw ? 600 : 400,
|
||||
}}
|
||||
>
|
||||
|
|
@ -833,7 +880,7 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
value={tw}
|
||||
checked={timeWindow === tw}
|
||||
onChange={() => setTimeWindow(tw)}
|
||||
style={{ accentColor: "#1d4ed8" }}
|
||||
style={{ accentColor: "var(--accent)" }}
|
||||
/>
|
||||
{TIME_WINDOW_LABELS[tw]}
|
||||
</label>
|
||||
|
|
@ -843,7 +890,13 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
|
||||
{/* Target flats input */}
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
|
||||
<label style={{ fontSize: 12, color: "#6b7280", fontWeight: 500 }}>
|
||||
<label
|
||||
style={{
|
||||
fontSize: 12,
|
||||
color: "var(--fg-tertiary)",
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
Целевой объём (квартир)
|
||||
</label>
|
||||
<input
|
||||
|
|
@ -855,11 +908,11 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
placeholder="300"
|
||||
style={{
|
||||
padding: "5px 10px",
|
||||
border: "1px solid #d1d5db",
|
||||
border: "1px solid var(--border-strong)",
|
||||
borderRadius: 6,
|
||||
fontSize: 13,
|
||||
width: 110,
|
||||
color: "#111827",
|
||||
color: "var(--fg-primary)",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -870,8 +923,8 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
disabled={isPending}
|
||||
style={{
|
||||
padding: "7px 20px",
|
||||
background: isPending ? "#9ca3af" : "#1d4ed8",
|
||||
color: "#fff",
|
||||
background: isPending ? "var(--fg-tertiary)" : "var(--accent)",
|
||||
color: "var(--fg-on-dark)",
|
||||
border: "none",
|
||||
borderRadius: 7,
|
||||
fontSize: 13,
|
||||
|
|
@ -888,8 +941,8 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
<span
|
||||
style={{
|
||||
fontSize: 11,
|
||||
color: "#1d4ed8",
|
||||
background: "#eff6ff",
|
||||
color: "var(--accent)",
|
||||
background: "var(--accent-soft)",
|
||||
padding: "3px 8px",
|
||||
borderRadius: 4,
|
||||
alignSelf: "flex-end",
|
||||
|
|
@ -912,7 +965,7 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
style={{
|
||||
height: 18,
|
||||
borderRadius: 6,
|
||||
background: "#f3f4f6",
|
||||
background: "var(--bg-card-alt)",
|
||||
width: `${w}%`,
|
||||
animation: "pulse 1.5s ease-in-out infinite",
|
||||
}}
|
||||
|
|
@ -926,10 +979,10 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
<div
|
||||
style={{
|
||||
padding: "12px 16px",
|
||||
background: "#fef2f2",
|
||||
border: "1px solid #fca5a5",
|
||||
background: "var(--danger-soft)",
|
||||
border: "1px solid var(--danger-soft)",
|
||||
borderRadius: 8,
|
||||
color: "#dc2626",
|
||||
color: "var(--danger)",
|
||||
fontSize: 13,
|
||||
}}
|
||||
>
|
||||
|
|
@ -952,7 +1005,7 @@ export function BestLayoutsBlock({ cadNum, selectedCompetitorObjIds }: Props) {
|
|||
style={{
|
||||
padding: "24px 0",
|
||||
textAlign: "center",
|
||||
color: "#d1d5db",
|
||||
color: "var(--fg-tertiary)",
|
||||
fontSize: 13,
|
||||
}}
|
||||
>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue