{"id":63,"date":"2026-05-15T12:04:29","date_gmt":"2026-05-15T12:04:29","guid":{"rendered":"http:\/\/nordbalance.dk\/?page_id=63"},"modified":"2026-06-04T16:39:22","modified_gmt":"2026-06-04T16:39:22","slug":"mit-budget","status":"publish","type":"page","link":"https:\/\/nordbalance.dk\/?page_id=63","title":{"rendered":"Mit Budget"},"content":{"rendered":"\n<div class=\"wp-block-group has-global-padding is-layout-constrained wp-block-group-is-layout-constrained\">\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-794e3cfa wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:100%\">\n<meta charset=\"UTF-8\">\n<title>Mit Budget NordBalance<\/title>\n<!-- NORDBALANCE BUDGET VERSION: budgets-only-2026-06-03 -->\n<meta name=\"description\" content=\"F\u00e5 fuldt overblik over din \u00f8konomi med Mit Budget NordBalance.\">\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Inter:wght@400;600;700;800;900&amp;display=swap\" rel=\"stylesheet\">\n\n<style>\nhtml,body{width:100%;max-width:100%;overflow-x:hidden}\nbody{font-family:Inter,Arial,sans-serif;background:#f4f7fb;margin:0;color:#0f172a}\n.entry-content,.wp-block-post-content,.wp-site-blocks,.is-layout-constrained,.is-layout-constrained > *,.wp-block-group,.wp-block-html,.wp-block-html > div,.wp-block-post-content > div{max-width:100% !important;width:100% !important;margin-left:0 !important;margin-right:0 !important;box-sizing:border-box}\n.nb-wrap{width:100% !important;max-width:1600px !important;margin:0 auto !important;padding:24px clamp(14px,3vw,42px);box-sizing:border-box}\n.nb-nav{width:100%;background:white;border:1px solid #e5eaf2;border-radius:22px;padding:16px;margin-bottom:22px;display:flex;flex-wrap:wrap;gap:12px;box-shadow:0 8px 24px rgba(15,23,42,.05);box-sizing:border-box}\n.nb-nav a,.nb-nav button{text-decoration:none;border:none;cursor:pointer;background:#f1f5f9;color:#0f172a;padding:13px 18px;border-radius:999px;font-weight:900;font-size:15px;line-height:1;min-height:48px;display:flex;align-items:center;justify-content:center;box-sizing:border-box}\n.nb-nav a.active{background:#1677ff;color:white}\n.nb-nav button{background:#dc2626;color:white}\n.nb-top{width:100%;background:linear-gradient(135deg,#071b3a,#1677ff);color:white;padding:clamp(24px,4vw,46px);border-radius:30px;margin-bottom:24px;box-shadow:0 18px 45px rgba(22,119,255,.18);box-sizing:border-box}\n.nb-top h1{margin:0 0 14px;font-size:clamp(34px,5vw,62px);line-height:1.05;font-weight:900;letter-spacing:-1px}\n.nb-top p{font-size:clamp(17px,1.6vw,22px);margin:0 0 20px;color:#dbeafe;line-height:1.55;max-width:850px}\n.nb-top-grid{display:grid;grid-template-columns:minmax(0,2fr) minmax(280px,0.9fr);gap:28px;align-items:stretch}\n.nb-info{background:#ffffff18;border:1px solid #ffffff30;color:white;padding:22px;border-radius:20px;line-height:1.55;font-size:16px;box-sizing:border-box}\n.nb-layout{width:100%;display:grid;grid-template-columns:minmax(0,2.2fr) minmax(320px,0.9fr);gap:26px;align-items:start}\n.nb-card{background:white;padding:clamp(20px,2vw,30px);border-radius:26px;box-shadow:0 10px 30px rgba(15,23,42,.06);border:1px solid #e5eaf2;margin-bottom:24px;box-sizing:border-box}\n.nb-card h2{margin:0 0 18px;font-size:clamp(22px,2vw,30px);line-height:1.2}\n.nb-fields{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}\n.nb-field label{display:block;font-size:14px;color:#475569;font-weight:900;margin-bottom:8px}\n.nb-field input,.nb-field select{width:100%;padding:15px 14px;border-radius:15px;border:1px solid #d8deea;box-sizing:border-box;font-size:16px;background:white;min-height:52px}\n.nb-actions{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin-top:22px}\n.nb-btn{padding:15px 16px;border:none;border-radius:15px;cursor:pointer;font-weight:900;font-size:15px;min-height:52px}\n.nb-primary{background:#1677ff;color:white}\n.nb-save{background:#16a34a;color:white}\n.nb-bank{background:#2563eb;color:white}\n.nb-reset{background:#dc2626;color:white}\n.nb-result{background:#f8fafc;border:1px solid #e2e8f0;border-radius:20px;padding:20px;line-height:1.65;box-sizing:border-box}\n.nb-muted{color:#64748b;font-size:15px;line-height:1.6}\n.nb-stat-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px;margin-top:14px}\n.nb-stat{background:#f8fafc;border:1px solid #e2e8f0;border-radius:18px;padding:16px;box-sizing:border-box}\n.nb-stat span{display:block;color:#64748b;font-size:13px;font-weight:900}\n.nb-stat strong{display:block;margin-top:6px;font-size:clamp(20px,2vw,28px)}\n.nb-good{color:#16a34a}\n.nb-warn{color:#f59e0b}\n.nb-bad{color:#dc2626}\n.nb-bar{width:100%;height:12px;background:#e2e8f0;border-radius:999px;overflow:hidden;margin:8px 0 12px}\n.nb-bar-fill{height:100%;width:0%;background:linear-gradient(90deg,#16a34a,#1677ff);border-radius:999px}\n.nb-recommend{background:#eff6ff;border:1px solid #bfdbfe;color:#1e3a8a;padding:16px;border-radius:16px;line-height:1.65;margin-top:14px}\n.nb-small-table{width:100%;border-collapse:collapse;margin-top:8px;font-size:15px}\n.nb-small-table td{border-bottom:1px solid #e2e8f0;padding:11px 0}\n.nb-small-table td:last-child{text-align:right;font-weight:900}\n@media(max-width:1100px){.nb-layout,.nb-top-grid{grid-template-columns:1fr}.nb-fields{grid-template-columns:repeat(2,minmax(0,1fr))}.nb-actions{grid-template-columns:repeat(2,minmax(0,1fr))}}\n@media(max-width:700px){.nb-wrap{padding:14px}.nb-nav{display:grid;grid-template-columns:1fr 1fr;gap:10px;padding:12px;border-radius:18px}.nb-nav a,.nb-nav button{width:100%;text-align:center;font-size:14px;padding:13px 10px;min-height:48px}.nb-top{padding:22px;border-radius:22px}.nb-top h1{font-size:34px}.nb-top p{font-size:17px}.nb-layout,.nb-top-grid,.nb-fields,.nb-stat-grid,.nb-actions{grid-template-columns:1fr}.nb-card{padding:20px;border-radius:22px}.nb-card h2{font-size:24px}.nb-field input,.nb-field select,.nb-btn{font-size:16px;min-height:54px}}\n@media(max-width:420px){.nb-nav{grid-template-columns:1fr}.nb-top h1{font-size:30px}.nb-wrap{padding:10px}}\n<\/style>\n\n<div class=\"nb-wrap\">\n\n<div class=\"nb-menu\">\n<a href=\"https:\/\/nordbalance.dk\/?page_id=63\">\ud83d\udcca Mit Budget<\/a>\n<a href=\"https:\/\/nordbalance.dk\/?page_id=126\">\ud83d\udcb0 Opsparing<\/a>\n<a href=\"https:\/\/nordbalance.dk\/?page_id=130\">\ud83d\udcc8 \u00d8konomi-score<\/a>\n<a href=\"https:\/\/nordbalance.dk\/?page_id=493\">\ud83d\udcc5 M\u00e5nedsoverblik<\/a>\n<a href=\"https:\/\/nordbalance.dk\/?page_id=195\">\ud83e\udde0 Smart Budget Planner<\/a>\n<a class=\"active\" href=\"https:\/\/nordbalance.dk\/?page_id=14\">\ud83e\udd16 AI Hj\u00e6lp<\/a>\n<a href=\"https:\/\/nordbalance.dk\/?page_id=76\">\u2699\ufe0f Min Profil<\/a>\n<\/div>\n\n  <div class=\"nb-top\">\n    <div class=\"nb-top-grid\">\n      <div>\n        <h1>Mit Budget NordBalance<\/h1>\n        <p>F\u00e5 et samlet overblik over din \u00f8konomi. Lav et budget for privat eller familie, og gem det sikkert i Supabase.<\/p>\n        <p>Budgettet kan bagefter bruges p\u00e5 Opsparing, \u00d8konomi-score, AI Hj\u00e6lp og Min Profil.<\/p>\n        <button class=\"nb-btn nb-bank\" type=\"button\" onclick=\"nbConnectBank()\">\ud83c\udfe6 Start bank<\/button>\n      <\/div>\n\n      <div class=\"nb-info\">\n        <b>Status:<\/b><br>\n        <span id=\"bankStatus\">Ingen bank tilkoblet<\/span><br><br>\n        Budgettet kan bruges manuelt imens.\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <div class=\"nb-layout\">\n    <div>\n\n      <div class=\"nb-card\">\n        <h2>\ud83d\udc64 Din husstand<\/h2>\n        <div class=\"nb-fields\">\n          <div class=\"nb-field\">\n            <label>Budgettype<\/label>\n            <select id=\"accountType\">\n              <option value=\"privat\">Privat<\/option>\n              <option value=\"familie\">Familie<\/option>\n            <\/select>\n          <\/div>\n          <div class=\"nb-field\">\n            <label>Antal voksne<\/label>\n            <input id=\"adults\" type=\"number\" min=\"1\" value=\"1\">\n          <\/div>\n          <div class=\"nb-field\">\n            <label>Antal b\u00f8rn<\/label>\n            <input id=\"children\" type=\"number\" min=\"0\" value=\"0\">\n          <\/div>\n        <\/div>\n      <\/div>\n\n      <div class=\"nb-card\">\n        <h2>\ud83d\udcb0 Indkomst<\/h2>\n        <div class=\"nb-fields\">\n          <div class=\"nb-field\">\n            <label>Indkomst 1 efter skat<\/label>\n            <input id=\"income1\" type=\"number\" inputmode=\"decimal\" placeholder=\"Fx 28000\">\n          <\/div>\n          <div class=\"nb-field\">\n            <label>Indkomst 2 efter skat<\/label>\n            <input id=\"income2\" type=\"number\" inputmode=\"decimal\" placeholder=\"Fx 22000\">\n          <\/div>\n          <div class=\"nb-field\">\n            <label>Anden indkomst<\/label>\n            <input id=\"otherIncome\" type=\"number\" inputmode=\"decimal\" placeholder=\"Fx b\u00f8rnepenge, tilskud\">\n          <\/div>\n        <\/div>\n      <\/div>\n\n      <div class=\"nb-card\">\n        <h2>\ud83d\udccb Udgifter<\/h2>\n        <div class=\"nb-fields\">\n          <div class=\"nb-field\"><label>Bolig<\/label><input id=\"housing\" type=\"number\" inputmode=\"decimal\" placeholder=\"Husleje\/l\u00e5n\"><\/div>\n          <div class=\"nb-field\"><label>Mad<\/label><input id=\"food\" type=\"number\" inputmode=\"decimal\" placeholder=\"Madbudget\"><\/div>\n          <div class=\"nb-field\"><label>Transport<\/label><input id=\"transport\" type=\"number\" inputmode=\"decimal\" placeholder=\"Bil, tog, benzin\"><\/div>\n          <div class=\"nb-field\"><label>Abonnementer<\/label><input id=\"subs\" type=\"number\" inputmode=\"decimal\" placeholder=\"Netflix, mobil osv.\"><\/div>\n          <div class=\"nb-field\"><label>G\u00e6ld \/ l\u00e5n<\/label><input id=\"debt\" type=\"number\" inputmode=\"decimal\" placeholder=\"Afdrag\"><\/div>\n          <div class=\"nb-field\"><label>Forsikringer<\/label><input id=\"insurance\" type=\"number\" inputmode=\"decimal\" placeholder=\"Forsikringer\"><\/div>\n          <div class=\"nb-field\"><label>B\u00f8rn \/ familie<\/label><input id=\"familyCosts\" type=\"number\" inputmode=\"decimal\" placeholder=\"Institution, t\u00f8j, fritid\"><\/div>\n          <div class=\"nb-field\"><label>Fritid \/ forbrug<\/label><input id=\"leisure\" type=\"number\" inputmode=\"decimal\" placeholder=\"Sport, gaver, caf\u00e9\"><\/div>\n          <div class=\"nb-field\"><label>Opsparing<\/label><input id=\"savings\" type=\"number\" inputmode=\"decimal\" placeholder=\"Opsparing\"><\/div>\n        <\/div>\n\n        <div class=\"nb-actions\">\n          <button class=\"nb-btn nb-primary\" type=\"button\" onclick=\"nbCalculateBudget()\">\ud83d\udcca Beregn budget<\/button>\n          <button class=\"nb-btn nb-save\" type=\"button\" onclick=\"nbSaveBudget()\">\ud83d\udcbe Gem budget<\/button>\n          <button class=\"nb-btn nb-bank\" type=\"button\" onclick=\"nbCalculateFromBank()\">\ud83c\udfe6 Opdater fra bank<\/button>\n          <button class=\"nb-btn nb-reset\" type=\"button\" onclick=\"nbResetFields()\">Nulstil<\/button>\n          <div id=\"budgetSaveStatus\" style=\"grid-column:1\/-1;font-weight:900;padding:12px 4px 0;color:#64748b;\">Klar til at beregne<\/div>\n        <\/div>\n      <\/div>\n\n      <div class=\"nb-card\">\n        <h2>\ud83d\udcc8 Resultat<\/h2>\n        <div id=\"result\" class=\"nb-result\">Udfyld budgettet og tryk p\u00e5 \u201cBeregn budget\u201d.<\/div>\n      <\/div>\n\n    <\/div>\n\n    <div>\n      <div class=\"nb-card\">\n        <h2>\ud83c\udfe6 Bank<\/h2>\n        <div id=\"bankAccounts\">Ingen bankdata hentet endnu.<\/div>\n      <\/div>\n\n      <div class=\"nb-card\">\n        <h2>\ud83e\udd16 AI budgetr\u00e5d<\/h2>\n        <div id=\"aiAdvice\" class=\"nb-muted\">N\u00e5r du beregner budgettet, f\u00e5r du automatisk personlige r\u00e5d her.<\/div>\n      <\/div>\n\n      <div class=\"nb-card\">\n        <h2>\u2705 Anbefalet fordeling<\/h2>\n        <table class=\"nb-small-table\">\n          <tbody>\n            <tr><td>Bolig<\/td><td>25-35%<\/td><\/tr>\n            <tr><td>Mad<\/td><td>10-18%<\/td><\/tr>\n            <tr><td>Transport<\/td><td>5-15%<\/td><\/tr>\n            <tr><td>G\u00e6ld<\/td><td>Under 15%<\/td><\/tr>\n            <tr><td>Opsparing<\/td><td>10-20%<\/td><\/tr>\n            <tr><td>B\u00f8rn\/familie<\/td><td>Efter behov<\/td><\/tr>\n          <\/tbody>\n        <\/table>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/@supabase\/supabase-js@2\"><\/script>\n\n<script>\nconst NB_SUPABASE_URL = \"https:\/\/vmcpmdcbzatavfkwdcuz.supabase.co\";\nconst NB_SUPABASE_KEY = \"sb_publishable_ODGTPniESClcPb8E2alCQQ_3tadLNmM\";\nconst NB_BUDGET_VERSION = \"budgets-only-2026-06-03\";\nconsole.log(\"NordBalance budget version:\", NB_BUDGET_VERSION);\n\nlet nbClient = null;\n\nfunction nbEl(id){ return document.getElementById(id); }\n\nfunction nbSetHtml(id, html){\n  const el = nbEl(id);\n  if(el) el.innerHTML = html;\n}\n\nfunction nbSetValue(id, value){\n  const el = nbEl(id);\n  if(el) el.value = value ?? \"\";\n}\n\nfunction nbGetValue(id){\n  const el = nbEl(id);\n  return el ? el.value : \"\";\n}\n\nfunction nbNumber(id){\n  const el = nbEl(id);\n  if(!el) return 0;\n  const value = String(el.value || \"0\").replace(\",\", \".\");\n  const number = Number(value);\n  return Number.isFinite(number) ? number : 0;\n}\n\nfunction nbKr(value){\n  return new Intl.NumberFormat(\"da-DK\",{\n    style:\"currency\",\n    currency:\"DKK\",\n    maximumFractionDigits:0\n  }).format(Number(value) || 0);\n}\n\nfunction nbStatus(text, isError=false){\n  const el = nbEl(\"budgetSaveStatus\");\n  if(el){\n    el.innerText = text;\n    el.style.color = isError ? \"#dc2626\" : \"#16a34a\";\n  }\n}\n\nfunction nbGetClient(){\n  if(nbClient) return nbClient;\n\n  if(!window.supabase){\n    nbStatus(\"Supabase er ikke indl\u00e6st.\", true);\n    return null;\n  }\n\n  nbClient = window.supabase.createClient(NB_SUPABASE_URL, NB_SUPABASE_KEY, {\n    auth:{\n      persistSession:true,\n      autoRefreshToken:true,\n      detectSessionInUrl:true\n    }\n  });\n\n  return nbClient;\n}\n\nfunction nbGetBudgetData(){\n  const accountType = nbGetValue(\"accountType\") || \"privat\";\n  const adults = Math.max(1, nbNumber(\"adults\"));\n  const children = Math.max(0, nbNumber(\"children\"));\n\n  const income1 = nbNumber(\"income1\");\n  const income2 = nbNumber(\"income2\");\n  const otherIncome = nbNumber(\"otherIncome\");\n  const income = income1 + income2 + otherIncome;\n\n  const housing = nbNumber(\"housing\");\n  const food = nbNumber(\"food\");\n  const transport = nbNumber(\"transport\");\n  const subscriptions = nbNumber(\"subs\");\n  const debt = nbNumber(\"debt\");\n  const insurance = nbNumber(\"insurance\");\n  const familyCosts = nbNumber(\"familyCosts\");\n  const leisure = nbNumber(\"leisure\");\n  const savings = nbNumber(\"savings\");\n\n  const totalExpenses = housing + food + transport + subscriptions + debt + insurance + familyCosts + leisure + savings;\n  const disposable = income - totalExpenses;\n\n  const housingPct = income > 0 ? housing \/ income * 100 : 0;\n  const foodPct = income > 0 ? food \/ income * 100 : 0;\n  const debtPct = income > 0 ? debt \/ income * 100 : 0;\n  const savingsPct = income > 0 ? savings \/ income * 100 : 0;\n  const familyPct = income > 0 ? familyCosts \/ income * 100 : 0;\n\n  let score = 50;\n  if(income > 0) score += 10;\n  if(disposable >= 0) score += 15;\n  if(savingsPct >= 10) score += 15;\n  if(housingPct <= 35 &#038;&#038; housingPct > 0) score += 10;\n  if(debtPct <= 15) score += 10;\n  if(disposable < 0) score -= 25;\n  if(housingPct > 45) score -= 15;\n  if(savingsPct <= 0 &#038;&#038; income > 0) score -= 10;\n  if(debtPct > 25) score -= 10;\n\n  score = Math.max(0, Math.min(100, Math.round(score)));\n\n  return {\n    accountType,\n    adults,\n    children,\n    income1,\n    income2,\n    otherIncome,\n    income,\n    housing,\n    food,\n    transport,\n    subscriptions,\n    debt,\n    insurance,\n    familyCosts,\n    leisure,\n    savings,\n    totalExpenses,\n    disposable,\n    housingPct,\n    foodPct,\n    debtPct,\n    savingsPct,\n    familyPct,\n    score,\n    month: new Date().toISOString().slice(0,7)\n  };\n}\n\nfunction nbAdvice(data){\n  const advice = [];\n\n  if(data.income <= 0){\n    advice.push(\"Start med at indtaste husstandens indkomst efter skat.\");\n  }\n\n  if(data.accountType === \"familie\"){\n    advice.push(\"Budgettet tager h\u00f8jde for familie, voksne og b\u00f8rn.\");\n  }\n\n  if(data.children > 0){\n    advice.push(\"Med \" + data.children + \" barn\/b\u00f8rn b\u00f8r I have en fast b\u00f8rnepost og en buffer til uforudsete udgifter.\");\n  }\n\n  if(data.disposable < 0){\n    advice.push(\"Budgettet g\u00e5r i minus. Gennemg\u00e5 abonnementer, fritid, mad og variable udgifter.\");\n  }else if(data.disposable < 1500){\n    advice.push(\"R\u00e5dighedsbel\u00f8bet er lavt. Pr\u00f8v at skabe en buffer p\u00e5 mindst 500-1.000 kr. om m\u00e5neden.\");\n  }else{\n    advice.push(\"Budgettet ser positivt ud, fordi der er penge tilbage efter udgifter og opsparing.\");\n  }\n\n  if(data.savingsPct < 10 &#038;&#038; data.income > 0){\n    advice.push(\"Opsparingen er under 10% af indkomsten. Et godt m\u00e5l er at h\u00e6ve den lidt ad gangen.\");\n  }\n\n  if(data.housingPct > 40){\n    advice.push(\"Bolig fylder meget i budgettet. Derfor skal de andre poster styres ekstra stramt.\");\n  }\n\n  if(data.debtPct > 20){\n    advice.push(\"G\u00e6ld fylder meget. Overvej at prioritere dyr g\u00e6ld f\u00f8rst.\");\n  }\n\n  return advice;\n}\n\nfunction nbCalculateBudget(){\n  const data = nbGetBudgetData();\n\n  let scoreClass = \"nb-good\";\n  if(data.score < 70) scoreClass = \"nb-warn\";\n  if(data.score < 45) scoreClass = \"nb-bad\";\n\n  nbSetHtml(\"result\", `\n    <div class=\"nb-stat-grid\">\n      <div class=\"nb-stat\">\n        <span>Samlet indkomst<\/span>\n        <strong>${nbKr(data.income)}<\/strong>\n      <\/div>\n      <div class=\"nb-stat\">\n        <span>Udgifter inkl. opsparing<\/span>\n        <strong>${nbKr(data.totalExpenses)}<\/strong>\n      <\/div>\n      <div class=\"nb-stat\">\n        <span>R\u00e5dighedsbel\u00f8b<\/span>\n        <strong class=\"${data.disposable >= 0 ? \"nb-good\" : \"nb-bad\"}\">${nbKr(data.disposable)}<\/strong>\n      <\/div>\n    <\/div>\n\n    <div class=\"nb-recommend\">\n      <b>Budgettype:<\/b> ${data.accountType === \"familie\" ? \"Familie\" : \"Privat\"}<br>\n      <b>Husstand:<\/b> ${data.adults} voksen\/voksne og ${data.children} barn\/b\u00f8rn<br><br>\n\n      <b>Din \u00f8konomi-score:<\/b> \n      <span class=\"${scoreClass}\" style=\"font-weight:900;\">${data.score}\/100<\/span>\n\n      <div class=\"nb-bar\">\n        <div class=\"nb-bar-fill\" style=\"width:${data.score}%;\"><\/div>\n      <\/div>\n\n      <b>Fordeling:<\/b><br>\n      Bolig: ${data.housingPct.toFixed(1)}% af indkomst<br>\n      Mad: ${data.foodPct.toFixed(1)}% af indkomst<br>\n      G\u00e6ld: ${data.debtPct.toFixed(1)}% af indkomst<br>\n      Opsparing: ${data.savingsPct.toFixed(1)}% af indkomst<br>\n      B\u00f8rn\/familie: ${data.familyPct.toFixed(1)}% af indkomst\n    <\/div>\n  `);\n\n  nbSetHtml(\"aiAdvice\", `\n    <ul style=\"margin:0;padding-left:18px;line-height:1.6;\">\n      ${nbAdvice(data).map(item => `<li>${item}<\/li>`).join(\"\")}\n    <\/ul>\n  `);\n\n  localStorage.setItem(\"nordbalance_latest_budget\", JSON.stringify(data));\n  localStorage.setItem(\"nordbalance_budget_backup\", JSON.stringify(data));\n  localStorage.setItem(\"nordbalance_budget_master\", JSON.stringify(data));\n\n  nbStatus(\"Budget beregnet.\");\n  return data;\n}\n\nasync function nbSaveBudget(){\n  const data = nbCalculateBudget();\n  const supa = nbGetClient();\n\n  if(!supa){\n    alert(\"Budgettet blev beregnet, men Supabase blev ikke indl\u00e6st.\");\n    return;\n  }\n\n  const userRes = await supa.auth.getUser();\n  const user = userRes && userRes.data ? userRes.data.user : null;\n\n  if(!user){\n    alert(\"Du skal v\u00e6re logget ind for at gemme budgettet.\");\n    window.location.href = \"https:\/\/nordbalance.dk\/?page_id=40\";\n    return;\n  }\n\n  nbStatus(\"Gemmer budget i Supabase...\");\n\n  const payload = {\n    user_id: user.id,\n    email: user.email || \"\",\n    month: data.month,\n\n    income: data.income,\n    housing: data.housing,\n    food: data.food,\n    transport: data.transport,\n    subscriptions: data.subscriptions,\n\n    insurance: data.insurance,\n    utilities: 0,\n    phone: 0,\n    debt: data.debt,\n    leisure: data.leisure,\n    other: data.familyCosts,\n    savings: data.savings,\n\n    score: data.score\n  };\n\n  const res = await supa\n    .from(\"budgets\")\n    .insert([payload])\n    .select();\n\n  if(res.error){\n    console.error(\"Supabase gem fejl:\", res.error);\n    nbStatus(\"Budgettet blev ikke gemt i Supabase: \" + res.error.message, true);\n    alert(\"Budgettet blev ikke gemt i Supabase: \" + res.error.message);\n    return;\n  }\n\n  nbStatus(\"Budget gemt i Supabase.\");\n  alert(\"\u2705 Dit budget er gemt i Supabase. Version: budgets-only-2026-06-03\");\n}\n\nasync function nbLoadLatestBudget(){\n  const supa = nbGetClient();\n  if(!supa) return;\n\n  try{\n    const userRes = await supa.auth.getUser();\n    const user = userRes && userRes.data ? userRes.data.user : null;\n\n    if(!user) return;\n\n    const res = await supa\n      .from(\"budgets\")\n      .select(\"*\")\n      .eq(\"user_id\", user.id)\n      .order(\"created_at\", { ascending:false })\n      .limit(1);\n\n    if(res.error){\n      console.warn(\"Kunne ikke hente budget:\", res.error);\n      return;\n    }\n\n    if(res.data && res.data.length > 0){\n      const b = res.data[0];\n\n      nbSetValue(\"income1\", b.income || 0);\n      nbSetValue(\"income2\", 0);\n      nbSetValue(\"otherIncome\", 0);\n\n      nbSetValue(\"housing\", b.housing || 0);\n      nbSetValue(\"food\", b.food || 0);\n      nbSetValue(\"transport\", b.transport || 0);\n      nbSetValue(\"subs\", b.subscriptions || 0);\n      nbSetValue(\"debt\", b.debt || 0);\n      nbSetValue(\"insurance\", b.insurance || 0);\n      nbSetValue(\"familyCosts\", b.other || 0);\n      nbSetValue(\"leisure\", b.leisure || 0);\n      nbSetValue(\"savings\", b.savings || 0);\n\n      nbCalculateBudget();\n      nbStatus(\"Seneste budget hentet fra Supabase.\");\n    }\n\n  }catch(error){\n    console.warn(\"Budget load fejl:\", error);\n  }\n}\n\nfunction nbResetFields(){\n  [\n    \"income1\",\n    \"income2\",\n    \"otherIncome\",\n    \"housing\",\n    \"food\",\n    \"transport\",\n    \"subs\",\n    \"debt\",\n    \"insurance\",\n    \"familyCosts\",\n    \"leisure\",\n    \"savings\"\n  ].forEach(id => nbSetValue(id,\"\"));\n\n  nbSetValue(\"accountType\",\"privat\");\n  nbSetValue(\"adults\",1);\n  nbSetValue(\"children\",0);\n\n  nbSetHtml(\"result\", \"Udfyld budgettet og tryk p\u00e5 \u201cBeregn budget\u201d.\");\n  nbSetHtml(\"aiAdvice\", \"N\u00e5r du beregner budgettet, f\u00e5r du automatisk personlige r\u00e5d her.\");\n\n  nbStatus(\"Felterne er nulstillet.\");\n}\n\nfunction nbCalculateFromBank(){\n  nbSetHtml(\"result\", \"<b>Ingen banktransaktioner fundet endnu.<\/b><br>Forbind f\u00f8rst din bank og pr\u00f8v derefter igen.\");\n}\n\nfunction nbConnectBank(){\n  alert(\"Banktilkobling venter p\u00e5 endelig aktivering. Budgettet kan bruges manuelt imens.\");\n}\n\nasync function nbLogout(){\n  const supa = nbGetClient();\n\n  try{\n    if(supa) await supa.auth.signOut();\n  }catch(error){\n    console.warn(error);\n  }\n\n  localStorage.removeItem(\"nordbalance_latest_budget\");\n  localStorage.removeItem(\"nordbalance_budget_backup\");\n  localStorage.removeItem(\"nordbalance_budget_master\");\n\n  window.location.href = \"https:\/\/nordbalance.dk\/?page_id=40\";\n}\n\nfunction nbInit(){\n  nbGetClient();\n  nbLoadLatestBudget();\n  nbStatus(\"Klar til at beregne\");\n}\n\nif(document.readyState === \"loading\"){\n  document.addEventListener(\"DOMContentLoaded\", nbInit);\n}else{\n  nbInit();\n}\n\nwindow.nbCalculateBudget = nbCalculateBudget;\nwindow.nbSaveBudget = nbSaveBudget;\nwindow.nbResetFields = nbResetFields;\nwindow.nbCalculateFromBank = nbCalculateFromBank;\nwindow.nbConnectBank = nbConnectBank;\nwindow.nbLogout = nbLogout;\n<\/script>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mit Budget NordBalance \ud83d\udcca Mit Budget \ud83d\udcb0 Opsparing \ud83d\udcc8 \u00d8konomi-score \ud83d\udcc5 M\u00e5nedsoverblik \ud83e\udde0 Smart Budget Planner \ud83e\udd16 AI Hj\u00e6lp \u2699\ufe0f Min Profil Mit Budget NordBalance F\u00e5 et samlet overblik over din \u00f8konomi. Lav et budget for privat eller familie, og gem det sikkert i Supabase. Budgettet kan bagefter bruges p\u00e5 Opsparing, \u00d8konomi-score, AI Hj\u00e6lp og [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-63","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/nordbalance.dk\/index.php?rest_route=\/wp\/v2\/pages\/63","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nordbalance.dk\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/nordbalance.dk\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/nordbalance.dk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nordbalance.dk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=63"}],"version-history":[{"count":66,"href":"https:\/\/nordbalance.dk\/index.php?rest_route=\/wp\/v2\/pages\/63\/revisions"}],"predecessor-version":[{"id":500,"href":"https:\/\/nordbalance.dk\/index.php?rest_route=\/wp\/v2\/pages\/63\/revisions\/500"}],"wp:attachment":[{"href":"https:\/\/nordbalance.dk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=63"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}