[fix] negodata/front: 윈도우 모달 한글 깨짐 — 컨테이너 font-mono 제거 + 모노 스택 한글 폴백

모달 래퍼·폼에 걸린 font-mono 가 내부 한글까지 모노 스택으로 태웠다. JetBrains Mono·Consolas 에
한글 글리프가 없어 Windows 에서 굴림으로 떨어졌다(맥은 뒤쪽 폰트가 한글을 커버해 정상으로 보임).

- 한글이 들어가는 컨테이너 15곳에서 font-mono 제거 — 숫자 정렬이 필요한 칸은 유지
- --font-mono 스택 끝에 'Noto Sans KR' 추가, index.html 에 구글폰트 링크
  (self-host Pretendard 가 못 뜰 때의 안전망 — 정상 경로는 동일 도메인 Pretendard)
This commit is contained in:
Mina Choi 2026-08-10 09:49:26 +09:00
parent 436384fa36
commit 86d50c1291
17 changed files with 29 additions and 25 deletions

View File

@ -3,6 +3,10 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<!-- 구글폰트 Noto Sans KR — self-host Pretendard 가 어떤 환경에서든 못 뜰 때 한글이 굴림/맑은고딕으로 떨어지지 않게 하는 안전망 -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300..900&display=swap" rel="stylesheet" />
<title>NegoData</title> <title>NegoData</title>
</head> </head>
<body> <body>

View File

