"2.0rem", "list_value" => "0.95rem", // [INDEX] "index_title" => "1.25rem", "index_subtitle" => "0.90rem", "index_device_list_title" => "0.95rem", "index_device_name" => "0.95rem", "index_ai_summary_title" => "0.95rem", "index_ai_summary_text" => "0.90rem", "index_sim_title" => "1.00rem", "index_sim_text" => "0.78rem", "kpi_label" => "0.82rem", "card_title" => "0.95rem", "card_value" => "2.10rem", "list_header" => "0.95rem", // [DEVICE] "device_title" => "1.20rem", "device_kpi_label" => "0.82rem", "ai_title" => "1.00rem", "ai_body" => "0.95rem", "device_list_header" => "0.95rem", "device_list_value" => "0.95rem", ]; $NS40_FONTS = $__NS40_FONTS_DEFAULT; // JSON 로드(확장 키 포함) if (is_file($__NS40_FONT_JSON)) { $raw = @file_get_contents($__NS40_FONT_JSON); $j = json_decode($raw, true); if (is_array($j)) { foreach ($j as $k=>$v) { if (is_string($k) && is_string($v) && trim($v)!=="") { // 알려진 키만 반영(오타 방지) if (array_key_exists($k, $NS40_FONTS)) { $NS40_FONTS[$k] = trim($v); } } } } } $__is_direct = (basename($_SERVER['SCRIPT_NAME'] ?? '') === basename(__FILE__)); if (!$__is_direct) return; // ⚠️ 다른 include 파일과 함께 로드될 때 전역 함수명 충돌(Fatal: Cannot redeclare ...) 방지 $h = function($s){ return htmlspecialchars((string)$s, ENT_QUOTES|ENT_SUBSTITUTE, "UTF-8"); }; // 공통: 폰트 입력 검증(단위 포함) $__re_font = '/^[0-9.]+(px|rem|em|%)$/'; function ns40_get_post_font($key, $default, $re){ $v = trim($_POST[$key] ?? ""); if($v === "") return $default; // 비우면 기본값으로 if(!preg_match($re, $v)) return null; // invalid return $v; } $msg=""; if ($_SERVER["REQUEST_METHOD"] === "POST") { $save = []; $invalid = []; foreach ($__NS40_FONTS_DEFAULT as $k=>$def) { $v = ns40_get_post_font($k, $def, $__re_font); if($v === null){ $invalid[] = $k; }else{ $save[$k] = $v; } } if(count($invalid) > 0){ $msg = "형식 오류: " . implode(", ", $invalid) . " (예: 1.2rem / 18px / 110%)"; } else { $ok = @file_put_contents($__NS40_FONT_JSON, json_encode($save, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT)); if ($ok !== false) { $msg = "저장 완료: " . basename($__NS40_FONT_JSON) . " (새로고침하면 즉시 반영됩니다)"; $NS40_FONTS = array_merge($NS40_FONTS, $save); } else { $msg = "저장 실패: 서버 권한(쓰기 권한)을 확인하세요. (" . $h($__NS40_FONT_JSON) . ")"; } } } ?>