{"id":7,"date":"2026-05-04T02:44:26","date_gmt":"2026-05-04T02:44:26","guid":{"rendered":"https:\/\/owner-portal.rotibakarngeunah.my.id\/?page_id=7"},"modified":"2026-05-04T05:58:28","modified_gmt":"2026-05-04T05:58:28","slug":"beranda","status":"publish","type":"page","link":"https:\/\/owner-portal.rotibakarngeunah.my.id\/","title":{"rendered":"Beranda"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"7\" class=\"elementor elementor-7\">\n\t\t\t\t<div class=\"elementor-element elementor-element-0ba1b89 e-con-full e-flex e-con e-parent\" data-id=\"0ba1b89\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-9cf5bd2 elementor-widget elementor-widget-html\" data-id=\"9cf5bd2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"id\">\r\n<head>\r\n  <meta charset=\"UTF-8\"\/>\r\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\"\/>\r\n  <title>Roti Bakar Ngeunah \u2013 Owner Portal<\/title>\r\n  <link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\"\/>\r\n  <link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin\/>\r\n  <link href=\"https:\/\/fonts.googleapis.com\/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap\" rel=\"stylesheet\"\/>\r\n  <link rel=\"preload\" as=\"image\" href=\"https:\/\/res.cloudinary.com\/dckzmg6c3\/image\/upload\/f_auto,q_auto,w_96\/v1777572835\/Untitled-2_tgjm4u.png\"\/>\r\n  <link rel=\"icon\" type=\"image\/png\" href=\"https:\/\/res.cloudinary.com\/dckzmg6c3\/image\/upload\/v1777572835\/Untitled-2_tgjm4u.png\"\/>\r\n\r\n  <style>\r\n    :root{\r\n      --red:#C8202B;\r\n      --red-soft:#FDECEA;\r\n      --orange:#F0681A;\r\n      --org-soft:#FEF0E8;\r\n      --yellow:#F6B800;\r\n      --yel-soft:#FEF8E0;\r\n      --green:#1A8A3C;\r\n      --grn-soft:#E8F5ED;\r\n      --blue:#1A5FA8;\r\n      --blu-soft:#E8F0FB;\r\n      --purple:#6B3FA0;\r\n      --pur-soft:#F0EAF9;\r\n      --teal:#0D7D72;\r\n      --tel-soft:#E5F5F3;\r\n      --bg:#FFF8F2;\r\n      --surface:#FFFFFF;\r\n      --border:#F0DDD0;\r\n      --text:#1C0A00;\r\n      --muted:#9B7060;\r\n    }\r\n\r\n    *,*::before,*::after{\r\n      box-sizing:border-box;\r\n      margin:0;\r\n      padding:0;\r\n    }\r\n\r\n    html{\r\n      height:100%;\r\n      overflow:hidden;\r\n      touch-action:none;\r\n    }\r\n\r\n    body{\r\n      height:100%;\r\n      overflow-y:auto;\r\n      overflow-x:hidden;\r\n      -webkit-overflow-scrolling:touch;\r\n      touch-action:pan-y;\r\n      font-family:'Plus Jakarta Sans',sans-serif;\r\n      background:var(--bg);\r\n      color:var(--text);\r\n      -webkit-text-size-adjust:100%;\r\n      \/* Prevent text selection *\/\r\n      -webkit-user-select:none;\r\n      -moz-user-select:none;\r\n      -ms-user-select:none;\r\n      user-select:none;\r\n    }\r\n\r\n    \/* \u2500\u2500 PASSWORD GATE \u2500\u2500 *\/\r\n    #gate{\r\n      position:fixed;\r\n      inset:0;\r\n      z-index:9999;\r\n      background:linear-gradient(135deg,#1C0A00 0%,#3B1509 50%,#1C0A00 100%);\r\n      display:flex;\r\n      flex-direction:column;\r\n      align-items:center;\r\n      justify-content:center;\r\n      padding:24px;\r\n    }\r\n\r\n    #gate .gate-logo{\r\n      width:76px;\r\n      height:76px;\r\n      border-radius:50%;\r\n      background:#fff;\r\n      display:grid;\r\n      place-items:center;\r\n      box-shadow:0 0 0 3px var(--orange), 0 0 0 6px rgba(240,104,26,.25);\r\n      overflow:hidden;\r\n      margin-bottom:20px;\r\n    }\r\n\r\n    #gate .gate-logo img{\r\n      width:70px;\r\n      height:70px;\r\n      border-radius:50%;\r\n      object-fit:contain;\r\n    }\r\n\r\n    #gate h1{\r\n      font-size:1.4rem;\r\n      font-weight:800;\r\n      color:#fff;\r\n      letter-spacing:-0.3px;\r\n      text-align:center;\r\n      line-height:1.2;\r\n    }\r\n\r\n    #gate h1 span{ color:var(--orange); }\r\n\r\n    #gate p{\r\n      margin-top:6px;\r\n      font-size:.68rem;\r\n      font-weight:700;\r\n      letter-spacing:3px;\r\n      text-transform:uppercase;\r\n      color:rgba(255,255,255,.45);\r\n      text-align:center;\r\n    }\r\n\r\n    #gate .gate-card{\r\n      margin-top:28px;\r\n      background:rgba(255,255,255,.06);\r\n      border:1.5px solid rgba(255,255,255,.12);\r\n      border-radius:18px;\r\n      padding:24px 22px;\r\n      width:100%;\r\n      max-width:340px;\r\n    }\r\n\r\n    #gate .gate-label{\r\n      font-size:.68rem;\r\n      font-weight:700;\r\n      letter-spacing:2px;\r\n      text-transform:uppercase;\r\n      color:rgba(255,255,255,.5);\r\n      margin-bottom:10px;\r\n    }\r\n\r\n    #gate .input-wrap{\r\n      position:relative;\r\n    }\r\n\r\n    #gate input[type=\"password\"]{\r\n      width:100%;\r\n      padding:13px 44px 13px 14px;\r\n      border-radius:11px;\r\n      border:1.5px solid rgba(255,255,255,.15);\r\n      background:rgba(255,255,255,.08);\r\n      color:#fff;\r\n      font-family:inherit;\r\n      font-size:.95rem;\r\n      font-weight:600;\r\n      letter-spacing:3px;\r\n      outline:none;\r\n      transition:border-color .2s;\r\n      -webkit-text-security:disc;\r\n    }\r\n\r\n    #gate input[type=\"password\"]::placeholder{\r\n      color:rgba(255,255,255,.25);\r\n      letter-spacing:1px;\r\n    }\r\n\r\n    #gate input[type=\"password\"]:focus{\r\n      border-color:var(--orange);\r\n    }\r\n\r\n    #gate .toggle-pw{\r\n      position:absolute;\r\n      right:12px;\r\n      top:50%;\r\n      transform:translateY(-50%);\r\n      background:none;\r\n      border:none;\r\n      cursor:pointer;\r\n      color:rgba(255,255,255,.4);\r\n      font-size:1rem;\r\n      padding:4px;\r\n      line-height:1;\r\n    }\r\n\r\n    #gate .btn-login{\r\n      margin-top:12px;\r\n      width:100%;\r\n      padding:13px;\r\n      border-radius:11px;\r\n      border:none;\r\n      background:linear-gradient(135deg,var(--red),var(--orange));\r\n      color:#fff;\r\n      font-family:inherit;\r\n      font-size:.92rem;\r\n      font-weight:800;\r\n      letter-spacing:.5px;\r\n      cursor:pointer;\r\n      transition:opacity .2s, transform .15s;\r\n    }\r\n\r\n    #gate .btn-login:active{\r\n      transform:scale(.97);\r\n      opacity:.9;\r\n    }\r\n\r\n    #gate .gate-error{\r\n      margin-top:10px;\r\n      font-size:.72rem;\r\n      font-weight:700;\r\n      color:#FF7070;\r\n      text-align:center;\r\n      min-height:18px;\r\n      transition:opacity .2s;\r\n    }\r\n\r\n    #gate .gate-error.hidden{\r\n      opacity:0;\r\n    }\r\n\r\n    #gate .gate-attempts{\r\n      margin-top:6px;\r\n      font-size:.65rem;\r\n      color:rgba(255,255,255,.3);\r\n      text-align:center;\r\n      min-height:16px;\r\n    }\r\n\r\n    \/* Lockout overlay *\/\r\n    #lockout-msg{\r\n      display:none;\r\n      margin-top:14px;\r\n      background:rgba(200,32,43,.15);\r\n      border:1px solid rgba(200,32,43,.4);\r\n      border-radius:10px;\r\n      padding:12px 14px;\r\n      font-size:.75rem;\r\n      color:#FF9090;\r\n      text-align:center;\r\n      line-height:1.5;\r\n    }\r\n\r\n    \/* \u2500\u2500 MAIN CONTENT (hidden until auth) \u2500\u2500 *\/\r\n    #app{\r\n      display:none;\r\n    }\r\n\r\n    .page{\r\n      min-height:100%;\r\n      display:flex;\r\n      flex-direction:column;\r\n      align-items:center;\r\n      padding:40px 16px 56px;\r\n      max-width:420px;\r\n      margin:0 auto;\r\n      width:100%;\r\n    }\r\n\r\n    .logo-wrap{\r\n      width:88px;\r\n      height:88px;\r\n      border-radius:50%;\r\n      background:#fff;\r\n      display:grid;\r\n      place-items:center;\r\n      flex-shrink:0;\r\n      box-shadow:\r\n        0 0 0 3px var(--orange),\r\n        0 0 0 6px rgba(240,104,26,.15);\r\n      position:relative;\r\n      overflow:hidden;\r\n    }\r\n\r\n    .logo-fallback{\r\n      position:absolute;\r\n      inset:0;\r\n      display:flex;\r\n      align-items:center;\r\n      justify-content:center;\r\n      background:linear-gradient(135deg,#C8202B,#F0681A);\r\n      border-radius:50%;\r\n      z-index:1;\r\n    }\r\n\r\n    .logo-fallback svg{\r\n      width:48px;\r\n      height:48px;\r\n    }\r\n\r\n    .logo-img{\r\n      width:82px;\r\n      height:82px;\r\n      border-radius:50%;\r\n      object-fit:contain;\r\n      display:block;\r\n      position:relative;\r\n      z-index:2;\r\n      opacity:0;\r\n      transition:opacity .2s ease;\r\n    }\r\n\r\n    .logo-img.loaded{ opacity:1; }\r\n    .logo-img.loaded ~ .logo-fallback{ display:none; }\r\n\r\n    .profile{\r\n      text-align:center;\r\n      margin-top:14px;\r\n    }\r\n\r\n    .profile-name{\r\n      font-size:clamp(1.35rem,5.5vw,1.75rem);\r\n      font-weight:800;\r\n      color:var(--text);\r\n      letter-spacing:-0.5px;\r\n      line-height:1.15;\r\n    }\r\n\r\n    .profile-name span{ color:var(--red); }\r\n\r\n    .profile-sub{\r\n      margin-top:4px;\r\n      font-size:.68rem;\r\n      font-weight:700;\r\n      letter-spacing:3px;\r\n      text-transform:uppercase;\r\n      color:var(--muted);\r\n    }\r\n\r\n    .section-label{\r\n      width:100%;\r\n      font-size:.62rem;\r\n      font-weight:700;\r\n      letter-spacing:2.5px;\r\n      text-transform:uppercase;\r\n      color:var(--muted);\r\n      margin-bottom:6px;\r\n      padding-left:4px;\r\n    }\r\n\r\n    .divider,.divider-sm{\r\n      width:100%;\r\n      height:1px;\r\n      background:linear-gradient(90deg,transparent,var(--border),transparent);\r\n      flex-shrink:0;\r\n    }\r\n\r\n    .divider{ margin:20px 0 16px; }\r\n    .divider-sm{ margin:14px 0 10px; }\r\n\r\n    .links{\r\n      display:flex;\r\n      flex-direction:column;\r\n      gap:8px;\r\n      width:100%;\r\n    }\r\n\r\n    .link-btn{\r\n      position:relative;\r\n      display:flex;\r\n      align-items:center;\r\n      gap:12px;\r\n      text-decoration:none;\r\n      border-radius:14px;\r\n      padding:12px 14px;\r\n      overflow:hidden;\r\n      background:var(--surface);\r\n      border:1.5px solid var(--border);\r\n      -webkit-tap-highlight-color:transparent;\r\n      transition:transform .14s ease,box-shadow .14s ease,border-color .14s ease;\r\n    }\r\n\r\n    .link-btn:active{\r\n      transform:scale(.985);\r\n      box-shadow:0 2px 8px rgba(0,0,0,.08);\r\n      border-color:var(--orange);\r\n    }\r\n\r\n    @media (hover:hover){\r\n      .link-btn:hover{\r\n        transform:translateY(-2px);\r\n        box-shadow:0 6px 20px rgba(0,0,0,.10);\r\n        border-color:var(--orange);\r\n      }\r\n    }\r\n\r\n    .link-btn::before{\r\n      content:'';\r\n      position:absolute;\r\n      left:0;\r\n      top:20%;\r\n      bottom:20%;\r\n      width:3px;\r\n      border-radius:0 3px 3px 0;\r\n      background:var(--accent,var(--orange));\r\n    }\r\n\r\n    .link-icon{\r\n      width:38px;\r\n      height:38px;\r\n      flex-shrink:0;\r\n      border-radius:10px;\r\n      display:grid;\r\n      place-items:center;\r\n      font-size:1.1rem;\r\n      background:var(--icon-bg,var(--org-soft));\r\n    }\r\n\r\n    .link-text{ flex:1; min-width:0; }\r\n\r\n    .link-title{\r\n      font-weight:700;\r\n      font-size:.86rem;\r\n      color:var(--text);\r\n      line-height:1.2;\r\n      white-space:nowrap;\r\n      overflow:hidden;\r\n      text-overflow:ellipsis;\r\n    }\r\n\r\n    .link-desc{\r\n      margin-top:2px;\r\n      font-size:.70rem;\r\n      color:var(--muted);\r\n      line-height:1.4;\r\n      white-space:nowrap;\r\n      overflow:hidden;\r\n      text-overflow:ellipsis;\r\n    }\r\n\r\n    .link-arrow{ color:#D0B8A8; flex-shrink:0; }\r\n\r\n    \/* Session badge *\/\r\n    .session-bar{\r\n      width:100%;\r\n      display:flex;\r\n      align-items:center;\r\n      justify-content:space-between;\r\n      background:var(--grn-soft);\r\n      border:1px solid rgba(26,138,60,.2);\r\n      border-radius:10px;\r\n      padding:7px 12px;\r\n      margin-bottom:4px;\r\n    }\r\n\r\n    .session-bar span{\r\n      font-size:.65rem;\r\n      font-weight:700;\r\n      letter-spacing:1.5px;\r\n      text-transform:uppercase;\r\n      color:var(--green);\r\n    }\r\n\r\n    .btn-logout{\r\n      background:none;\r\n      border:1px solid rgba(200,32,43,.4);\r\n      border-radius:6px;\r\n      color:var(--red);\r\n      font-family:inherit;\r\n      font-size:.62rem;\r\n      font-weight:700;\r\n      letter-spacing:1px;\r\n      text-transform:uppercase;\r\n      padding:3px 8px;\r\n      cursor:pointer;\r\n    }\r\n\r\n    .footer{\r\n      margin-top:28px;\r\n      font-size:.65rem;\r\n      font-weight:500;\r\n      letter-spacing:1.5px;\r\n      text-transform:uppercase;\r\n      color:#C8A898;\r\n      text-align:center;\r\n    }\r\n\r\n    @media (max-height:680px){\r\n      .page{ padding-top:24px; padding-bottom:32px; }\r\n      .logo-wrap{ width:72px; height:72px; }\r\n      .logo-img{ width:66px; height:66px; }\r\n      .divider{ margin:14px 0 10px; }\r\n      .links{ gap:6px; }\r\n      .link-btn{ padding:10px 12px; }\r\n    }\r\n  <\/style>\r\n<\/head>\r\n\r\n<body>\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 PASSWORD GATE \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<div id=\"gate\">\r\n\r\n  <div class=\"gate-logo\">\r\n    <img\r\n      src=\"https:\/\/res.cloudinary.com\/dckzmg6c3\/image\/upload\/f_auto,q_auto,w_96\/v1777572835\/Untitled-2_tgjm4u.png\"\r\n      alt=\"Logo\"\r\n      width=\"70\" height=\"70\"\r\n      decoding=\"async\"\r\n    \/>\r\n  <\/div>\r\n\r\n  <h1>Roti Bakar <span>Ngeunah<\/span><\/h1>\r\n  <p>Owner Portal \u00b7 Akses Terbatas<\/p>\r\n\r\n  <div class=\"gate-card\">\r\n    <div class=\"gate-label\">\ud83d\udd10 Masukkan Password<\/div>\r\n\r\n    <div class=\"input-wrap\">\r\n      <input\r\n        type=\"password\"\r\n        id=\"pw-input\"\r\n        placeholder=\"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\"\r\n        autocomplete=\"off\"\r\n        autocorrect=\"off\"\r\n        autocapitalize=\"off\"\r\n        spellcheck=\"false\"\r\n        maxlength=\"64\"\r\n      \/>\r\n      <button class=\"toggle-pw\" id=\"toggle-pw\" tabindex=\"-1\" aria-label=\"Lihat password\">\ud83d\udc41<\/button>\r\n    <\/div>\r\n\r\n    <button class=\"btn-login\" id=\"btn-login\">Masuk<\/button>\r\n\r\n    <div class=\"gate-error hidden\" id=\"gate-error\">Password salah. Coba lagi.<\/div>\r\n    <div class=\"gate-attempts\" id=\"gate-attempts\"><\/div>\r\n    <div id=\"lockout-msg\"><\/div>\r\n  <\/div>\r\n\r\n<\/div>\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 MAIN APP \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<div id=\"app\">\r\n<div class=\"page\">\r\n\r\n  <!-- Session bar -->\r\n  <div class=\"session-bar\">\r\n    <span>\ud83d\udfe2 Sesi Aktif<\/span>\r\n    <button class=\"btn-logout\" id=\"btn-logout\">Keluar<\/button>\r\n  <\/div>\r\n\r\n  <!-- Logo -->\r\n  <div class=\"logo-wrap\">\r\n    <img\r\n      class=\"logo-img\"\r\n      src=\"https:\/\/res.cloudinary.com\/dckzmg6c3\/image\/upload\/f_auto,q_auto,w_96\/v1777572835\/Untitled-2_tgjm4u.png\"\r\n      alt=\"Roti Bakar Ngeunah\"\r\n      width=\"82\" height=\"82\"\r\n      decoding=\"async\"\r\n    \/>\r\n    <div class=\"logo-fallback\">\r\n      <svg viewBox=\"0 0 48 48\" fill=\"none\">\r\n        <rect x=\"6\" y=\"20\" width=\"36\" height=\"18\" rx=\"9\" fill=\"white\" fill-opacity=\".15\" stroke=\"white\" stroke-width=\"1.5\"\/>\r\n        <path d=\"M8 26 C10 20,14 18,24 18 C34 18,38 20,40 26\" stroke=\"white\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\"\/>\r\n        <path d=\"M12 30 L36 30\" stroke=\"white\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-dasharray=\"3 3\"\/>\r\n      <\/svg>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- Header -->\r\n  <div class=\"profile\">\r\n    <div class=\"profile-name\">Roti Bakar <span>Ngeunah<\/span><\/div>\r\n    <div class=\"profile-sub\">Owner Portal<\/div>\r\n  <\/div>\r\n\r\n  <div class=\"divider\"><\/div>\r\n\r\n  <!-- Keuangan -->\r\n  <div class=\"section-label\">\ud83d\udcca Keuangan<\/div>\r\n  <div class=\"links\">\r\n\r\n    <a class=\"link-btn\" style=\"--accent:#1A8A3C; --icon-bg:#E8F5ED;\"\r\n       href=\"https:\/\/docs.google.com\/spreadsheets\/d\/1LvbAeupHEJLXiawJ3Qf9wTAc40hZi7K1m7wYJWi9a5E\/edit?usp=sharing\"\r\n       target=\"_blank\" rel=\"noopener\">\r\n      <div class=\"link-icon\">\ud83d\udcb0<\/div>\r\n      <div class=\"link-text\">\r\n        <div class=\"link-title\">Business Cashflow<\/div>\r\n        <div class=\"link-desc\">Pantau arus kas dan keuangan bisnis<\/div>\r\n      <\/div>\r\n      <div class=\"link-arrow\">\u203a<\/div>\r\n    <\/a>\r\n\r\n    <a class=\"link-btn\" style=\"--accent:#1A5FA8; --icon-bg:#E8F0FB;\"\r\n       href=\"https:\/\/docs.google.com\/spreadsheets\/d\/1-9cFiGtCFLqw0U_haofKvHxadw5Gc6yL3tSxh9Xp7gI\/edit?usp=sharing\"\r\n       target=\"_blank\" rel=\"noopener\">\r\n      <div class=\"link-icon\">\ud83d\udcc8<\/div>\r\n      <div class=\"link-text\">\r\n        <div class=\"link-title\">Sales Report<\/div>\r\n        <div class=\"link-desc\">Laporan penjualan dan performa outlet<\/div>\r\n      <\/div>\r\n      <div class=\"link-arrow\">\u203a<\/div>\r\n    <\/a>\r\n\r\n    <a class=\"link-btn\" style=\"--accent:#F0681A; --icon-bg:#FEF0E8;\"\r\n       href=\"https:\/\/docs.google.com\/spreadsheets\/d\/1oHU45mpFkx3uJr8RDVi3IDqPNFNgej8pVW1I3wJFOjs\/edit?usp=sharing\"\r\n       target=\"_blank\" rel=\"noopener\">\r\n      <div class=\"link-icon\">\ud83d\udccb<\/div>\r\n      <div class=\"link-text\">\r\n        <div class=\"link-title\">Raw Report<\/div>\r\n        <div class=\"link-desc\">Data mentah transaksi harian<\/div>\r\n      <\/div>\r\n      <div class=\"link-arrow\">\u203a<\/div>\r\n    <\/a>\r\n\r\n    <a class=\"link-btn\" style=\"--accent:#0D7D72; --icon-bg:#E5F5F3;\"\r\n       href=\"https:\/\/rbngeunah-tools-sales-shopeefood.netlify.app\/\"\r\n       target=\"_blank\" rel=\"noopener\">\r\n      <div class=\"link-icon\">\ud83d\uded2<\/div>\r\n      <div class=\"link-text\">\r\n        <div class=\"link-title\">Rekap Sales ShopeeFood<\/div>\r\n        <div class=\"link-desc\">Tools rekap dan analisis ShopeeFood<\/div>\r\n      <\/div>\r\n      <div class=\"link-arrow\">\u203a<\/div>\r\n    <\/a>\r\n\r\n  <\/div>\r\n\r\n  <div class=\"divider-sm\"><\/div>\r\n\r\n  <!-- Manajemen -->\r\n  <div class=\"section-label\">\u2699\ufe0f Manajemen<\/div>\r\n  <div class=\"links\">\r\n\r\n    <a class=\"link-btn\" style=\"--accent:#C8202B; --icon-bg:#FDECEA;\"\r\n       href=\"https:\/\/admin-portalrbngeunah.netlify.app\/\"\r\n       target=\"_blank\" rel=\"noopener\">\r\n      <div class=\"link-icon\">\ud83d\udee1\ufe0f<\/div>\r\n      <div class=\"link-text\">\r\n        <div class=\"link-title\">Admin Portal<\/div>\r\n        <div class=\"link-desc\">Kelola outlet, menu, dan pengaturan sistem<\/div>\r\n      <\/div>\r\n      <div class=\"link-arrow\">\u203a<\/div>\r\n    <\/a>\r\n\r\n    <a class=\"link-btn\" style=\"--accent:#1A5FA8; --icon-bg:#E8F0FB;\"\r\n       href=\"https:\/\/pos.rotibakarngeunah.my.id\/admin.html\"\r\n       target=\"_blank\" rel=\"noopener\">\r\n      <div class=\"link-icon\">\ud83e\uddfe<\/div>\r\n      <div class=\"link-text\">\r\n        <div class=\"link-title\">POS<\/div>\r\n        <div class=\"link-desc\">Akses sistem kasir outlet<\/div>\r\n      <\/div>\r\n      <div class=\"link-arrow\">\u203a<\/div>\r\n    <\/a>\r\n\r\n    <a class=\"link-btn\" style=\"--accent:#1A8A3C; --icon-bg:#E8F5ED;\"\r\n       href=\"https:\/\/staff-portal.rotibakarngeunah.my.id\/inventori\/\"\r\n       target=\"_blank\" rel=\"noopener\">\r\n      <div class=\"link-icon\">\ud83d\udce6<\/div>\r\n      <div class=\"link-text\">\r\n        <div class=\"link-title\">Inventory<\/div>\r\n        <div class=\"link-desc\">Kelola stok bahan baku dan persediaan<\/div>\r\n      <\/div>\r\n      <div class=\"link-arrow\">\u203a<\/div>\r\n    <\/a>\r\n\r\n    <a class=\"link-btn\" style=\"--accent:#6B3FA0; --icon-bg:#F0EAF9;\"\r\n       href=\"https:\/\/recruitment-rbngeunah.vercel.app\/admin\/login\"\r\n       target=\"_blank\" rel=\"noopener\">\r\n      <div class=\"link-icon\">\ud83d\udc65<\/div>\r\n      <div class=\"link-text\">\r\n        <div class=\"link-title\">Rekrutmen<\/div>\r\n        <div class=\"link-desc\">Data kandidat dan proses rekrutmen<\/div>\r\n      <\/div>\r\n      <div class=\"link-arrow\">\u203a<\/div>\r\n    <\/a>\r\n\r\n    <a class=\"link-btn\" style=\"--accent:#F6B800; --icon-bg:#FEF8E0;\"\r\n       href=\"https:\/\/template-slip-gaji.netlify.app\/\"\r\n       target=\"_blank\" rel=\"noopener\">\r\n      <div class=\"link-icon\">\ud83d\udcb3<\/div>\r\n      <div class=\"link-text\">\r\n        <div class=\"link-title\">Generate Slip Gaji<\/div>\r\n        <div class=\"link-desc\">Buat dan cetak slip gaji karyawan<\/div>\r\n      <\/div>\r\n      <div class=\"link-arrow\">\u203a<\/div>\r\n    <\/a>\r\n\r\n  <\/div>\r\n\r\n  <div class=\"footer\">\r\n    Internal Use Only \u00b7 \u00a9 2026 Roti Bakar Ngeunah\r\n  <\/div>\r\n\r\n<\/div>\r\n<\/div>\r\n\r\n<script>\r\n(function(){\r\n  \"use strict\";\r\n\r\n  \/* \u2500\u2500 SECURITY CONFIG \u2500\u2500 *\/\r\n  const CORRECT = (function(){\r\n    \/\/ Stored as char codes \u2014 harder to spot in raw source\r\n    return [103,97,109,101,97,100,105,116,52,53,50,49].map(c=>String.fromCharCode(c)).join('');\r\n  })();\r\n\r\n  const MAX_ATTEMPTS   = 5;\r\n  const LOCKOUT_MS     = 5 * 60 * 1000; \/\/ 5 menit\r\n  const SESSION_MS     = 4 * 60 * 60 * 1000; \/\/ 4 jam\r\n  const SESSION_KEY    = '_rbn_sess';\r\n  const LOCKOUT_KEY    = '_rbn_lock';\r\n  const ATTEMPT_KEY    = '_rbn_atmp';\r\n\r\n  \/* \u2500\u2500 ELEMENTS \u2500\u2500 *\/\r\n  const gate        = document.getElementById('gate');\r\n  const app         = document.getElementById('app');\r\n  const pwInput     = document.getElementById('pw-input');\r\n  const btnLogin    = document.getElementById('btn-login');\r\n  const btnLogout   = document.getElementById('btn-logout');\r\n  const gateError   = document.getElementById('gate-error');\r\n  const gateAttempts= document.getElementById('gate-attempts');\r\n  const lockoutMsg  = document.getElementById('lockout-msg');\r\n  const togglePw    = document.getElementById('toggle-pw');\r\n\r\n  \/* \u2500\u2500 SESSION HELPERS \u2500\u2500 *\/\r\n  function getSession(){\r\n    try{\r\n      const raw = sessionStorage.getItem(SESSION_KEY);\r\n      if(!raw) return null;\r\n      const obj = JSON.parse(raw);\r\n      if(Date.now() > obj.exp) { sessionStorage.removeItem(SESSION_KEY); return null; }\r\n      return obj;\r\n    }catch(e){ return null; }\r\n  }\r\n\r\n  function setSession(){\r\n    try{\r\n      sessionStorage.setItem(SESSION_KEY, JSON.stringify({ exp: Date.now() + SESSION_MS }));\r\n    }catch(e){}\r\n  }\r\n\r\n  function clearSession(){\r\n    try{ sessionStorage.removeItem(SESSION_KEY); }catch(e){}\r\n  }\r\n\r\n  \/* \u2500\u2500 LOCKOUT HELPERS \u2500\u2500 *\/\r\n  function getLockout(){\r\n    try{\r\n      const raw = localStorage.getItem(LOCKOUT_KEY);\r\n      if(!raw) return null;\r\n      const obj = JSON.parse(raw);\r\n      if(Date.now() > obj.until){ clearLockout(); return null; }\r\n      return obj;\r\n    }catch(e){ return null; }\r\n  }\r\n\r\n  function setLockout(){\r\n    try{\r\n      localStorage.setItem(LOCKOUT_KEY, JSON.stringify({ until: Date.now() + LOCKOUT_MS }));\r\n      localStorage.setItem(ATTEMPT_KEY, '0');\r\n    }catch(e){}\r\n  }\r\n\r\n  function clearLockout(){\r\n    try{\r\n      localStorage.removeItem(LOCKOUT_KEY);\r\n      localStorage.removeItem(ATTEMPT_KEY);\r\n    }catch(e){}\r\n  }\r\n\r\n  function getAttempts(){\r\n    return parseInt(localStorage.getItem(ATTEMPT_KEY)||'0',10);\r\n  }\r\n\r\n  function incAttempts(){\r\n    const n = getAttempts() + 1;\r\n    try{ localStorage.setItem(ATTEMPT_KEY, String(n)); }catch(e){}\r\n    return n;\r\n  }\r\n\r\n  \/* \u2500\u2500 TIMING-SAFE COMPARE \u2500\u2500 *\/\r\n  function safeEq(a,b){\r\n    if(typeof a !== 'string' || typeof b !== 'string') return false;\r\n    const pa = new TextEncoder().encode(a.padEnd(256));\r\n    const pb = new TextEncoder().encode(b.padEnd(256));\r\n    let diff = a.length === b.length ? 0 : 1;\r\n    for(let i=0;i<256;i++) diff |= (pa[i] ^ pb[i]);\r\n    return diff === 0;\r\n  }\r\n\r\n  \/* \u2500\u2500 SHOW \/ HIDE \u2500\u2500 *\/\r\n  function showApp(){\r\n    gate.style.display = 'none';\r\n    app.style.display  = 'block';\r\n    const img = app.querySelector('.logo-img');\r\n    if(img){\r\n      if(img.complete && img.naturalWidth) img.classList.add('loaded');\r\n      else img.addEventListener('load', ()=>img.classList.add('loaded'));\r\n    }\r\n  }\r\n\r\n  function showGate(){\r\n    app.style.display  = 'none';\r\n    gate.style.display = 'flex';\r\n  }\r\n\r\n  \/* \u2500\u2500 LOCKOUT UI \u2500\u2500 *\/\r\n  function showLockoutUI(until){\r\n    pwInput.disabled  = true;\r\n    btnLogin.disabled = true;\r\n    lockoutMsg.style.display = 'block';\r\n\r\n    function tick(){\r\n      const rem = Math.max(0, Math.ceil((until - Date.now()) \/ 1000));\r\n      const m = Math.floor(rem\/60), s = rem%60;\r\n      lockoutMsg.innerHTML = `\ud83d\udd12 Terlalu banyak percobaan salah.<br>Coba lagi dalam <strong>${m}:${String(s).padStart(2,'0')}<\/strong>`;\r\n      if(rem <= 0){\r\n        clearLockout();\r\n        pwInput.disabled  = false;\r\n        btnLogin.disabled = false;\r\n        lockoutMsg.style.display = 'none';\r\n        gateAttempts.textContent = '';\r\n      } else {\r\n        setTimeout(tick, 1000);\r\n      }\r\n    }\r\n    tick();\r\n  }\r\n\r\n  \/* \u2500\u2500 LOGIN \u2500\u2500 *\/\r\n  function attemptLogin(){\r\n    const lock = getLockout();\r\n    if(lock){ showLockoutUI(lock.until); return; }\r\n\r\n    const val = pwInput.value;\r\n\r\n    if(safeEq(val, CORRECT)){\r\n      clearLockout();\r\n      setSession();\r\n      pwInput.value = '';\r\n      gateError.classList.add('hidden');\r\n      gateAttempts.textContent = '';\r\n      showApp();\r\n    } else {\r\n      const n = incAttempts();\r\n      const left = MAX_ATTEMPTS - n;\r\n\r\n      gateError.textContent = 'Password salah. Coba lagi.';\r\n      gateError.classList.remove('hidden');\r\n      pwInput.value = '';\r\n      pwInput.focus();\r\n\r\n      if(n >= MAX_ATTEMPTS){\r\n        setLockout();\r\n        showLockoutUI(getLockout().until);\r\n      } else {\r\n        gateAttempts.textContent = `Sisa percobaan: ${left}`;\r\n      }\r\n    }\r\n  }\r\n\r\n  \/* \u2500\u2500 INIT \u2500\u2500 *\/\r\n  (function init(){\r\n    \/\/ Already logged in this session?\r\n    if(getSession()){\r\n      showApp();\r\n    } else {\r\n      showGate();\r\n      setTimeout(()=>{ try{ pwInput.focus(); }catch(e){} }, 300);\r\n    }\r\n\r\n    \/\/ Check lockout on load\r\n    const lock = getLockout();\r\n    if(lock) showLockoutUI(lock.until);\r\n  })();\r\n\r\n  \/* \u2500\u2500 EVENTS \u2500\u2500 *\/\r\n  btnLogin.addEventListener('click', attemptLogin);\r\n\r\n  pwInput.addEventListener('keydown', function(e){\r\n    if(e.key === 'Enter') attemptLogin();\r\n  });\r\n\r\n  togglePw.addEventListener('click', function(){\r\n    const isText = pwInput.type === 'text';\r\n    pwInput.type = isText ? 'password' : 'text';\r\n    togglePw.textContent = isText ? '\ud83d\udc41' : '\ud83d\ude48';\r\n  });\r\n\r\n  btnLogout.addEventListener('click', function(){\r\n    clearSession();\r\n    showGate();\r\n    setTimeout(()=>{ try{ pwInput.focus(); }catch(e){} }, 150);\r\n  });\r\n\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     ANTI-INSPECTION \/ SECURITY LAYER\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n\r\n  \/\/ 1. Block right-click\r\n  document.addEventListener('contextmenu', function(e){\r\n    e.preventDefault();\r\n    return false;\r\n  }, true);\r\n\r\n  \/\/ 2. Block common DevTools keyboard shortcuts\r\n  document.addEventListener('keydown', function(e){\r\n    const key = e.key ? e.key.toLowerCase() : '';\r\n    \/\/ F12\r\n    if(e.keyCode === 123){ e.preventDefault(); return false; }\r\n    \/\/ Ctrl\/Cmd + Shift + I\/J\/C\/K\/U\r\n    if((e.ctrlKey||e.metaKey) && e.shiftKey && ['i','j','c','k'].includes(key)){\r\n      e.preventDefault(); return false;\r\n    }\r\n    \/\/ Ctrl\/Cmd + U (view source)\r\n    if((e.ctrlKey||e.metaKey) && key==='u'){ e.preventDefault(); return false; }\r\n    \/\/ Ctrl\/Cmd + S (save page)\r\n    if((e.ctrlKey||e.metaKey) && key==='s'){ e.preventDefault(); return false; }\r\n    \/\/ Ctrl\/Cmd + P (print)\r\n    if((e.ctrlKey||e.metaKey) && key==='p'){ e.preventDefault(); return false; }\r\n  }, true);\r\n\r\n  \/\/ 3. Block drag\r\n  document.addEventListener('dragstart', function(e){ e.preventDefault(); }, true);\r\n\r\n  \/\/ 4. Detect DevTools open via window size heuristic (desktop)\r\n  (function devtoolsGuard(){\r\n    let warned = false;\r\n    setInterval(function(){\r\n      const threshold = 160;\r\n      const opened =\r\n        (window.outerWidth - window.innerWidth > threshold) ||\r\n        (window.outerHeight - window.innerHeight > threshold);\r\n      if(opened && !warned){\r\n        warned = true;\r\n        if(!getSession()){\r\n          \/\/ Already on gate, do nothing extra\r\n        }\r\n        \/\/ Optional: clear session if devtools opened while logged in\r\n        \/\/ clearSession(); showGate();\r\n      }\r\n      if(!opened) warned = false;\r\n    }, 1000);\r\n  })();\r\n\r\n  \/\/ 5. Disable print screen via CSS (best-effort)\r\n  (function noPrint(){\r\n    const style = document.createElement('style');\r\n    style.textContent = '@media print { body { display:none !important; } }';\r\n    document.head.appendChild(style);\r\n  })();\r\n\r\n  \/\/ 6. Session expiry check \u2014 every 60 seconds\r\n  setInterval(function(){\r\n    if(app.style.display !== 'none' && !getSession()){\r\n      clearSession();\r\n      showGate();\r\n    }\r\n  }, 60000);\r\n\r\n})();\r\n<\/script>\r\n<\/body>\r\n<\/html>\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>Roti Bakar Ngeunah \u2013 Owner Portal Roti Bakar Ngeunah Owner Portal \u00b7 Akses Terbatas &#x1f510; Masukkan Password &#x1f441; Masuk Password salah. Coba lagi. &#x1f7e2; Sesi Aktif Keluar Roti Bakar Ngeunah Owner Portal &#x1f4ca; Keuangan &#x1f4b0; Business Cashflow Pantau arus kas dan keuangan bisnis \u203a &#x1f4c8; Sales Report Laporan penjualan dan performa outlet \u203a &#x1f4cb; Raw [&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-7","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/owner-portal.rotibakarngeunah.my.id\/index.php?rest_route=\/wp\/v2\/pages\/7","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/owner-portal.rotibakarngeunah.my.id\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/owner-portal.rotibakarngeunah.my.id\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/owner-portal.rotibakarngeunah.my.id\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/owner-portal.rotibakarngeunah.my.id\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7"}],"version-history":[{"count":19,"href":"https:\/\/owner-portal.rotibakarngeunah.my.id\/index.php?rest_route=\/wp\/v2\/pages\/7\/revisions"}],"predecessor-version":[{"id":30,"href":"https:\/\/owner-portal.rotibakarngeunah.my.id\/index.php?rest_route=\/wp\/v2\/pages\/7\/revisions\/30"}],"wp:attachment":[{"href":"https:\/\/owner-portal.rotibakarngeunah.my.id\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}