@ -68,7 +68,7 @@ export function ProfileSheet({ open, onClose }: { open: boolean; onClose: () =>
return ( return (
<Sheet open={open} title="내 정보 수정" onClose={onClose}> <Sheet open={open} title="내 정보 수정" onClose={onClose}>
<form onSubmit={handleSubmit(onValid)} className="mt-6 space-y-4 text-xs font-mono"> <form onSubmit={handleSubmit(onValid)} className="mt-6 space-y-4 text-xs">
{/* 읽기 전용: 회사 / 로그인ID / 권한 */} {/* 읽기 전용: 회사 / 로그인ID / 권한 */}
<div className="rounded-md border border-border bg-muted/40 p-3 space-y-1.5"> <div className="rounded-md border border-border bg-muted/40 p-3 space-y-1.5">
<div className="flex justify-between"> <div className="flex justify-between">

View File

@ -160,7 +160,7 @@ export function CardExcelUploadModal({ open, onConfirm, onClose }: CardExcelUplo
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40 backdrop-blur-xs"> <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40 backdrop-blur-xs">
<div className="w-full max-w-6xl bg-card border border-border rounded-lg shadow-2xl p-6 max-h-[90vh] overflow-y-auto animate-scale-up font-mono"> <div className="w-full max-w-6xl bg-card border border-border rounded-lg shadow-2xl p-6 max-h-[90vh] overflow-y-auto animate-scale-up">
{/* Modal Title */} {/* Modal Title */}
<div className="flex items-center justify-between pb-4 border-b border-border"> <div className="flex items-center justify-between pb-4 border-b border-border">

View File

@ -221,7 +221,7 @@ export function CardFormSheet({
return ( return (
<Sheet open={open} title={title} onClose={onClose}> <Sheet open={open} title={title} onClose={onClose}>
<form onSubmit={handleSubmit(onValid)} className="mt-6 space-y-4 text-xs font-mono"> <form onSubmit={handleSubmit(onValid)} className="mt-6 space-y-4 text-xs">
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3"> <div className="grid grid-cols-1 sm:grid-cols-3 gap-3">
{/* Card Type Selection */} {/* Card Type Selection */}
<div className="space-y-1"> <div className="space-y-1">

View File

@ -131,7 +131,7 @@ export function MemberFormSheet({
return ( return (
<Sheet open={open} title={mode === 'create' ? '신규 계정 생성' : '계정 정보 관리'} onClose={onClose}> <Sheet open={open} title={mode === 'create' ? '신규 계정 생성' : '계정 정보 관리'} onClose={onClose}>
<form onSubmit={handleSubmit(onValid)} className="mt-6 space-y-4 text-xs font-mono"> <form onSubmit={handleSubmit(onValid)} className="mt-6 space-y-4 text-xs">
{/* 로그인 ID */} {/* 로그인 ID */}
<div className="space-y-1"> <div className="space-y-1">
<Typography as="label" variant="label"> ID</Typography> <Typography as="label" variant="label"> ID</Typography>

View File

@ -225,7 +225,7 @@ export function ExcelUploadModal({ open, partners, onConfirm, onClose }: ExcelUp
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40 backdrop-blur-xs"> <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40 backdrop-blur-xs">
<div className="w-full max-w-5xl bg-card border border-border rounded-lg shadow-2xl p-6 max-h-[90vh] overflow-y-auto animate-scale-up font-mono"> <div className="w-full max-w-5xl bg-card border border-border rounded-lg shadow-2xl p-6 max-h-[90vh] overflow-y-auto animate-scale-up">
{/* Modal Title */} {/* Modal Title */}
<div className="flex items-center justify-between pb-4 border-b border-border"> <div className="flex items-center justify-between pb-4 border-b border-border">

View File

@ -128,7 +128,7 @@ export function PartnerFormSheet({
title={mode === 'create' ? '신규 협력사 등록' : '협력사 정보 관리'} title={mode === 'create' ? '신규 협력사 등록' : '협력사 정보 관리'}
onClose={onClose} onClose={onClose}
> >
<form onSubmit={handleSubmit(onValid)} className="mt-6 space-y-4 text-xs font-mono"> <form onSubmit={handleSubmit(onValid)} className="mt-6 space-y-4 text-xs">
{/* Partner Name */} {/* Partner Name */}
<div className="space-y-1"> <div className="space-y-1">
<Typography as="label" variant="label">{label('supplier.name')}</Typography> <Typography as="label" variant="label">{label('supplier.name')}</Typography>

View File

@ -442,7 +442,7 @@ export function ExcelUploadModal({ open, products, onConfirm, onClose }: ExcelUp
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40 backdrop-blur-xs"> <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40 backdrop-blur-xs">
<div className="w-full max-w-5xl bg-card border border-border rounded-lg shadow-2xl p-6 max-h-[90vh] overflow-y-auto animate-scale-up font-mono"> <div className="w-full max-w-5xl bg-card border border-border rounded-lg shadow-2xl p-6 max-h-[90vh] overflow-y-auto animate-scale-up">
{/* Modal Title */} {/* Modal Title */}
<div className="flex items-center justify-between pb-4 border-b border-border"> <div className="flex items-center justify-between pb-4 border-b border-border">
@ -511,7 +511,7 @@ export function ExcelUploadModal({ open, products, onConfirm, onClose }: ExcelUp
<CheckCircle2 className="text-emerald-500" size={16} /> <CheckCircle2 className="text-emerald-500" size={16} />
<span>{excelFile}</span> <span>{excelFile}</span>
</div> </div>
<span className="text-[10px] text-muted-foreground font-mono">{validated.length} </span> <span className="text-[10px] text-muted-foreground">{validated.length} </span>
</div> </div>
{/* Previews table and validation */} {/* Previews table and validation */}
@ -519,7 +519,7 @@ export function ExcelUploadModal({ open, products, onConfirm, onClose }: ExcelUp
<span className="text-xs font-bold text-foreground block"> </span> <span className="text-xs font-bold text-foreground block"> </span>
<div className="border border-border rounded overflow-auto max-h-72"> <div className="border border-border rounded overflow-auto max-h-72">
<Table className="text-left font-mono text-[11px] border-collapse bg-background min-w-max"> <Table className="text-left text-[11px] border-collapse bg-background min-w-max">
<TableHeader className="bg-muted text-muted-foreground text-[10px] border-b border-border"> <TableHeader className="bg-muted text-muted-foreground text-[10px] border-b border-border">
<TableRow> <TableRow>
<TableHead className="p-2 font-semibold whitespace-nowrap"></TableHead> <TableHead className="p-2 font-semibold whitespace-nowrap"></TableHead>
@ -559,7 +559,7 @@ export function ExcelUploadModal({ open, products, onConfirm, onClose }: ExcelUp
{row.status} {row.status}
</span> </span>
</TableCell> </TableCell>
<TableCell className={`p-2 font-mono text-[10px] whitespace-nowrap ${row.status === '오류' ? 'text-rose-500' : 'text-emerald-600'}`}> <TableCell className={`p-2 text-[10px] whitespace-nowrap ${row.status === '오류' ? 'text-rose-500' : 'text-emerald-600'}`}>
{row.message} {row.message}
</TableCell> </TableCell>
{columns.map((c) => { {columns.map((c) => {
@ -569,7 +569,7 @@ export function ExcelUploadModal({ open, products, onConfirm, onClose }: ExcelUp
<Input <Input
type={c.numeric && !c.customKey ? 'number' : 'text'} type={c.numeric && !c.customKey ? 'number' : 'text'}
placeholder={c.header} placeholder={c.header}
className={`bg-muted/20 hover:bg-muted/50 ${c.numeric ? 'w-24 text-right font-mono' : 'min-w-[110px] font-mono'}`} className={`bg-muted/20 hover:bg-muted/50 ${c.numeric ? 'w-24 text-right font-mono' : 'min-w-[110px]'}`}
value={String(value ?? '')} value={String(value ?? '')}
onChange={(e) => handleUpdateField(row.id, c, e.target.value)} onChange={(e) => handleUpdateField(row.id, c, e.target.value)}
/> />
@ -588,7 +588,7 @@ export function ExcelUploadModal({ open, products, onConfirm, onClose }: ExcelUp
{/* Excel footer */} {/* Excel footer */}
<div className="flex items-center justify-between pt-4 border-t border-border mt-6 text-xs bg-muted/40 p-3 rounded"> <div className="flex items-center justify-between pt-4 border-t border-border mt-6 text-xs bg-muted/40 p-3 rounded">
<span className="font-mono text-muted-foreground"> <span className="text-muted-foreground">
: {validCount} // 오류 행 수치: {errorCount}개 : {validCount} // 오류 행 수치: {errorCount}개
</span> </span>
<div className="flex gap-2"> <div className="flex gap-2">

View File

@ -113,7 +113,7 @@ export function ImageBulkUploadModal({
if (!open) return null; if (!open) return null;
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40 backdrop-blur-xs"> <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40 backdrop-blur-xs">
<div className="w-full max-w-3xl bg-card border border-border rounded-lg shadow-2xl p-6 max-h-[90vh] overflow-y-auto animate-scale-up font-mono"> <div className="w-full max-w-3xl bg-card border border-border rounded-lg shadow-2xl p-6 max-h-[90vh] overflow-y-auto animate-scale-up">
{/* 헤더 */} {/* 헤더 */}
<div className="flex items-center justify-between pb-3 border-b border-border"> <div className="flex items-center justify-between pb-3 border-b border-border">
<Typography variant="h3"> </Typography> <Typography variant="h3"> </Typography>

View File

@ -241,7 +241,7 @@ export function ProductFormSheet({
title={mode === 'create' ? '신규 상품 등록' : '상품 정보 수정'} title={mode === 'create' ? '신규 상품 등록' : '상품 정보 수정'}
onClose={onClose} onClose={onClose}
> >
<form onSubmit={handleSubmit(onValid)} className="mt-6 space-y-4 text-xs font-mono"> <form onSubmit={handleSubmit(onValid)} className="mt-6 space-y-4 text-xs">
{/* Product Name */} {/* Product Name */}
<div className="space-y-1"> <div className="space-y-1">
<Typography as="label" variant="label">{label('item.name')}</Typography> <Typography as="label" variant="label">{label('item.name')}</Typography>

View File

@ -290,12 +290,12 @@ export function QuotationCreateModal({
<div className="fixed inset-0 z-[60] flex items-center justify-center"> <div className="fixed inset-0 z-[60] flex items-center justify-center">
<div className="flex flex-col items-center gap-3 rounded-xl bg-card px-8 py-6 shadow-2xl border border-border"> <div className="flex flex-col items-center gap-3 rounded-xl bg-card px-8 py-6 shadow-2xl border border-border">
<Loader2 className="text-primary animate-spin" size={44} strokeWidth={2.5} /> <Loader2 className="text-primary animate-spin" size={44} strokeWidth={2.5} />
<Typography variant="small" className="font-semibold font-mono"> </Typography> <Typography variant="small" className="font-semibold"> </Typography>
<Typography variant="small" className="text-muted-foreground font-mono"> · </Typography> <Typography variant="small" className="text-muted-foreground"> · </Typography>
</div> </div>
</div> </div>
)} )}
<div className="w-full max-w-2xl bg-card border border-border rounded-lg shadow-2xl p-6 flex flex-col max-h-[90vh] overflow-hidden animate-scale-up font-mono"> <div className="w-full max-w-2xl bg-card border border-border rounded-lg shadow-2xl p-6 flex flex-col max-h-[90vh] overflow-hidden animate-scale-up">
{/* Header */} {/* Header */}
<div className="shrink-0 flex items-center justify-between pb-4 border-b border-border"> <div className="shrink-0 flex items-center justify-between pb-4 border-b border-border">
@ -429,7 +429,7 @@ export function QuotationCreateModal({
{step === 3 && ( {step === 3 && (
<div className="space-y-4"> <div className="space-y-4">
<div className="space-y-1 font-mono text-xs"> <div className="space-y-1 text-xs">
<Typography as="label" variant="label"> </Typography> <Typography as="label" variant="label"> </Typography>
<Select value={settingId} onValueChange={(v) => setSettingId(v ?? '')}> <Select value={settingId} onValueChange={(v) => setSettingId(v ?? '')}>
<SelectTrigger id="wizard-setting-select" className="w-full"> <SelectTrigger id="wizard-setting-select" className="w-full">

View File

@ -92,7 +92,7 @@ export function DrawerHeaderCards({
: []; : [];
return ( return (
<div className="mt-4 space-y-4 text-xs font-mono"> <div className="mt-4 space-y-4 text-xs">
{/* 결과 요약: 목표가 대비 낙찰/절감 */} {/* 결과 요약: 목표가 대비 낙찰/절감 */}
<ResultSummaryBand quotation={quotation} sessionViews={sessionViews} /> <ResultSummaryBand quotation={quotation} sessionViews={sessionViews} />

View File

@ -166,7 +166,7 @@ export function RegenerateModal({
return ( return (
<div className="fixed inset-0 z-[55] flex items-center justify-center p-4 bg-black/40 backdrop-blur-xs"> <div className="fixed inset-0 z-[55] flex items-center justify-center p-4 bg-black/40 backdrop-blur-xs">
<div className="w-full max-w-3xl bg-card border border-border rounded-lg shadow-2xl p-6 max-h-[90vh] overflow-y-auto animate-scale-up font-mono"> <div className="w-full max-w-3xl bg-card border border-border rounded-lg shadow-2xl p-6 max-h-[90vh] overflow-y-auto animate-scale-up">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between pb-4 border-b border-border"> <div className="flex items-center justify-between pb-4 border-b border-border">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">

View File

@ -52,7 +52,7 @@ export function TargetPriceModal({
onClick={onClose} onClick={onClose}
> >
<div <div
className="w-full max-w-md bg-card border border-border rounded-lg shadow-2xl p-6 max-h-[90vh] overflow-y-auto font-mono text-xs animate-scale-up" className="w-full max-w-md bg-card border border-border rounded-lg shadow-2xl p-6 max-h-[90vh] overflow-y-auto text-xs animate-scale-up"
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
> >
{/* 헤더 */} {/* 헤더 */}

View File

@ -45,7 +45,7 @@ export function QuotationSettingsModal({
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40 backdrop-blur-xs"> <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/40 backdrop-blur-xs">
<div className="w-full max-w-2xl bg-card border border-border rounded-lg shadow-2xl p-6 max-h-[90vh] overflow-y-auto animate-scale-up font-mono text-xs"> <div className="w-full max-w-2xl bg-card border border-border rounded-lg shadow-2xl p-6 max-h-[90vh] overflow-y-auto animate-scale-up text-xs">
<div className="flex items-center justify-between pb-4 border-b border-border mb-4"> <div className="flex items-center justify-between pb-4 border-b border-border mb-4">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">

View File

@ -159,7 +159,7 @@ export function SettingsView({ tabs = SETTINGS_TABS }: { tabs?: readonly Setting
setDraft((d) => ({ ...d, labels: { ...d.labels, [key]: value } })); setDraft((d) => ({ ...d, labels: { ...d.labels, [key]: value } }));
return ( return (
<div className="space-y-4 font-mono text-xs"> <div className="space-y-4 text-xs">
<Tabs value={tab} onValueChange={setTab}> <Tabs value={tab} onValueChange={setTab}>
<div className="flex items-center justify-between gap-3 flex-wrap"> <div className="flex items-center justify-between gap-3 flex-wrap">
<TabsList> <TabsList>

View File

@ -37,7 +37,7 @@
--font-sans: "Inter", ui-sans-serif, system-ui, sans-serif; --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
/* 모노 폰트엔 한글 글리프가 없다 — Pretendard 를 넣어야 한글이 OS 기본(Windows 굴림)으로 떨어지지 않는다 */ /* 모노 폰트엔 한글 글리프가 없다 — Pretendard 를 넣어야 한글이 OS 기본(Windows 굴림)으로 떨어지지 않는다 */
--font-mono: "JetBrains Mono", Consolas, "Segoe UI Mono", ui-monospace, SFMono-Regular, "Menlo", "Pretendard Variable", monospace; --font-mono: "JetBrains Mono", Consolas, "Segoe UI Mono", ui-monospace, SFMono-Regular, "Menlo", "Pretendard Variable", "Noto Sans KR", monospace;
} }
:root { :root {
@ -125,7 +125,7 @@
@theme inline { @theme inline {
--font-heading: var(--font-sans); --font-heading: var(--font-sans);
--font-sans: 'Pretendard Variable', 'Geist Variable', system-ui, sans-serif; --font-sans: 'Pretendard Variable', 'Geist Variable', 'Noto Sans KR', system-ui, sans-serif;
--color-sidebar-ring: var(--sidebar-ring); --color-sidebar-ring: var(--sidebar-ring);
--color-sidebar-border: var(--sidebar-border); --color-sidebar-border: var(--sidebar-border);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);