{"id":318,"date":"2026-08-17T11:16:14","date_gmt":"2026-08-17T11:16:14","guid":{"rendered":"https:\/\/kikistationary.pt\/?page_id=318"},"modified":"2026-09-16T16:46:52","modified_gmt":"2026-09-16T16:46:52","slug":"compras-do-mes-individual-2000-kcal","status":"publish","type":"page","link":"https:\/\/kikistationary.pt\/?page_id=318","title":{"rendered":"Compras do M\u00eas &#8211; Individual &#8211; 2000 Kcal"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"318\" class=\"elementor elementor-318\">\n\t\t\t\t<div class=\"elementor-element elementor-element-44b8b9b e-flex e-con-boxed e-con e-parent\" data-id=\"44b8b9b\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-aff0db9 elementor-widget elementor-widget-html\" data-id=\"aff0db9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<style>\n  .kks-header{\n    --kks-bg: #1b2b22;\n    --kks-paper: #f4efe3;\n    --kks-paper-soft: #fbf8f1;\n    --kks-ink: #22301f;\n    --kks-accent: #e8a33d;\n    --kks-line: rgba(244,239,227,0.16);\n    box-sizing: border-box;\n    font-family:'Inter', sans-serif;\n    position: sticky; top:0; z-index: 999;\n    background: rgba(27,43,34,0.94);\n    backdrop-filter: blur(8px);\n    border-bottom: 1px solid var(--kks-line);\n  }\n  .kks-header *{ box-sizing: border-box; }\n\n  .kks-header-inner{\n    max-width: 1200px; margin:0 auto;\n    display:flex; align-items:center; justify-content:space-between;\n    padding: 14px 20px;\n  }\n  .kks-logo{\n    font-family:'Oswald', sans-serif; font-weight:700; font-size:22px;\n    letter-spacing: .04em; color: var(--kks-paper-soft); text-decoration:none;\n    display:flex; align-items:baseline; gap:2px; flex-shrink:0;\n  }\n  .kks-logo span{ color: var(--kks-accent); }\n\n  .kks-desktop-nav{ display:flex; align-items:center; gap: 6px; }\n  .kks-nav-item{ position:relative; }\n  .kks-nav-btn{\n    font-family:'IBM Plex Mono', monospace; font-size:12.5px; letter-spacing:.04em;\n    text-transform:uppercase; background:transparent; color: var(--kks-paper-soft);\n    border: 1.5px solid transparent; border-radius: 8px; padding: 10px 14px;\n    cursor:pointer; text-decoration:none; display:inline-flex; align-items:center; gap:6px;\n    transition: background .15s ease, color .15s ease, border-color .15s ease;\n  }\n  .kks-nav-btn:hover, .kks-nav-btn:focus-visible, .kks-nav-btn.kks-active{\n    background: var(--kks-accent); color: var(--kks-ink); border-color: var(--kks-accent);\n    outline:none;\n  }\n  .kks-nav-btn.kks-parent-active{ border-color: var(--kks-accent); color: var(--kks-accent); }\n  .kks-nav-btn .kks-caret{ font-size:9px; transition: transform .15s ease; }\n  .kks-nav-item.kks-open .kks-nav-btn .kks-caret{ transform: rotate(180deg); }\n\n  .kks-dropdown{\n    position:absolute; top: calc(100% + 8px); left:0;\n    background: var(--kks-paper); border-radius: 12px; min-width: 220px;\n    box-shadow: 0 14px 30px rgba(0,0,0,0.35);\n    padding: 6px; display:none; flex-direction:column; gap:2px;\n  }\n  .kks-nav-item.kks-open .kks-dropdown{ display:flex; }\n  .kks-dropdown a{\n    font-family:'Inter', sans-serif; font-size:13.5px; font-weight:500;\n    color: var(--kks-ink); text-decoration:none; padding: 10px 12px; border-radius: 8px;\n    transition: background .12s ease, color .12s ease;\n  }\n  .kks-dropdown a:hover, .kks-dropdown a:focus-visible{ background: var(--kks-accent); color: var(--kks-ink); outline:none; }\n\n  .kks-hamburger{\n    display:none; flex-direction:column; justify-content:center; gap:5px;\n    width: 40px; height: 40px; background:transparent; border:1.5px solid var(--kks-line);\n    border-radius: 8px; cursor:pointer; padding:0; align-items:center;\n  }\n  .kks-hamburger span{\n    width: 20px; height:2px; background: var(--kks-paper-soft); border-radius:2px;\n    transition: transform .2s ease, opacity .2s ease;\n  }\n  .kks-hamburger.kks-open span:nth-child(1){ transform: translateY(7px) rotate(45deg); }\n  .kks-hamburger.kks-open span:nth-child(2){ opacity:0; }\n  .kks-hamburger.kks-open span:nth-child(3){ transform: translateY(-7px) rotate(-45deg); }\n  .kks-hamburger:hover, .kks-hamburger:focus-visible{ background: rgba(232,163,61,0.12); border-color: var(--kks-accent); outline:none; }\n\n  .kks-mobile-nav{\n    display:none; flex-direction:column; gap:4px;\n    max-width:1200px; margin:0 auto; padding: 4px 20px 16px;\n  }\n  .kks-mobile-nav.kks-open{ display:flex; }\n  .kks-m-nav-item{ display:flex; flex-direction:column; }\n  .kks-m-nav-btn{\n    font-family:'IBM Plex Mono', monospace; font-size:13px; letter-spacing:.03em;\n    text-transform:uppercase; background:transparent; color: var(--kks-paper-soft);\n    border:none; text-align:left; padding: 13px 10px; border-radius: 8px;\n    cursor:pointer; display:flex; justify-content:space-between; align-items:center;\n    text-decoration:none; width:100%; transition: background .15s ease, color .15s ease;\n  }\n  .kks-m-nav-btn:hover, .kks-m-nav-btn:focus-visible, .kks-m-nav-btn.kks-active{\n    background: var(--kks-accent); color: var(--kks-ink); outline:none;\n  }\n  .kks-m-nav-btn.kks-parent-active{ color: var(--kks-accent); }\n  .kks-m-dropdown{ display:none; flex-direction:column; padding: 2px 4px 6px 14px; gap:2px; }\n  .kks-m-nav-item.kks-open .kks-m-dropdown{ display:flex; }\n  .kks-m-dropdown a{\n    font-family:'Inter', sans-serif; font-size:13px; color: rgba(244,239,227,0.75);\n    text-decoration:none; padding: 10px 12px; border-radius: 7px;\n    border-left: 2px solid var(--kks-line);\n    transition: background .12s ease, color .12s ease, border-color .12s ease;\n  }\n  .kks-m-dropdown a:hover, .kks-m-dropdown a:focus-visible{\n    background: rgba(232,163,61,0.14); color: var(--kks-accent); border-color: var(--kks-accent); outline:none;\n  }\n  .kks-m-nav-item.kks-open .kks-m-nav-btn .kks-caret{ transform: rotate(180deg); }\n\n  .kks-toast{\n    position: fixed; bottom: 24px; left:50%; transform: translateX(-50%) translateY(20px);\n    background: var(--kks-paper); color: var(--kks-ink); font-family:'IBM Plex Mono', monospace;\n    font-size:13px; padding: 12px 20px; border-radius: 999px; box-shadow: 0 12px 30px rgba(0,0,0,0.35);\n    opacity:0; pointer-events:none; transition: opacity .2s ease, transform .2s ease; z-index:9999;\n  }\n  .kks-toast.kks-show{ opacity:1; transform: translateX(-50%) translateY(0); }\n\n  @media (max-width: 860px){\n    .kks-desktop-nav{ display:none; }\n    .kks-hamburger{ display:flex; }\n  }\n  @media (prefers-reduced-motion: reduce){ .kks-header *{ transition:none !important; } }\n<\/style>\n\n<header class=\"kks-header\">\n  <div class=\"kks-header-inner\">\n    <a href=\"\/\" class=\"kks-logo\">KIKI<span>STAT<\/span><\/a>\n\n    <nav class=\"kks-desktop-nav\" aria-label=\"Navega\u00e7\u00e3o principal\">\n      <div class=\"kks-nav-item\" data-kks-nav=\"compra\">\n        <button class=\"kks-nav-btn\" data-kks-toggle=\"compra\" aria-haspopup=\"true\" aria-expanded=\"false\">\n          Compra do M\u00eas <span class=\"kks-caret\">\u25be<\/span>\n        <\/button>\n        <div class=\"kks-dropdown\">\n          <a href=\"https:\/\/kikistationary.pt\/?page_id=250\" data-kks-id=\"casal\">Casal<\/a>\n          <a href=\"https:\/\/kikistationary.pt\/?page_id=318\" data-kks-id=\"2000kcal\">Individual 2000kcal<\/a>\n          <a href=\"https:\/\/kikistationary.pt\/?page_id=309\" data-kks-id=\"3000kcal\">Individual 3000kcal<\/a>\n        <\/div>\n      <\/div>\n      <a class=\"kks-nav-btn\" href=\"https:\/\/kikistationary.pt\/?page_id=286\" data-kks-id=\"limpeza\">Limpeza da Casa<\/a>\n      <a class=\"kks-nav-btn\" href=\"https:\/\/kikistationary.pt\/?page_id=244\" data-kks-id=\"habit\">Habit Tracker<\/a>\n    <\/nav>\n\n    <button class=\"kks-hamburger\" id=\"kksHamburgerBtn\" aria-label=\"Abrir menu\" aria-expanded=\"false\">\n      <span><\/span><span><\/span><span><\/span>\n    <\/button>\n  <\/div>\n\n  <nav class=\"kks-mobile-nav\" id=\"kksMobileNav\" aria-label=\"Navega\u00e7\u00e3o m\u00f3vel\">\n    <div class=\"kks-m-nav-item\" data-kks-mnav=\"compra\">\n      <button class=\"kks-m-nav-btn\" data-kks-mtoggle=\"compra\" aria-haspopup=\"true\" aria-expanded=\"false\">\n        Compra do M\u00eas <span class=\"kks-caret\">\u25be<\/span>\n      <\/button>\n      <div class=\"kks-m-dropdown\">\n        <a href=\"https:\/\/kikistationary.pt\/?page_id=250\" data-kks-id=\"casal\">Casal<\/a>\n        <a href=\"https:\/\/kikistationary.pt\/?page_id=318\" data-kks-id=\"2000kcal\">Individual 2000kcal<\/a>\n        <a href=\"https:\/\/kikistationary.pt\/?page_id=309\" data-kks-id=\"3000kcal\">Individual 3000kcal<\/a>\n      <\/div>\n    <\/div>\n    <a class=\"kks-m-nav-btn\" href=\"https:\/\/kikistationary.pt\/?page_id=286\" data-kks-id=\"limpeza\">Limpeza da Casa<\/a>\n    <a class=\"kks-m-nav-btn\" href=\"https:\/\/kikistationary.pt\/?page_id=244\" data-kks-id=\"habit\">Habit Tracker<\/a>\n    <button class=\"kks-m-nav-btn\" data-kks-placeholder=\"Estudo\">Estudo<\/button>\n  <\/nav>\n<\/header>\n\n<div class=\"kks-toast\" id=\"kksToast\"><\/div>\n\n<script>\n(function(){\n  var navItem = document.querySelector('.kks-nav-item[data-kks-nav=\"compra\"]');\n  var navBtn = navItem.querySelector('[data-kks-toggle=\"compra\"]');\n  navBtn.addEventListener('click', function(e){\n    e.stopPropagation();\n    var isOpen = navItem.classList.toggle('kks-open');\n    navBtn.setAttribute('aria-expanded', isOpen);\n  });\n  document.addEventListener('click', function(e){\n    if(!navItem.contains(e.target)){\n      navItem.classList.remove('kks-open');\n      navBtn.setAttribute('aria-expanded', 'false');\n    }\n  });\n  document.addEventListener('keydown', function(e){\n    if(e.key === 'Escape'){\n      navItem.classList.remove('kks-open');\n      navBtn.setAttribute('aria-expanded', 'false');\n    }\n  });\n\n  var hamburger = document.getElementById('kksHamburgerBtn');\n  var mobileNav = document.getElementById('kksMobileNav');\n  hamburger.addEventListener('click', function(){\n    var isOpen = hamburger.classList.toggle('kks-open');\n    mobileNav.classList.toggle('kks-open', isOpen);\n    hamburger.setAttribute('aria-expanded', isOpen);\n    hamburger.setAttribute('aria-label', isOpen ? 'Fechar menu' : 'Abrir menu');\n  });\n\n  var mNavItem = document.querySelector('.kks-m-nav-item[data-kks-mnav=\"compra\"]');\n  var mNavBtn = mNavItem.querySelector('[data-kks-mtoggle=\"compra\"]');\n  mNavBtn.addEventListener('click', function(){\n    var isOpen = mNavItem.classList.toggle('kks-open');\n    mNavBtn.setAttribute('aria-expanded', isOpen);\n  });\n\n  \/\/ ---- cache da sec\u00e7\u00e3o ativa (localStorage) ----\n  \/\/ Num site real cada clique recarrega a p\u00e1gina, por isso o bot\u00e3o \"ativo\"\n  \/\/ precisa de ficar guardado em localStorage para sobreviver ao reload.\n  var LS_KEY = 'kks-active-nav';\n\n  function lsGet(){\n    try{ return window.localStorage.getItem(LS_KEY); }\n    catch(e){ return null; } \/\/ ex: preview em iframe sandboxed (artefacto do Claude)\n  }\n  function lsSet(id){\n    try{ window.localStorage.setItem(LS_KEY, id); }\n    catch(e){ \/* localStorage indispon\u00edvel neste contexto \u2014 segue sem cache *\/ }\n  }\n\n  var SUBMENU_IDS = ['casal', '2000kcal', '3000kcal'];\n  var URL_MAP = {\n    'casal': 'page_id=250',\n    '2000kcal': 'page_id=318',\n    '3000kcal': 'page_id=309',\n    'limpeza': 'page_id=286',\n    'habit': 'page_id=244'\n  };\n\n  function applyActive(id){\n    if(!id) return;\n    document.querySelectorAll('[data-kks-id]').forEach(function(el){\n      el.classList.toggle('kks-active', el.dataset.kksId === id);\n    });\n    var isSubmenu = SUBMENU_IDS.indexOf(id) > -1;\n    document.querySelectorAll('[data-kks-toggle=\"compra\"], [data-kks-mtoggle=\"compra\"]').forEach(function(el){\n      el.classList.toggle('kks-parent-active', isSubmenu);\n    });\n  }\n\n  function detectFromUrl(){\n    var href = window.location.href;\n    for(var id in URL_MAP){\n      if(href.indexOf(URL_MAP[id]) > -1) return id;\n    }\n    return null;\n  }\n\n  var activeId = detectFromUrl() || lsGet();\n  applyActive(activeId);\n\n  document.querySelectorAll('[data-kks-id]').forEach(function(el){\n    el.addEventListener('click', function(){\n      lsSet(el.dataset.kksId);\n      applyActive(el.dataset.kksId);\n    });\n  });\n\n  var toastTimer = null;\n  function showToast(msg){\n    var toast = document.getElementById('kksToast');\n    toast.textContent = msg;\n    toast.classList.add('kks-show');\n    clearTimeout(toastTimer);\n    toastTimer = setTimeout(function(){ toast.classList.remove('kks-show'); }, 2200);\n  }\n  document.querySelectorAll('[data-kks-placeholder]').forEach(function(btn){\n    btn.addEventListener('click', function(){\n      showToast(btn.dataset.kksPlaceholder + \" \u2014 p\u00e1gina a caminho \ud83d\udea7\");\n      hamburger.classList.remove('kks-open');\n      mobileNav.classList.remove('kks-open');\n      hamburger.setAttribute('aria-expanded', 'false');\n    });\n  });\n\n  document.querySelectorAll('.kks-mobile-nav a').forEach(function(a){\n    a.addEventListener('click', function(){\n      hamburger.classList.remove('kks-open');\n      mobileNav.classList.remove('kks-open');\n      hamburger.setAttribute('aria-expanded', 'false');\n    });\n  });\n})();\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-b20a9bd e-flex e-con-boxed e-con e-parent\" data-id=\"b20a9bd\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-e856215 elementor-widget elementor-widget-html\" data-id=\"e856215\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\n<html lang=\"pt-PT\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Compra do M\u00eas \u2014 Talho & Horta<\/title>\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n\n<style>\n  :root{\n    --bg: #1b2b22; --bg-soft: #223528;\n    --paper: #f4efe3; --paper-soft: #fbf8f1;\n    --ink: #22301f; --ink-soft: #5b6b54;\n    --accent: #e8a33d; --accent-dark: #c9862b;\n    --good: #3f7a52; --good-bg: #e4f0e6;\n    --warn: #c97a1f; --warn-bg: #f7ead2;\n    --bad: #b8433a; --bad-bg: #f6e0dd;\n    --line: rgba(34,48,31,0.14); --radius: 10px;\n  }\n  *{ box-sizing:border-box; }\n  html,body{ margin:0; padding:0; }\n  body{\n    background: radial-gradient(ellipse at top left, var(--bg-soft), var(--bg) 60%);\n    color: var(--paper); font-family: 'Inter', sans-serif;\n    min-height: 100vh; padding: 28px 16px 150px;\n  }\n  .wrap{ max-width: 1000px; margin: 0 auto; }\n  header{ margin-bottom: 18px; }\n  .eyebrow{\n    font-family:'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: .14em;\n    text-transform: uppercase; color: var(--accent); margin: 0 0 6px;\n  }\n  h1{\n    font-family:'Oswald', sans-serif; font-weight: 700; font-size: clamp(28px, 5vw, 42px);\n    margin: 0 0 4px; letter-spacing: .01em; color: var(--paper-soft);\n  }\n  .subtitle{ color: rgba(244,239,227,0.65); font-size: 14px; margin: 0 0 16px; }\n  .note{\n    background: rgba(232,163,61,0.1); border: 1px solid rgba(232,163,61,0.35);\n    border-radius: var(--radius); padding: 14px 16px; font-size: 13.5px; line-height: 1.55;\n    color: var(--paper-soft);\n  }\n  .note b{ color: var(--accent); }\n  .note + .note{ margin-top:10px; }\n\n  .estimate-banner{\n    margin-top:16px; background: var(--paper); border-radius: 14px; padding: 16px 20px;\n    display:flex; flex-wrap:wrap; gap: 18px 24px; align-items:center;\n    box-shadow: 0 10px 30px rgba(0,0,0,0.25);\n  }\n  .estimate-item{ font-family:'IBM Plex Mono', monospace; }\n  .estimate-item .label{ font-size:10.5px; text-transform:uppercase; letter-spacing:.08em; color: var(--ink-soft); display:block; }\n  .estimate-item .value{ font-size: 21px; font-weight:600; color: var(--ink); }\n  .estimate-item .value.small{ font-size:15px; }\n\n  .quinzena{ margin-top: 26px; }\n  .quinzena-head{ display:flex; align-items:baseline; justify-content:space-between; padding: 0 4px 8px; }\n  .quinzena-head h2{ font-family:'Oswald', sans-serif; font-size: 22px; color: var(--paper-soft); margin:0; }\n  .quinzena-head span{ font-family:'IBM Plex Mono', monospace; font-size:12px; color: rgba(244,239,227,0.6); }\n\n  .category{\n    background: var(--paper); border-radius: 14px; padding: 6px 0 8px; margin-top: 12px;\n    box-shadow: 0 10px 30px rgba(0,0,0,0.25); overflow: hidden;\n  }\n  .category h3{\n    font-family:'Oswald', sans-serif; font-size: 17px; font-weight: 600; color: var(--ink);\n    margin: 0; padding: 14px 18px 8px; display:flex; align-items:center; justify-content:space-between;\n  }\n  .category h3 .count{\n    font-family:'IBM Plex Mono', monospace; font-size: 11px; font-weight: 500; color: var(--ink-soft);\n    background: rgba(34,48,31,0.06); padding: 3px 9px; border-radius: 999px;\n  }\n\n  .items{ list-style:none; margin:0; padding:0; }\n  .item{\n    display:grid; grid-template-columns: 30px 1.6fr 0.9fr 0.9fr 1.1fr;\n    align-items:center; gap: 8px; padding: 9px 18px; border-top: 1px solid var(--line);\n    transition: background .15s ease;\n  }\n  .item.checked{ background: rgba(63,122,82,0.06); }\n  .check{ position:relative; display:flex; align-items:center; justify-content:center; cursor:pointer; }\n  .check input{ position:absolute; opacity:0; width:24px; height:24px; margin:0; cursor:pointer; }\n  .box{\n    width:20px; height:20px; border-radius:6px; border:2px solid var(--ink-soft);\n    display:flex; align-items:center; justify-content:center; transition: all .15s ease; flex-shrink:0;\n  }\n  .check input:checked + .box{ background: var(--good); border-color: var(--good); }\n  .box svg{ opacity:0; transform: scale(.5); transition: all .12s ease; }\n  .check input:checked + .box svg{ opacity:1; transform:scale(1); }\n  .check input:focus-visible + .box{ outline: 2px solid var(--accent-dark); outline-offset:2px; }\n\n  .info{ min-width:0; }\n  .name{ display:block; font-weight:600; color: var(--ink); font-size:14px; }\n  .item.checked .name{ color: var(--ink-soft); }\n  .unit{ display:block; font-size:11px; color: var(--ink-soft); margin-top:1px; }\n\n  .qty-wrap{ display:flex; align-items:center; gap:4px; min-width:0; }\n  .qty-wrap input{\n    width: 68px; flex-shrink:0; font-family:'IBM Plex Mono', monospace; font-size:13px;\n    border:1.5px solid var(--line); border-radius:7px; padding:5px 6px;\n    background: var(--paper-soft); color: var(--ink); text-align:right;\n  }\n  .qty-wrap .qtylabel{ font-size:11px; color: var(--ink-soft); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\n\n  .estcost{ font-family:'IBM Plex Mono', monospace; font-size:12.5px; color: var(--ink-soft); text-align:right; }\n  .estcost strong{ color: var(--ink); font-weight:600; }\n\n  .paid{\n    display:flex; align-items:center; gap:4px; background: var(--paper-soft);\n    border: 1.5px solid var(--line); border-radius: 8px; padding: 5px 8px; min-width: 0;\n  }\n  .paid span{ font-family:'IBM Plex Mono', monospace; font-size:12px; color: var(--ink-soft); flex-shrink:0; }\n  .paid input{\n    border:none; background:transparent; width:100%; min-width: 64px; flex:1;\n    font-family:'IBM Plex Mono', monospace; font-size:13px; color: var(--ink); outline:none;\n  }\n  .paid.good{ border-color: var(--good); background: var(--good-bg); }\n  .paid.warn{ border-color: var(--warn); background: var(--warn-bg); }\n  .paid.bad{ border-color: var(--bad); background: var(--bad-bg); }\n\n  .status-pill{\n    grid-column: 2 \/ -1; font-size: 10.5px; font-family:'IBM Plex Mono', monospace;\n    margin-top: 2px; display:none;\n  }\n  .status-pill.show{ display:block; }\n  .status-pill.good{ color: var(--good); }\n  .status-pill.warn{ color: var(--warn); }\n  .status-pill.bad{ color: var(--bad); }\n\n  .add-row{ padding: 12px 18px 6px; }\n  .add-toggle{\n    font-family:'IBM Plex Mono', monospace; font-size: 12px; background:none;\n    border: 1.5px dashed var(--ink-soft); color: var(--ink-soft); padding: 7px 12px;\n    border-radius: 8px; cursor:pointer; width:100%; text-align:left;\n  }\n  .add-toggle:hover{ border-color: var(--accent-dark); color: var(--ink); }\n  .add-form{ display:none; grid-template-columns: 1fr 90px 90px auto; gap: 8px; margin-top: 8px; }\n  .add-form.show{ display:grid; }\n  .add-form input{\n    font-family:'Inter', sans-serif; font-size: 12.5px; padding: 8px 8px; border-radius: 7px;\n    border: 1.5px solid var(--line); background: var(--paper-soft); color: var(--ink);\n  }\n  .add-form button{\n    font-family:'Inter', sans-serif; font-weight:600; font-size:12.5px; background: var(--ink);\n    color: var(--paper-soft); border:none; border-radius:7px; padding: 8px 12px; cursor:pointer;\n  }\n\n  .actions{ margin-top: 24px; display:flex; gap:10px; flex-wrap:wrap; }\n  .actions button{\n    font-family:'IBM Plex Mono', monospace; font-size:12px; background: rgba(244,239,227,0.08);\n    color: var(--paper-soft); border: 1px solid rgba(244,239,227,0.25); padding: 9px 14px;\n    border-radius: 8px; cursor:pointer;\n  }\n  .actions button:hover{ background: rgba(244,239,227,0.16); }\n\n  .receipt-wrap{ position: fixed; bottom: 0; left:0; right:0; display:flex; justify-content:center; pointer-events:none; padding: 0 12px; }\n  .receipt{\n    pointer-events:auto; width:100%; max-width: 460px; background: var(--paper-soft); color: var(--ink);\n    font-family:'IBM Plex Mono', monospace; border-radius: 14px 14px 0 0;\n    box-shadow: 0 -12px 30px rgba(0,0,0,0.35); padding: 12px 20px 14px; position: relative;\n  }\n  .receipt::before{\n    content:\"\"; position:absolute; top:-9px; left:0; right:0; height:10px;\n    background:\n      linear-gradient(135deg, transparent 50%, var(--paper-soft) 50%) 0 0\/12px 10px repeat-x,\n      linear-gradient(-135deg, transparent 50%, var(--paper-soft) 50%) 0 0\/12px 10px repeat-x;\n  }\n  .receipt-head{\n    display:flex; justify-content:space-between; align-items:baseline; font-size: 10.5px;\n    letter-spacing:.06em; text-transform:uppercase; color: var(--ink-soft);\n    border-bottom: 1px dashed var(--line); padding-bottom: 7px; margin-bottom: 7px;\n  }\n  .receipt-row{ display:flex; justify-content:space-between; font-size:12.5px; margin: 3px 0; }\n  .receipt-row.total{ font-size: 16px; font-weight:600; margin-top:6px; border-top: 1px dashed var(--line); padding-top:7px; }\n  .receipt-row .diff-good{ color: var(--good); }\n  .receipt-row .diff-bad{ color: var(--bad); }\n\n  @media (max-width: 760px){\n    .item{ grid-template-columns: 26px 1fr; row-gap:6px; }\n    .qty-wrap{ grid-column: 2\/3; width: 100%; max-width: 220px; }\n    .qty-wrap input{ width: 84px; font-size: 15px; }\n    .estcost{ grid-column: 2\/3; text-align:left; }\n    .paid{ grid-column: 2\/3; width: 100%; max-width: 220px; }\n    .paid input{ font-size: 15px; }\n    body{ padding-bottom: 190px; }\n    .estimate-banner{ flex-direction:column; align-items:flex-start; gap:10px; }\n  }\n  @media (prefers-reduced-motion: reduce){ *{ transition:none !important; } }\n<\/style>\n<\/head>\n<body>\n<div class=\"wrap\">\n  <header>\n    <p class=\"eyebrow\">Talho, Horta &amp; Despensa \u00b7 Casal Fitness<\/p>\n    <h1>Compra do M\u00eas<\/h1>\n    <p class=\"subtitle\">Dividida em 2 quinzenas para os frescos n\u00e3o estragarem. Marca o que j\u00e1 foi ao carrinho e acompanha o gasto real vs. estimado.<\/p>\n    <div class=\"note\">\n      <b>Como calculei as quantidades:<\/b> prote\u00edna ~2g\/kg para ele (92kg \u2192 ~184g\/dia) e ~30% das calorias em prote\u00edna para ela (1700kcal \u2192 ~127g\/dia) \u2014 juntos ~311g\/dia, dos quais a lista de carnes\/peixe\/ovos cobre cerca de 75%. Carboidratos seguem o restante das calorias de cada um (~378g\/dia dele + ~191g\/dia dela). Vegetais e frutas seguem ~400g\/dia por pessoa cada. Os campos de quantidade s\u00e3o edit\u00e1veis \u2014 ajusta \u00e0 vontade se algo n\u00e3o bater certo.\n    <\/div>\n    <div class=\"note\">\n      <b>Receitas especiais do m\u00eas:<\/b> tartar de atum (quinzena 1), ceviche de peixe branco e feij\u00e3o tropeiro (quinzena 2) \u2014 os ingredientes s\u00f3 aparecem com quantidade na quinzena em que a receita \u00e9 feita; se mudares de ideia sobre quando cozinhar cada uma, ajusta o campo de quantidade na quinzena certa e zera na outra.\n    <\/div>\n  <\/header>\n\n  <div class=\"estimate-banner\">\n    <div class=\"estimate-item\"><span class=\"label\">Estimativa do m\u00eas<\/span><span class=\"value\" id=\"monthEstimate\">0,00\u20ac<\/span><\/div>\n    <div class=\"estimate-item\"><span class=\"label\">Por quinzena<\/span><span class=\"value small\" id=\"fortnightEstimate\">0,00\u20ac<\/span><\/div>\n    <div class=\"estimate-item\"><span class=\"label\">Carnes\/peixe\/ovos<\/span><span class=\"value small\" id=\"estCarnes\">0,00\u20ac<\/span><\/div>\n    <div class=\"estimate-item\"><span class=\"label\">Legumes\/vegetais<\/span><span class=\"value small\" id=\"estLegumes\">0,00\u20ac<\/span><\/div>\n    <div class=\"estimate-item\"><span class=\"label\">Carboidratos<\/span><span class=\"value small\" id=\"estCarboidratos\">0,00\u20ac<\/span><\/div>\n    <div class=\"estimate-item\"><span class=\"label\">Frutas<\/span><span class=\"value small\" id=\"estFrutas\">0,00\u20ac<\/span><\/div>\n    <div class=\"estimate-item\"><span class=\"label\">Outros<\/span><span class=\"value small\" id=\"estOutros\">0,00\u20ac<\/span><\/div>\n    <div class=\"estimate-item\"><span class=\"label\">Receitas especiais<\/span><span class=\"value small\" id=\"estReceitas\">0,00\u20ac<\/span><\/div>\n  <\/div>\n\n  <div id=\"quinzenas\"><\/div>\n\n  <div class=\"actions\">\n    <button type=\"button\" id=\"resetBtn\">\ud83d\udd04 Nova compra (limpar marca\u00e7\u00f5es e valores pagos)<\/button>\n  <\/div>\n<\/div>\n\n<div class=\"receipt-wrap\">\n  <div class=\"receipt\">\n    <div class=\"receipt-head\"><span>tal\u00e3o da compra \u00b7 m\u00eas inteiro<\/span><span id=\"itemCount\">0 itens<\/span><\/div>\n    <div class=\"receipt-row\"><span>Estimado p\/ itens marcados<\/span><span id=\"idealSum\">0,00\u20ac<\/span><\/div>\n    <div class=\"receipt-row total\"><span>Total gasto<\/span><span id=\"paidSum\">0,00\u20ac<\/span><\/div>\n    <div class=\"receipt-row\"><span>Diferen\u00e7a<\/span><span id=\"diffVal\">\u2014<\/span><\/div>\n  <\/div>\n<\/div>\n\n<script>\n(function(){\n  const CATEGORIES = [\n    { key:\"carnes\", label:\"\ud83e\udd69 Carnes, Peixe &amp; Ovos\" },\n    { key:\"legumes\", label:\"\ud83e\udd6c Legumes &amp; Vegetais\" },\n    { key:\"carboidratos\", label:\"\ud83c\udf3e Carboidratos\" },\n    { key:\"frutas\", label:\"\ud83c\udf4e Frutas\" },\n    { key:\"outros\", label:\"\ud83e\uddc8 Outros Essenciais\" },\n    { key:\"receitas\", label:\"\ud83c\udf7d\ufe0f Receitas Especiais do M\u00eas\" }\n  ];\n\n  const DEFAULT_ITEMS = {\n    legumes: [\n      { id:\"brocolos\", name:\"Br\u00f3colos\", unitLabel:\"unidades\", ideal:1.79, qty:3 },\n      { id:\"couve-flor\", name:\"Couve-flor\", unitLabel:\"unidades\", ideal:1.99, qty:2 },\n      { id:\"courgette\", name:\"Courgette\", unitLabel:\"kg\", ideal:1.49, qty:1.5 },\n      { id:\"pimentos\", name:\"Pimentos (mistos)\", unitLabel:\"kg\", ideal:2.99, qty:1 },\n      { id:\"cogumelos\", name:\"Cogumelos\", unitLabel:\"embalagens (250g)\", ideal:1.49, qty:2 },\n      { id:\"batata-doce\", name:\"Batata-doce (extra p\/ pratos)\", unitLabel:\"kg\", ideal:1.99, qty:1 },\n      { id:\"alho-frances\", name:\"Alho-franc\u00eas\", unitLabel:\"kg\", ideal:1.99, qty:1 },\n      { id:\"cebola\", name:\"Cebola\", unitLabel:\"kg\", ideal:1.49, qty:1.5 },\n      { id:\"tomate\", name:\"Tomate\", unitLabel:\"kg\", ideal:1.99, qty:1.5 },\n      { id:\"pepino\", name:\"Pepino\", unitLabel:\"unidades\", ideal:0.79, qty:3 },\n      { id:\"abobora\", name:\"Ab\u00f3bora\", unitLabel:\"kg\", ideal:1.99, qty:1 }\n    ],\n    carnes: [\n      { id:\"peito-frango\", name:\"Peito de frango\", unitLabel:\"kg\", ideal:6.49, qty:3.5 },\n      { id:\"carne-picada\", name:\"Carne picada (vaca)\", unitLabel:\"kg\", ideal:12.99, qty:2 },\n      { id:\"bife-vaca\", name:\"Bife de vaca\", unitLabel:\"kg\", ideal:17.99, qty:1.3 },\n      { id:\"lombo-porco\", name:\"Lombo de porco\", unitLabel:\"kg\", ideal:6.49, qty:1.5 },\n      { id:\"salmao\", name:\"Salm\u00e3o (posta\/filete)\", unitLabel:\"kg\", ideal:14.99, qty:1.4 },\n      { id:\"pescada\", name:\"Pescada (filete)\", unitLabel:\"kg\", ideal:8.99, qty:1.5 },\n      { id:\"ovos\", name:\"Ovos\", unitLabel:\"d\u00fazias\", ideal:3.29, qty:7 }\n    ],\n    carboidratos: [\n      { id:\"arroz\", name:\"Arroz\", unitLabel:\"kg\", ideal:1.49, qty:2.5 },\n      { id:\"massa\", name:\"Massa (macarr\u00e3o)\", unitLabel:\"kg\", ideal:1.39, qty:2 },\n      { id:\"aveia\", name:\"Aveia em flocos\", unitLabel:\"kg\", ideal:1.99, qty:1.5 },\n      { id:\"batata\", name:\"Batata\", unitLabel:\"kg\", ideal:1.29, qty:2 },\n      { id:\"pao-integral\", name:\"P\u00e3o integral\", unitLabel:\"embalagens\", ideal:1.79, qty:3 }\n    ],\n    frutas: [\n      { id:\"banana\", name:\"Banana\", unitLabel:\"kg\", ideal:1.29, qty:5 },\n      { id:\"maca\", name:\"Ma\u00e7\u00e3\", unitLabel:\"kg\", ideal:1.79, qty:3 },\n      { id:\"laranja\", name:\"Laranja\", unitLabel:\"kg\", ideal:1.49, qty:2.5 },\n      { id:\"frutos-vermelhos\", name:\"Frutos vermelhos\", unitLabel:\"caixas (125g)\", ideal:2.99, qty:4 },\n      { id:\"kiwi\", name:\"Kiwi\", unitLabel:\"kg\", ideal:2.49, qty:1.5 }\n    ],\n    outros: [\n      { id:\"azeite\", name:\"Azeite virgem extra\", unitLabel:\"litros\", ideal:6.49, qty:0.6 },\n      { id:\"sal\", name:\"Sal marinho\", unitLabel:\"embalagens (1kg)\", ideal:0.79, qty:0.15 },\n      { id:\"mel\", name:\"Mel\", unitLabel:\"embalagens (500g)\", ideal:3.99, qty:0.5 },\n      { id:\"limpeza-superficies\", name:\"Creme de limpeza de superf\u00edcies (tipo Cif)\", unitLabel:\"unidades\", ideal:2.99, qty:0.5 }\n    ],\n    receitas: [\n      { id:\"tartar-atum\", name:\"Atum fresco (grau sushi) \u2014 Tartar de atum\", unitLabel:\"kg\", ideal:28.00, qty:0.3, qtyByQuinzena:{ q1:0.3, q2:0 } },\n      { id:\"tartar-lima\", name:\"Lima \u2014 Tartar de atum\", unitLabel:\"unidades\", ideal:0.50, qty:2, qtyByQuinzena:{ q1:2, q2:0 } },\n      { id:\"tartar-gengibre\", name:\"Gengibre fresco (raiz) \u2014 Tartar de atum\", unitLabel:\"unidades\", ideal:1.20, qty:1, qtyByQuinzena:{ q1:1, q2:0 } },\n      { id:\"tartar-cebolinho\", name:\"Cebolinho fresco \u2014 Tartar de atum\", unitLabel:\"molhos\", ideal:0.99, qty:1, qtyByQuinzena:{ q1:1, q2:0 } },\n      { id:\"tartar-sesamo\", name:\"Sementes de s\u00e9samo \u2014 Tartar de atum\", unitLabel:\"embalagens (50g)\", ideal:1.49, qty:1, qtyByQuinzena:{ q1:1, q2:0 } },\n      { id:\"tartar-soja\", name:\"Molho de soja \u2014 Tartar de atum\", unitLabel:\"garrafas (150ml)\", ideal:1.99, qty:1, qtyByQuinzena:{ q1:1, q2:0 } },\n      { id:\"tartar-abacate\", name:\"Abacate \u2014 Tartar de atum\", unitLabel:\"unidades\", ideal:1.29, qty:1, qtyByQuinzena:{ q1:1, q2:0 } },\n      { id:\"ceviche-peixe\", name:\"Peixe branco fresco (robalo\/corvina) \u2014 Ceviche\", unitLabel:\"kg\", ideal:11.99, qty:0.4, qtyByQuinzena:{ q1:0, q2:0.4 } },\n      { id:\"ceviche-lima\", name:\"Lima \u2014 Ceviche\", unitLabel:\"unidades\", ideal:0.50, qty:4, qtyByQuinzena:{ q1:0, q2:4 } },\n      { id:\"ceviche-cebola-roxa\", name:\"Cebola roxa \u2014 Ceviche\", unitLabel:\"unidades\", ideal:0.79, qty:1, qtyByQuinzena:{ q1:0, q2:1 } },\n      { id:\"ceviche-coentros\", name:\"Coentros frescos \u2014 Ceviche\", unitLabel:\"molhos\", ideal:0.89, qty:1, qtyByQuinzena:{ q1:0, q2:1 } },\n      { id:\"ceviche-malagueta\", name:\"Malagueta\/pimenta fresca \u2014 Ceviche\", unitLabel:\"embalagens\", ideal:0.99, qty:1, qtyByQuinzena:{ q1:0, q2:1 } },\n      { id:\"ceviche-milho\", name:\"Milho doce em gr\u00e3o (acompanhamento) \u2014 Ceviche\", unitLabel:\"latas\", ideal:0.99, qty:1, qtyByQuinzena:{ q1:0, q2:1 } },\n      { id:\"tropeiro-feijao\", name:\"Feij\u00e3o carioca \u2014 Feij\u00e3o tropeiro\", unitLabel:\"embalagens (500g)\", ideal:1.99, qty:1, qtyByQuinzena:{ q1:0, q2:1 } },\n      { id:\"tropeiro-bacon\", name:\"Bacon em cubos \u2014 Feij\u00e3o tropeiro\", unitLabel:\"embalagens (200g)\", ideal:2.49, qty:1, qtyByQuinzena:{ q1:0, q2:1 } },\n      { id:\"tropeiro-linguica\", name:\"Lingui\u00e7a calabresa \u2014 Feij\u00e3o tropeiro\", unitLabel:\"embalagens (300g)\", ideal:3.99, qty:1, qtyByQuinzena:{ q1:0, q2:1 } },\n      { id:\"tropeiro-farinha-mandioca\", name:\"Farinha de mandioca \u2014 Feij\u00e3o tropeiro\", unitLabel:\"embalagens (500g)\", ideal:2.99, qty:1, qtyByQuinzena:{ q1:0, q2:1 } },\n      { id:\"tropeiro-couve\", name:\"Couve galega\/portuguesa \u2014 Feij\u00e3o tropeiro\", unitLabel:\"ma\u00e7os\", ideal:0.99, qty:1, qtyByQuinzena:{ q1:0, q2:1 } },\n      { id:\"tropeiro-alho\", name:\"Alho (cabe\u00e7a) \u2014 Feij\u00e3o tropeiro\", unitLabel:\"unidades\", ideal:0.59, qty:1, qtyByQuinzena:{ q1:0, q2:1 } }\n    ]\n  };\n\n  const QUINZENAS = [\n    { key:\"q1\", label:\"Quinzena 1\", range:\"dias 1\u201315\" },\n    { key:\"q2\", label:\"Quinzena 2\", range:\"dias 16\u201330\" }\n  ];\n  const STORAGE_KEY = \"compra-mes:state-v3\";\n\n  let state = {};\n  let items = JSON.parse(JSON.stringify(DEFAULT_ITEMS));\n  let extraCounter = 0;\n\n  function fmt(n){ return (isNaN(n)?0:n).toLocaleString('pt-PT', {minimumFractionDigits:2, maximumFractionDigits:2}) + \"\u20ac\"; }\n  function key(itemId, qkey){ return itemId + \"__\" + qkey; }\n  \/\/ Para a maioria dos itens a quantidade default \u00e9 igual nas duas quinzenas.\n  \/\/ Itens de receitas pontuais (feitas s\u00f3 numa quinzena) definem qtyByQuinzena\n  \/\/ com um valor diferente para q1\/q2 (normalmente 0 na quinzena em que n\u00e3o se cozinha).\n  function defQty(item, qkey){\n    if(item.qtyByQuinzena && item.qtyByQuinzena[qkey] != null) return item.qtyByQuinzena[qkey];\n    return item.qty;\n  }\n\n  function getEntry(itemId, qkey, defaultQty){\n    const k = key(itemId, qkey);\n    if(!state[k]) state[k] = { checked:false, paid:null, qty: defaultQty };\n    if(state[k].qty == null) state[k].qty = defaultQty;\n    return state[k];\n  }\n\n  function findItem(id){\n    for(const cat of CATEGORIES){\n      const found = items[cat.key].find(i=>i.id===id);\n      if(found) return found;\n    }\n    return null;\n  }\n\n  function loadState(){\n    try{\n      const raw = window.localStorage.getItem(STORAGE_KEY);\n      if(raw){\n        const parsed = JSON.parse(raw);\n        if(parsed.state) state = parsed.state;\n        if(parsed.extraItems){\n          CATEGORIES.forEach(cat=>{\n            items[cat.key] = items[cat.key].concat((parsed.extraItems[cat.key] || []));\n          });\n        }\n      }\n    }catch(e){ console.warn(\"N\u00e3o foi poss\u00edvel carregar o estado guardado:\", e); }\n    render();\n  }\n\n  let saveTimer = null;\n  function saveState(){\n    clearTimeout(saveTimer);\n    saveTimer = setTimeout(function(){\n      try{\n        const extraItems = {};\n        CATEGORIES.forEach(cat=>{ extraItems[cat.key] = items[cat.key].filter(i => i.id.startsWith(\"extra-\")); });\n        window.localStorage.setItem(STORAGE_KEY, JSON.stringify({ state, extraItems }));\n      }catch(e){ console.error(\"N\u00e3o foi poss\u00edvel guardar:\", e); }\n    }, 250);\n  }\n\n  function statusFor(estCost, paid){\n    if(paid == null || isNaN(paid) || estCost <= 0) return null;\n    const ratio = paid \/ estCost;\n    if(ratio <= 1.05) return { cls:\"good\", label:\"\u2713 dentro do estimado\" };\n    if(ratio <= 1.25) return { cls:\"warn\", label:\"\u26a0 um pouco acima do estimado\" };\n    return { cls:\"bad\", label:\"\u2715 bem acima do estimado\" };\n  }\n\n  function buildQuinzenaSections(){\n    const container = document.getElementById(\"quinzenas\");\n    container.innerHTML = \"\";\n    QUINZENAS.forEach(q=>{\n      const section = document.createElement(\"div\");\n      section.className = \"quinzena\";\n      let catsHtml = \"\";\n      CATEGORIES.forEach(cat=>{\n        const listKey = cat.key + \"-\" + q.key;\n        catsHtml += `\n          <section class=\"category\" data-cat=\"${cat.key}\" data-q=\"${q.key}\">\n            <h3>${cat.label} <span class=\"count\" data-count=\"${listKey}\">0\/0<\/span><\/h3>\n            <ul class=\"items\" data-list=\"${listKey}\"><\/ul>\n            <div class=\"add-row\">\n              <button class=\"add-toggle\" data-toggle=\"${listKey}\" type=\"button\">+ adicionar item<\/button>\n              <div class=\"add-form\" data-form=\"${listKey}\">\n                <input type=\"text\" placeholder=\"nome\" data-newname=\"${listKey}\">\n                <input type=\"text\" placeholder=\"qtd\" data-newqty=\"${listKey}\">\n                <input type=\"text\" placeholder=\"pre\u00e7o ideal (\u20ac)\" data-newprice=\"${listKey}\">\n                <button type=\"button\" data-addbtn=\"${listKey}\" data-cat=\"${cat.key}\" data-q=\"${q.key}\">Add<\/button>\n              <\/div>\n            <\/div>\n          <\/section>`;\n      });\n      section.innerHTML = `\n        <div class=\"quinzena-head\"><h2>\ud83d\uddd3\ufe0f ${q.label}<\/h2><span>${q.range}<\/span><\/div>\n        ${catsHtml}\n      `;\n      container.appendChild(section);\n    });\n  }\n\n  function renderList(catKey, qkey){\n    const listKey = catKey + \"-\" + qkey;\n    const ul = document.querySelector('[data-list=\"'+listKey+'\"]');\n    if(!ul) return;\n    ul.innerHTML = \"\";\n    items[catKey].forEach(item => {\n      const entry = getEntry(item.id, qkey, defQty(item, qkey));\n      const estCost = (entry.qty || 0) * item.ideal;\n      const st = statusFor(estCost, entry.paid);\n      const li = document.createElement(\"li\");\n      li.className = \"item\" + (entry.checked ? \" checked\" : \"\");\n      li.dataset.id = item.id; li.dataset.q = qkey;\n      li.innerHTML = `\n        <label class=\"check\">\n          <input type=\"checkbox\" data-id=\"${item.id}\" data-q=\"${qkey}\" ${entry.checked ? \"checked\" : \"\"}>\n          <span class=\"box\"><svg width=\"11\" height=\"9\" viewBox=\"0 0 12 10\" fill=\"none\"><path d=\"M1 5L4.5 8.5L11 1.5\" stroke=\"white\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg><\/span>\n        <\/label>\n        <div class=\"info\">\n          <span class=\"name\">${item.name}<\/span>\n          <span class=\"unit\">${item.unitLabel} \u00b7 ${fmt(item.ideal)}\/${item.unitLabel.replace(\/s$\/,'').replace('unidade','un')}<\/span>\n        <\/div>\n        <div class=\"qty-wrap\">\n          <input type=\"number\" step=\"0.1\" min=\"0\" value=\"${entry.qty}\" data-qty=\"${item.id}\" data-q=\"${qkey}\">\n          <span class=\"qtylabel\">${item.unitLabel}<\/span>\n        <\/div>\n        <div class=\"estcost\">est. <strong data-estcost=\"${item.id}-${qkey}\">${fmt(estCost)}<\/strong><\/div>\n        <div class=\"paid ${st ? st.cls : ''}\">\n          <span>\u20ac<\/span>\n          <input type=\"number\" inputmode=\"decimal\" step=\"0.01\" min=\"0\" placeholder=\"0,00\" data-paid=\"${item.id}\" data-q=\"${qkey}\" value=\"${entry.paid != null ? entry.paid : ''}\">\n        <\/div>\n        <div class=\"status-pill ${st ? st.cls + ' show' : ''}\">${st ? st.label : ''}<\/div>\n      `;\n      ul.appendChild(li);\n    });\n    const checkedCount = items[catKey].filter(i => getEntry(i.id, qkey, defQty(i, qkey)).checked).length;\n    const countEl = document.querySelector('[data-count=\"'+listKey+'\"]');\n    if(countEl) countEl.textContent = checkedCount + \"\/\" + items[catKey].length;\n  }\n\n  function computeEstimates(){\n    const totals = {};\n    CATEGORIES.forEach(cat=>{\n      let sum = 0;\n      QUINZENAS.forEach(q=>{\n        items[cat.key].forEach(i=>{ sum += getEntry(i.id, q.key, defQty(i, q.key)).qty * i.ideal; });\n      });\n      totals[cat.key] = sum;\n    });\n    const month = Object.values(totals).reduce((a,b)=>a+b,0);\n    document.getElementById(\"monthEstimate\").textContent = fmt(month);\n    document.getElementById(\"fortnightEstimate\").textContent = fmt(month \/ 2);\n    document.getElementById(\"estCarnes\").textContent = fmt(totals.carnes);\n    document.getElementById(\"estLegumes\").textContent = fmt(totals.legumes);\n    document.getElementById(\"estCarboidratos\").textContent = fmt(totals.carboidratos);\n    document.getElementById(\"estFrutas\").textContent = fmt(totals.frutas);\n    document.getElementById(\"estOutros\").textContent = fmt(totals.outros);\n    document.getElementById(\"estReceitas\").textContent = fmt(totals.receitas);\n  }\n\n  function renderReceipt(){\n    let paidSum = 0, idealSum = 0, count = 0;\n    QUINZENAS.forEach(q=>{\n      CATEGORIES.forEach(cat=>{\n        items[cat.key].forEach(item=>{\n          const entry = getEntry(item.id, q.key, defQty(item, q.key));\n          if(entry.checked){\n            count++;\n            idealSum += (entry.qty || 0) * item.ideal;\n            if(entry.paid != null && !isNaN(entry.paid)) paidSum += entry.paid;\n          }\n        });\n      });\n    });\n    document.getElementById(\"itemCount\").textContent = count + (count === 1 ? \" item\" : \" itens\");\n    document.getElementById(\"idealSum\").textContent = fmt(idealSum);\n    document.getElementById(\"paidSum\").textContent = fmt(paidSum);\n    const diff = idealSum - paidSum;\n    const diffEl = document.getElementById(\"diffVal\");\n    if(count === 0){ diffEl.textContent = \"\u2014\"; diffEl.className = \"\"; }\n    else if(diff >= 0){ diffEl.textContent = \"poupou \" + fmt(diff); diffEl.className = \"diff-good\"; }\n    else { diffEl.textContent = \"+\" + fmt(Math.abs(diff)) + \" acima\"; diffEl.className = \"diff-bad\"; }\n  }\n\n  function render(){\n    QUINZENAS.forEach(q=>{ CATEGORIES.forEach(cat=>{ renderList(cat.key, q.key); }); });\n    computeEstimates();\n    renderReceipt();\n  }\n\n  document.body.addEventListener(\"click\", e=>{\n    const toggleBtn = e.target.closest(\"[data-toggle]\");\n    if(toggleBtn){\n      document.querySelector('[data-form=\"'+toggleBtn.dataset.toggle+'\"]').classList.toggle(\"show\");\n      return;\n    }\n    const addBtn = e.target.closest(\"[data-addbtn]\");\n    if(addBtn){\n      const catKey = addBtn.dataset.cat, qkey = addBtn.dataset.q;\n      const listKey = catKey + \"-\" + qkey;\n      const nameInput = document.querySelector('[data-newname=\"'+listKey+'\"]');\n      const qtyInput = document.querySelector('[data-newqty=\"'+listKey+'\"]');\n      const priceInput = document.querySelector('[data-newprice=\"'+listKey+'\"]');\n      const name = nameInput.value.trim();\n      const qty = parseFloat((qtyInput.value || \"1\").replace(\",\", \".\")) || 1;\n      const price = parseFloat((priceInput.value || \"0\").replace(\",\", \".\")) || 0;\n      if(!name) return;\n      extraCounter++;\n      const id = \"extra-\" + catKey + \"-\" + extraCounter + \"-\" + Date.now();\n      items[catKey].push({ id, name, unitLabel:\"un.\", ideal: price, qty: qty });\n      nameInput.value = \"\"; qtyInput.value = \"\"; priceInput.value = \"\";\n      render(); saveState();\n    }\n  });\n\n  document.body.addEventListener(\"change\", e=>{\n    if(e.target.matches('input[type=\"checkbox\"][data-id]')){\n      const id = e.target.dataset.id, qkey = e.target.dataset.q;\n      const item = findItem(id);\n      getEntry(id, qkey, defQty(item, qkey)).checked = e.target.checked;\n      render(); saveState();\n    }\n  });\n\n  document.body.addEventListener(\"input\", e=>{\n    if(e.target.matches('input[data-qty]')){\n      const id = e.target.dataset.qty, qkey = e.target.dataset.q;\n      const item = findItem(id);\n      const val = parseFloat(e.target.value.replace(\",\", \".\")) || 0;\n      getEntry(id, qkey, defQty(item, qkey)).qty = val;\n      const estCost = val * item.ideal;\n      const estEl = document.querySelector('[data-estcost=\"'+id+'-'+qkey+'\"]');\n      if(estEl) estEl.textContent = fmt(estCost);\n      computeEstimates(); renderReceipt(); saveState();\n    }\n    if(e.target.matches('input[data-paid]')){\n      const id = e.target.dataset.paid, qkey = e.target.dataset.q;\n      const item = findItem(id);\n      const val = e.target.value === \"\" ? null : parseFloat(e.target.value.replace(\",\", \".\"));\n      const entry = getEntry(id, qkey, defQty(item, qkey));\n      entry.paid = val;\n      const estCost = (entry.qty || 0) * item.ideal;\n      const st = statusFor(estCost, val);\n      const wrapper = e.target.closest(\".paid\");\n      wrapper.className = \"paid\" + (st ? \" \" + st.cls : \"\");\n      const li = e.target.closest(\".item\");\n      const pill = li.querySelector(\".status-pill\");\n      if(st){ pill.textContent = st.label; pill.className = \"status-pill show \" + st.cls; }\n      else { pill.textContent = \"\"; pill.className = \"status-pill\"; }\n      renderReceipt(); saveState();\n    }\n  });\n\n  document.getElementById(\"resetBtn\").addEventListener(\"click\", async ()=>{\n    if(!confirm(\"Limpar todas as marca\u00e7\u00f5es e valores pagos (mant\u00e9m quantidades e pre\u00e7os ideais)?\")) return;\n    Object.keys(state).forEach(k=>{ state[k].checked = false; state[k].paid = null; });\n    render(); saveState();\n  });\n\n  buildQuinzenaSections();\n  loadState();\n})();\n<\/script>\n<\/body>\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-10324aa e-flex e-con-boxed e-con e-parent\" data-id=\"10324aa\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-54a046a elementor-widget elementor-widget-html\" data-id=\"54a046a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!-- ============================================================\n     KIKI STAT \u2014 bloco de Footer para o widget HTML do Elementor\n     Como usar: arrasta um widget \"HTML\" para a p\u00e1gina (ou para o\n     template de Footer no Theme Builder) e cola este c\u00f3digo\n     inteiro dentro dele.\n     Troca os href pelos URLs reais assim que tiveres todas as\n     p\u00e1ginas prontas \u2014 os que j\u00e1 t\u00eam p\u00e1gina real est\u00e3o preenchidos.\n     ============================================================ -->\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Oswald:wght@500;600;700&family=Inter:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500;600&display=swap\" rel=\"stylesheet\">\n\n<style>\n  .kks-footer{\n    --kksf-bg: #1b2b22;\n    --kksf-bg-soft: #16221b;\n    --kksf-paper-soft: #fbf8f1;\n    --kksf-accent: #e8a33d;\n    --kksf-line: rgba(244,239,227,0.14);\n    --kksf-text: rgba(244,239,227,0.72);\n    box-sizing: border-box;\n    font-family:'Inter', sans-serif;\n    background: var(--kksf-bg-soft);\n    border-top: 1px solid var(--kksf-line);\n    color: var(--kksf-text);\n  }\n  .kks-footer *{ box-sizing: border-box; }\n\n  .kks-footer-inner{\n    max-width: 1200px; margin: 0 auto;\n    padding: 40px 20px 24px;\n    display:grid;\n    grid-template-columns: 1.4fr 1fr 1fr;\n    gap: 28px;\n  }\n\n  .kks-footer-brand .kks-logo{\n    font-family:'Oswald', sans-serif; font-weight:700; font-size:22px;\n    letter-spacing:.04em; color: var(--kksf-paper-soft); text-decoration:none;\n    display:inline-flex; align-items:baseline; gap:2px;\n  }\n  .kks-footer-brand .kks-logo span{ color: var(--kksf-accent); }\n  .kks-footer-brand p{\n    margin: 10px 0 0; font-size: 13px; line-height:1.6; max-width: 280px;\n    color: var(--kksf-text);\n  }\n\n  .kks-footer-col h4{\n    font-family:'IBM Plex Mono', monospace; font-size: 11px; letter-spacing:.1em;\n    text-transform: uppercase; color: var(--kksf-accent); margin: 0 0 12px;\n  }\n  .kks-footer-col ul{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:9px; }\n  .kks-footer-col a{\n    font-size: 13.5px; color: var(--kksf-text); text-decoration:none;\n    transition: color .15s ease, padding-left .15s ease;\n    display:inline-block;\n  }\n  .kks-footer-col a:hover, .kks-footer-col a:focus-visible{\n    color: var(--kksf-accent); padding-left: 3px; outline:none;\n  }\n  .kks-footer-col span.kks-soon{\n    font-size: 13.5px; color: rgba(244,239,227,0.4);\n  }\n  .kks-footer-col span.kks-soon::after{\n    content: \" (brevemente)\"; font-size: 11px;\n  }\n\n  .kks-footer-bottom{\n    border-top: 1px solid var(--kksf-line);\n    padding: 16px 20px;\n  }\n  .kks-footer-bottom-inner{\n    max-width: 1200px; margin: 0 auto;\n    display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:10px;\n  }\n  .kks-footer-bottom-inner p{\n    margin:0; font-family:'IBM Plex Mono', monospace; font-size: 11.5px;\n    color: rgba(244,239,227,0.45);\n  }\n\n  @media (max-width: 760px){\n    .kks-footer-inner{ grid-template-columns: 1fr 1fr; }\n    .kks-footer-brand{ grid-column: 1 \/ -1; }\n  }\n  @media (max-width: 460px){\n    .kks-footer-inner{ grid-template-columns: 1fr; }\n  }\n  @media (prefers-reduced-motion: reduce){ .kks-footer *{ transition:none !important; } }\n<\/style>\n\n<footer class=\"kks-footer\">\n  <div class=\"kks-footer-inner\">\n    <div class=\"kks-footer-brand\">\n      <a href=\"\/\" class=\"kks-logo\">KIKI<span>STAT<\/span><\/a>\n      <p>Painel de organiza\u00e7\u00e3o do dia a dia: compras do m\u00eas, limpeza da casa, h\u00e1bitos e estudo \u2014 tudo num s\u00f3 s\u00edtio.<\/p>\n    <\/div>\n\n    <div class=\"kks-footer-col\">\n      <h4>Compra do M\u00eas<\/h4>\n      <ul>\n        <li><a href=\"https:\/\/kikistationary.pt\/?page_id=250\">Casal<\/a><\/li>\n        <li><a href=\"https:\/\/kikistationary.pt\/?page_id=318\">Individual 2000kcal<\/a><\/li>\n        <li><a href=\"https:\/\/kikistationary.pt\/?page_id=309\">Individual 3000kcal<\/a><\/li>\n      <\/ul>\n    <\/div>\n\n    <div class=\"kks-footer-col\">\n      <h4>Rotina<\/h4>\n      <ul>\n        <li><a href=\"https:\/\/kikistationary.pt\/?page_id=286\">Limpeza da Casa<\/a><\/li>\n        <li><a href=\"https:\/\/kikistationary.pt\/?page_id=244\">Habit Tracker<\/a><\/li>\n        <li><span class=\"kks-soon\">Estudo<\/span><\/li>\n      <\/ul>\n    <\/div>\n  <\/div>\n\n  <div class=\"kks-footer-bottom\">\n    <div class=\"kks-footer-bottom-inner\">\n      <p>&copy; <span id=\"kksYear\"><\/span> Kiki Stationary \u2014 Kiki Stat<\/p>\n      <p>Feito com carinho para organizar o dia a dia<\/p>\n    <\/div>\n  <\/div>\n<\/footer>\n\n<script>\n(function(){\n  var yearEl = document.getElementById('kksYear');\n  if(yearEl) yearEl.textContent = new Date().getFullYear();\n})();\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>KIKISTAT Compra do M\u00eas \u25be Casal Individual 2000kcal Individual 3000kcal Limpeza da Casa Habit Tracker Compra do M\u00eas \u25be Casal Individual 2000kcal Individual 3000kcal Limpeza da Casa Habit Tracker Estudo Compra do M\u00eas \u2014 Talho &#038; Horta Talho, Horta &amp; Despensa \u00b7 Casal Fitness Compra do M\u00eas Dividida em 2 quinzenas para os frescos n\u00e3o [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"footnotes":""},"class_list":["post-318","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/kikistationary.pt\/index.php?rest_route=\/wp\/v2\/pages\/318","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kikistationary.pt\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/kikistationary.pt\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/kikistationary.pt\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kikistationary.pt\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=318"}],"version-history":[{"count":31,"href":"https:\/\/kikistationary.pt\/index.php?rest_route=\/wp\/v2\/pages\/318\/revisions"}],"predecessor-version":[{"id":432,"href":"https:\/\/kikistationary.pt\/index.php?rest_route=\/wp\/v2\/pages\/318\/revisions\/432"}],"wp:attachment":[{"href":"https:\/\/kikistationary.pt\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=318"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}