{"id":193,"date":"2025-09-18T02:30:01","date_gmt":"2025-09-18T02:30:01","guid":{"rendered":"https:\/\/helpdesk.costbook.ph\/?page_id=193"},"modified":"2025-11-24T23:54:30","modified_gmt":"2025-11-25T07:54:30","slug":"dashboard-2","status":"publish","type":"page","link":"https:\/\/helpdesk.costbook.ph\/index.php\/dashboard-2\/","title":{"rendered":"Settings"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"193\" class=\"elementor elementor-193\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-7bc5493 e-con-full e-flex e-con e-parent\" data-id=\"7bc5493\" data-element_type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-d10d25f elementor-widget elementor-widget-template\" data-id=\"d10d25f\" data-element_type=\"widget\" data-widget_type=\"template.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-template\">\n\t\t\t\t\t<div data-elementor-type=\"page\" data-elementor-id=\"925\" class=\"elementor elementor-925\" data-elementor-post-type=\"elementor_library\">\n\t\t\t\t<div class=\"elementor-element elementor-element-7946887d e-con-full e-flex e-con e-parent\" data-id=\"7946887d\" data-element_type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t<div class=\"elementor-element elementor-element-64491c90 e-con-full e-flex e-con e-child\" data-id=\"64491c90\" data-element_type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-19812326 elementor-widget elementor-widget-image\" data-id=\"19812326\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"300\" height=\"169\" src=\"https:\/\/helpdesk.costbook.ph\/wp-content\/uploads\/2025\/09\/gffggfgf-removebg-preview-300x169.png\" class=\"attachment-medium size-medium wp-image-297\" alt=\"\" srcset=\"https:\/\/helpdesk.costbook.ph\/wp-content\/uploads\/2025\/09\/gffggfgf-removebg-preview-300x169.png 300w, https:\/\/helpdesk.costbook.ph\/wp-content\/uploads\/2025\/09\/gffggfgf-removebg-preview.png 666w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-2644b23e e-con-full e-flex e-con e-child\" data-id=\"2644b23e\" data-element_type=\"container\" data-settings=\"{&quot;position&quot;:&quot;absolute&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-2beff56e elementor-widget-tablet__width-initial elementor-widget__width-initial eael_simple_menu_hamburger_disable_selected_menu_no eael-simple-menu-hamburger-align-right eael-hamburger--tablet elementor-widget elementor-widget-eael-simple-menu\" data-id=\"2beff56e\" data-element_type=\"widget\" data-widget_type=\"eael-simple-menu.default\">\n\t\t\t\t\t<style>\n                        @media screen and (max-width: 1024px) {\n                            .eael-hamburger--tablet {\n                                .eael-simple-menu-horizontal,\n                                .eael-simple-menu-vertical {\n                                    display: none;\n                                }\n                            }\n                            .eael-hamburger--tablet {\n                                .eael-simple-menu-container .eael-simple-menu-toggle {\n                                    display: block;\n                                }\n                            }\n                        }\n                    <\/style>            <div data-hamburger-icon=\"&lt;svg aria-hidden=&quot;true&quot; class=&quot;e-font-icon-svg e-fas-bars&quot; viewBox=&quot;0 0 448 512&quot; xmlns=&quot;http:\/\/www.w3.org\/2000\/svg&quot;&gt;&lt;path d=&quot;M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z&quot;&gt;&lt;\/path&gt;&lt;\/svg&gt;\" data-indicator-icon=\"&lt;svg aria-hidden=&quot;true&quot; class=&quot;e-font-icon-svg e-fas-angle-down&quot; viewBox=&quot;0 0 320 512&quot; xmlns=&quot;http:\/\/www.w3.org\/2000\/svg&quot;&gt;&lt;path d=&quot;M143 352.3L7 216.3c-9.4-9.4-9.4-24.6 0-33.9l22.6-22.6c9.4-9.4 24.6-9.4 33.9 0l96.4 96.4 96.4-96.4c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9l-136 136c-9.2 9.4-24.4 9.4-33.8 0z&quot;&gt;&lt;\/path&gt;&lt;\/svg&gt;\" data-dropdown-indicator-icon=\"&lt;svg class=&quot;e-font-icon-svg e-fas-angle-down&quot; viewBox=&quot;0 0 320 512&quot; xmlns=&quot;http:\/\/www.w3.org\/2000\/svg&quot;&gt;&lt;path d=&quot;M143 352.3L7 216.3c-9.4-9.4-9.4-24.6 0-33.9l22.6-22.6c9.4-9.4 24.6-9.4 33.9 0l96.4 96.4 96.4-96.4c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9l-136 136c-9.2 9.4-24.4 9.4-33.8 0z&quot;&gt;&lt;\/path&gt;&lt;\/svg&gt;\" class=\"eael-simple-menu-container eael-simple-menu-align-center eael-simple-menu-dropdown-align-left preset-1\" data-hamburger-breakpoints=\"{&quot;mobile&quot;:&quot;Mobile Portrait (&gt; 767px)&quot;,&quot;tablet&quot;:&quot;Tablet Portrait (&gt; 1024px)&quot;,&quot;desktop&quot;:&quot;Desktop (&gt; 2400px)&quot;,&quot;none&quot;:&quot;None&quot;}\" data-hamburger-device=\"tablet\">\n                <ul id=\"menu-main-menu\" class=\"eael-simple-menu eael-simple-menu-dropdown-animate-to-top eael-simple-menu-indicator eael-simple-menu-horizontal\"><li id=\"menu-item-875\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-875\"><a href=\"https:\/\/helpdesk.costbook.ph\/index.php\/dashboard-2-2\/\">Home<\/a><\/li>\n<li id=\"menu-item-878\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-878\"><a href=\"https:\/\/helpdesk.costbook.ph\/index.php\/elementor-131\/\">Ticket<\/a><\/li>\n<li id=\"menu-item-1004\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1004\"><a href=\"https:\/\/helpdesk.costbook.ph\/index.php\/employees\/\">Employees<\/a><\/li>\n<li id=\"menu-item-1057\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1057\"><a href=\"https:\/\/helpdesk.costbook.ph\/index.php\/assets\/\">Assets<\/a><\/li>\n<li id=\"menu-item-996\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-996\"><a href=\"https:\/\/helpdesk.costbook.ph\/index.php\/category\/\">Category<\/a><\/li>\n<li id=\"menu-item-876\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-876\"><a href=\"https:\/\/helpdesk.costbook.ph\/index.php\/report-analytics\/\">Reports<\/a><\/li>\n<li id=\"menu-item-877\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-877\"><a href=\"https:\/\/helpdesk.costbook.ph\/index.php\/dashboard-2\/\">Settings<\/a><\/li>\n<\/ul>                <button class=\"eael-simple-menu-toggle\">\n                    <span class=\"sr-only \">Hamburger Toggle Menu<\/span>\n                    <svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fas-bars\" viewBox=\"0 0 448 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z\"><\/path><\/svg>                <\/button>\n            <\/div>\n            \t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-50be23d e-con-full e-flex e-con e-parent\" data-id=\"50be23d\" data-element_type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-8cb775e e-con-full e-flex e-con e-child\" data-id=\"8cb775e\" data-element_type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t<div class=\"elementor-element elementor-element-e3bc0dd e-con-full e-flex e-con e-child\" data-id=\"e3bc0dd\" data-element_type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-fd183af elementor-widget elementor-widget-heading\" data-id=\"fd183af\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Account Settings<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0ad287d e-n-tabs-mobile elementor-widget elementor-widget-n-tabs\" data-id=\"0ad287d\" data-element_type=\"widget\" data-widget_type=\"nested-tabs.default\">\n\t\t\t\t\t\t\t<div class=\"e-n-tabs\" data-widget-number=\"11348093\" aria-label=\"Tabs. Open items with Enter or Space, close with Escape and navigate using the Arrow keys.\">\n\t\t\t<div class=\"e-n-tabs-heading\" role=\"tablist\">\n\t\t\t\t\t<button id=\"e-n-tab-title-113480931\" class=\"e-n-tab-title\" aria-selected=\"true\" data-tab-index=\"1\" role=\"tab\" tabindex=\"0\" aria-controls=\"e-n-tab-content-113480931\" style=\"--n-tabs-title-order: 1;\">\n\t\t\t\t\t\t<span class=\"e-n-tab-title-text\">\n\t\t\t\tAdmin Profile\t\t\t<\/span>\n\t\t<\/button>\n\t\t\t\t<button id=\"e-n-tab-title-113480932\" class=\"e-n-tab-title\" aria-selected=\"false\" data-tab-index=\"2\" role=\"tab\" tabindex=\"-1\" aria-controls=\"e-n-tab-content-113480932\" style=\"--n-tabs-title-order: 2;\">\n\t\t\t\t\t\t<span class=\"e-n-tab-title-text\">\n\t\t\t\tSecurity &amp; Login\t\t\t<\/span>\n\t\t<\/button>\n\t\t\t\t<button id=\"e-n-tab-title-113480933\" class=\"e-n-tab-title\" aria-selected=\"false\" data-tab-index=\"3\" role=\"tab\" tabindex=\"-1\" aria-controls=\"e-n-tab-content-113480933\" style=\"--n-tabs-title-order: 3;\">\n\t\t\t\t\t\t<span class=\"e-n-tab-title-text\">\n\t\t\t\tRoles &amp; Permissions\t\t\t<\/span>\n\t\t<\/button>\n\t\t\t\t<button id=\"e-n-tab-title-113480934\" class=\"e-n-tab-title\" aria-selected=\"false\" data-tab-index=\"4\" role=\"tab\" tabindex=\"-1\" aria-controls=\"e-n-tab-content-113480934\" style=\"--n-tabs-title-order: 4;\">\n\t\t\t\t\t\t<span class=\"e-n-tab-title-text\">\n\t\t\t\tNotification\t\t\t<\/span>\n\t\t<\/button>\n\t\t\t\t<button id=\"e-n-tab-title-113480935\" class=\"e-n-tab-title\" aria-selected=\"false\" data-tab-index=\"5\" role=\"tab\" tabindex=\"-1\" aria-controls=\"e-n-tab-content-113480935\" style=\"--n-tabs-title-order: 5;\">\n\t\t\t\t\t\t<span class=\"e-n-tab-title-text\">\n\t\t\t\tAutomation &amp; Workflows\t\t\t<\/span>\n\t\t<\/button>\n\t\t\t\t\t<\/div>\n\t\t\t<div class=\"e-n-tabs-content\">\n\t\t\t\t<div id=\"e-n-tab-content-113480931\" role=\"tabpanel\" aria-labelledby=\"e-n-tab-title-113480931\" data-tab-index=\"1\" style=\"--n-tabs-title-order: 1;\" class=\"e-active elementor-element elementor-element-3e470e3 e-con-full e-flex e-con e-child\" data-id=\"3e470e3\" data-element_type=\"container\" data-settings=\"{&quot;position&quot;:&quot;absolute&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-79aa684 elementor-widget elementor-widget-html\" data-id=\"79aa684\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n<meta charset=\"UTF-8\" \/>\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\/>\r\n<title>Account Settings \u2013 Profile & Organization<\/title>\r\n<style>\r\n\r\n  :root{\r\n    \/* Base *\/\r\n    --bg:#f6f8fb;\r\n    --surface:#ffffff;\r\n    --text:#1e2430;\r\n    --muted:#6b7280;\r\n    --line:#e7eaf2;\r\n\r\n    \/* Brand (live-updated) *\/\r\n    --primary:#2d6bff;\r\n    --primary-10: rgba(45,107,255,.10);\r\n    --accent:#0ba98b;\r\n\r\n    \/* States *\/\r\n    --danger:#d92d20;\r\n    --focus: rgba(45,107,255,.18);\r\n\r\n    \/* Shape *\/\r\n    --radius-lg:16px;\r\n    --radius-md:12px;\r\n\r\n    \/* Shadow *\/\r\n    --shadow-sm:0 1px 2px rgba(16,24,40,.06);\r\n    --shadow-md:0 6px 18px rgba(16,24,40,.08);\r\n  }\r\n\r\n  *{box-sizing:border-box}\r\n  html,body{height:100%}\r\n  body{\r\n    margin:0; \r\n    font:14px\/1.55 ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, Inter, Arial, \"Apple Color Emoji\",\"Segoe UI Emoji\";\r\n    color:var(--text); \r\n    background:var(--bg);\r\n    padding:28px;\r\n    transition:background .25s ease;\r\n  }\r\n  .container{\r\n    max-width:1200px; \r\n    margin:0 auto;\r\n    display:grid; \r\n    grid-template-columns: 1.2fr .8fr; \r\n    gap:24px;\r\n  }\r\n  @media (max-width: 1020px){ .container{grid-template-columns:1fr} }\r\n\r\n  header {\r\n    max-width:1200px;\r\n    margin:0 auto 18px\r\n    text-align: left;\r\n  }\r\n  .h1 {\r\n    font-size:22px; \r\n    font-weight:700; \r\n    margin:0 0 6px; \r\n    letter-spacing:.2px;\r\n    text-align: left;\r\n    white-space:nowrap;        \r\n    display:block; \r\n  }\r\n  .subtle {\r\n    color:var(--muted)}\r\n\r\n  .tabs{\r\n    max-width:1200px; \r\n    margin:12px auto 20px;\r\n    position:sticky; \r\n    top:0; z-index:5;\r\n    background:linear-gradient(180deg, rgba(246,248,251,1) 60%, rgba(246,248,251,.7) 100%);\r\n    backdrop-filter:saturate(1.2) blur(4px);\r\n    border-bottom:1px solid var(--line);\r\n  }\r\n  .tablist{\r\n    display:flex; \r\n    gap:6px; \r\n    padding:8px 0;\r\n  }\r\n  .tab{\r\n    appearance:none; \r\n    border:none; \r\n    background:transparent; \r\n    cursor:pointer;\r\n    padding:10px 14px; \r\n    border-radius:10px; \r\n    font-weight:600; \r\n    color:#495268;\r\n    transition:background .18s ease, color .18s ease;\r\n  }\r\n  .tab:hover {\r\n    background:#f2f5ff\r\n  }\r\n  .tab[aria-selected=\"true\"]{\r\n    background:#eef3ff; \r\n    color:#1e3a8a; \r\n    outline:2px solid transparent; \r\n    border:1px solid #dfe6ff;\r\n  }\r\n  .tab:focus {\r\n    box-shadow:0 0 0 4px var(--focus); \r\n    outline:none}\r\n\r\n  .card {\r\n    background:var(--surface);\r\n    border:1px solid var(--line);\r\n    border-radius:var(--radius-lg);\r\n    box-shadow:var(--shadow-sm);\r\n    overflow:hidden;\r\n  }\r\n  .card + .card {margin-top:18px}\r\n  .card-h {\r\n    padding:18px 20px 12px;\r\n    border-bottom:1px solid var(--line);\r\n    background:linear-gradient(180deg,#fff, #fafbff);\r\n  }\r\n  .card-t{\r\n    font-weight:700; \r\n    letter-spacing:.2px\r\n  }\r\n  .card-d{\r\n    color:var(--muted); \r\n    font-size:13px; \r\n    margin-top:2px\r\n  }\r\n  .card-c{\r\n    padding:18px 20px\r\n  }\r\n\r\n  .grid-2 {\r\n    display:grid; \r\n    grid-template-columns:1fr 1fr; \r\n    gap:14px\r\n  }\r\n  .grid-3 {\r\n    display:grid; \r\n    grid-template-columns:repeat(3,1fr); \r\n    gap:14px\r\n  }\r\n  @media (max-width:760px){ .grid-2,.grid-3{grid-template-columns:1fr} }\r\n\r\n  label{\r\n    display:block; \r\n    font-weight:600; \r\n    font-size:12px;\r\n    letter-spacing:.28px; \r\n    text-transform:uppercase; \r\n    color:#7b8497; \r\n    margin:6px 0 8px\r\n  }\r\n\r\n  input[type=\"text\"], \r\n  input[type=\"email\"], \r\n  input[type=\"url\"], \r\n  input[type=\"tel\"], \r\n  select{\r\n    width:100%; \r\n    background:#fff; \r\n    border:1px solid var(--line); \r\n    color:var(--text);\r\n    padding:12px 12px; \r\n    border-radius:var(--radius-md); \r\n    outline:none;\r\n    transition:border-color .18s ease, box-shadow .18s ease, background .18s ease;\r\n    box-shadow:inset 0 1px 0 rgba(16,24,40,.02);\r\n  }\r\n  input::placeholder {\r\n    color:#9aa3b2\r\n  }\r\n  input:focus, select:focus {\r\n    border-color:var(--primary); \r\n    box-shadow:0 0 0 4px var(--focus)\r\n  }\r\n\r\n  .field {\r\n    margin-bottom:12px\r\n  }\r\n  .hint {\r\n    color:var(--muted); \r\n    font-size:12px; \r\n    margin-top:6px\r\n  }\r\n  .inline-help {\r\n    font-size:12px; \r\n    color:var(--muted)\r\n  }\r\n\r\n  .row {\r\n    display:flex; \r\n    gap:10px; \r\n    align-items:center; \r\n    flex-wrap:wrap\r\n  }\r\n\r\n  .btn{\r\n    border:1px solid var(--line);\r\n    background:#fff; \r\n    color:var(--text);\r\n    padding:10px 14px; \r\n    border-radius:10px; \r\n    cursor:pointer;\r\n    transition:transform .12s ease, background .18s ease, border .18s ease, box-shadow .18s ease;\r\n    font-weight:600\r\n  }\r\n  .btn:hover {\r\n    background:#f9fafe\r\n  }\r\n  .btn:active {\r\n    transform:translateY(1px)\r\n  }\r\n  .btn.primary {\r\n    background:var(--primary); \r\n    border-color:#275de0; \r\n    color:#fff; \r\n    box-shadow:0 1px 0 rgba(0,0,0,.02)\r\n  }\r\n  .btn.primary:hover {\r\n    filter:brightness(1.03)\r\n  }\r\n  .btn.primary[disabled]{opacity:.6; cursor:not-allowed}\r\n  .btn.ghost{\r\n    background:transparent\r\n  }\r\n  .btn.danger{\r\n    background:#fff5f5; \r\n    border-color:#ffd6d6; \r\n    color:#b42318\r\n  }\r\n\r\n  .toolbar{\r\n    position:sticky; \r\n    bottom:0;\r\n    background:linear-gradient(180deg, rgba(246,248,251,0) 0, rgba(246,248,251,.9) 30%, rgba(246,248,251,.98) 100%);\r\n    padding:14px 0; \r\n    display:flex; \r\n    gap:10px; \r\n    justify-content:flex-end\r\n  }\r\n\r\n  .sep {\r\n    height:1px; \r\n    background:var(--line); \r\n    margin:12px 0}\r\n\r\n  .upload {\r\n    position:relative; \r\n    border:1px dashed #dfe5ef; \r\n    border-radius:12px; \r\n    background:#fbfcfe; \r\n    padding:14px; \r\n    text-align:center; \r\n    cursor:pointer;\r\n    transition:border-color .18s ease, background .18s ease;\r\n  }\r\n  .upload:hover {\r\n    border-color:var(--primary); \r\n    background:#f7faff\r\n  }\r\n  .upload input {\r\n    position:absolute; \r\n    inset:0; \r\n    opacity:0; \r\n    cursor:pointer\r\n  }\r\n\r\n  .pill{\r\n    display:inline-flex; \r\n    gap:8px; \r\n    align-items:center; \r\n    border:1px solid var(--line); \r\n    background:#f7f8fc; \r\n    padding:8px 10px; \r\n    border-radius:999px; \r\n    font-size:12px; \r\n    color:#4b5563\r\n  }\r\n\r\n  .preview {\r\n    display:flex; \r\n    gap:12px; \r\n    align-items:center; \r\n    background:#f9fbff; \r\n    border:1px solid var(--line); \r\n    padding:10px; \r\n    border-radius:12px\r\n  }\r\n  .avatar, .logo {\r\n    width:56px; \r\n    height:56px; \r\n    border-radius:12px; \r\n    background:#f0f3f9; \r\n    border:1px solid var(--line); \r\n    object-fit:cover\r\n  }\r\n  .logo {\r\n    border-radius:10px\r\n  }\r\n\r\n  .brand-preview {\r\n    border:1px solid var(--line); \r\n    border-radius:12px; \r\n    overflow:hidden; \r\n    background:#fff; \r\n    box-shadow:var(--shadow-sm);\r\n  }\r\n  .brand-header {\r\n    padding:12px 14px; \r\n    font-weight:700; \r\n    background:#f6f8fe\r\n  }\r\n\r\n  .toast {\r\n    position:fixed; \r\n    right:20px; \r\n    bottom:20px; \r\n    background:#243b7b; \r\n    border:1px solid #314b95; \r\n    color:#e8efff;\r\n    padding:12px 14px; \r\n    border-radius:12px; \r\n    box-shadow:var(--shadow-md); \r\n    opacity:0; \r\n    transform:translateY(8px); \r\n    pointer-events:none; \r\n    transition:.25s\r\n  }\r\n  .toast.show {\r\n    opacity:1; \r\n    transform:translateY(0)\r\n  }\r\n  .error {\r\n    color:#b42318; \r\n    font-size:12px; \r\n    margin-top:6px\r\n  }\r\n\r\n  .panel {\r\n    display:none\r\n  }\r\n  .panel.active{\r\n    display:block\r\n  }\r\n\r\n  .spinner{\r\n    width:14px; \r\n    height:14px; \r\n    border-radius:50%;\r\n    border:2px solid rgba(255,255,255,.55); \r\n    border-top-color:#fff;\r\n    animation:spin .8s linear infinite; \r\n    display:inline-block; \r\n    vertical-align:middle; \r\n    margin-right:8px\r\n  }\r\n  @keyframes spin { to { transform: rotate(360deg); } }\r\n\r\n\r\n  .bg-grid {\r\n    display:grid; \r\n    grid-template-columns:1fr 1fr; \r\n    gap:12px\r\n  }\r\n  .bg-grid-3 {\r\n    display:grid; \r\n    grid-template-columns:1fr 1fr 1fr; \r\n    gap:12px\r\n  }\r\n  @media (max-width:760px){ .bg-grid, .bg-grid-3 { grid-template-columns:1fr } }\r\n<\/style>\r\n<\/head>\r\n<body>\r\n  <header>\r\n    <div class=\"h1\">Account Settings - Admin Profile<\/div>\r\n  <\/header>\r\n\r\n  <!-- Tabs -->\r\n  <nav class=\"tabs\" aria-label=\"Profile & Organization Tabs\">\r\n    <div class=\"tablist\" role=\"tablist\" aria-orientation=\"horizontal\">\r\n      <button class=\"tab\" role=\"tab\" id=\"tab-profile\" aria-controls=\"panel-profile\" aria-selected=\"true\">Profile<\/button>\r\n      <button class=\"tab\" role=\"tab\" id=\"tab-organization\" aria-controls=\"panel-organization\" aria-selected=\"false\">Organization<\/button>\r\n      <button class=\"tab\" role=\"tab\" id=\"tab-support\" aria-controls=\"panel-support\" aria-selected=\"false\">Support<\/button>\r\n      <button class=\"tab\" role=\"tab\" id=\"tab-branding\" aria-controls=\"panel-branding\" aria-selected=\"false\">Branding<\/button>\r\n    <\/div>\r\n  <\/nav>\r\n\r\n  <form id=\"settingsForm\" class=\"container\" novalidate>\r\n    <!-- LEFT: Panels (controlled by tabs) -->\r\n    <div>\r\n      <!-- Panel: Profile -->\r\n      <section id=\"panel-profile\" class=\"panel active\" role=\"tabpanel\" aria-labelledby=\"tab-profile\" tabindex=\"0\">\r\n        <!-- Admin Profile -->\r\n        <section class=\"card\">\r\n          <div class=\"card-h\">\r\n            <div class=\"card-t\">Admin Profile<\/div>\r\n            <div class=\"card-d\">Personal identity and your profile photo<\/div>\r\n          <\/div>\r\n          <div class=\"card-c\">\r\n            <div class=\"field\">\r\n              <label for=\"name\">Name *<\/label>\r\n              <input id=\"name\" name=\"name\" type=\"text\" placeholder=\"Jane Doe\" required\/>\r\n              <div class=\"error\" data-error-for=\"name\"><\/div>\r\n            <\/div>\r\n            <div class=\"grid-2\">\r\n              <div class=\"field\">\r\n                <label for=\"username\">Username *<\/label>\r\n                <input id=\"username\" name=\"username\" type=\"text\" placeholder=\"janedoe\" required\/>\r\n                <div class=\"error\" data-error-for=\"username\"><\/div>\r\n              <\/div>\r\n              <div class=\"field\">\r\n                <label for=\"designation\">Designation<\/label>\r\n                <input id=\"designation\" name=\"designation\" type=\"text\" placeholder=\"Support Lead\"\/>\r\n              <\/div>\r\n            <\/div>\r\n            <div class=\"grid-2\">\r\n              <div class=\"field\">\r\n                <label for=\"email\">Email *<\/label>\r\n                <input id=\"email\" name=\"email\" type=\"email\" placeholder=\"jane@company.com\" required\/>\r\n                <div class=\"error\" data-error-for=\"email\"><\/div>\r\n              <\/div>\r\n              <div class=\"field\">\r\n                <label for=\"phone\">Contact Number<\/label>\r\n                <input id=\"phone\" name=\"phone\" type=\"tel\" placeholder=\"+63 900 000 0000\"\/>\r\n              <\/div>\r\n            <\/div>\r\n\r\n            <div class=\"grid-2\">\r\n              <div class=\"field\">\r\n                <label>Profile Photo<\/label>\r\n                <div class=\"upload\" data-upload=\"photo\">\r\n                  <input type=\"file\" accept=\"image\/*\"\/>\r\n                  <div>Click or drop an image here<\/div>\r\n                <\/div>\r\n                <div class=\"hint\">PNG\/JPG up to ~2MB. Preview below.<\/div>\r\n                <div class=\"preview\" style=\"margin-top:10px\">\r\n                  <img id=\"photoPreview\" class=\"avatar\" alt=\"photo preview\"\/>\r\n                  <div>\r\n                    <div class=\"subtle\">Current photo<\/div>\r\n                    <div class=\"row\" style=\"margin-top:6px\">\r\n                      <button type=\"button\" class=\"btn ghost\" id=\"photoRemove\">Remove<\/button>\r\n                    <\/div>\r\n                  <\/div>\r\n                <\/div>\r\n                <input id=\"photo\" name=\"photo\" type=\"hidden\"\/>\r\n              <\/div>\r\n\r\n              <div class=\"field\">\r\n                <label>Company Logo<\/label>\r\n                <div class=\"upload\" data-upload=\"logo\">\r\n                  <input type=\"file\" accept=\"image\/*\"\/>\r\n                  <div>Click or drop a logo here<\/div>\r\n                <\/div>\r\n                <div class=\"hint\">Transparent PNG recommended. Preview below.<\/div>\r\n                <div class=\"preview\" style=\"margin-top:10px\">\r\n                  <img id=\"logoPreview\" class=\"logo\" alt=\"logo preview\"\/>\r\n                  <div>\r\n                    <div class=\"subtle\">Current logo<\/div>\r\n                    <div class=\"row\" style=\"margin-top:6px\">\r\n                      <button type=\"button\" class=\"btn ghost\" id=\"logoRemove\">Remove<\/button>\r\n                    <\/div>\r\n                  <\/div>\r\n                <\/div>\r\n                <input id=\"logo\" name=\"logo\" type=\"hidden\"\/>\r\n              <\/div>\r\n            <\/div>\r\n          <\/div>\r\n        <\/section>\r\n      <\/section>\r\n\r\n      <!-- Panel: Organization -->\r\n      <section id=\"panel-organization\" class=\"panel\" role=\"tabpanel\" aria-labelledby=\"tab-organization\" tabindex=\"0\">\r\n        <section class=\"card\">\r\n          <div class=\"card-h\">\r\n            <div class=\"card-t\">Organization Settings<\/div>\r\n            <div class=\"card-d\">Company identity, time & date preferences<\/div>\r\n          <\/div>\r\n          <div class=\"card-c\">\r\n            <div class=\"grid-2\">\r\n              <div class=\"field\">\r\n                <label for=\"companyName\">Company Name *<\/label>\r\n                <input id=\"companyName\" name=\"companyName\" type=\"text\" placeholder=\"Acme Support, Inc.\" required\/>\r\n                <div class=\"error\" data-error-for=\"companyName\"><\/div>\r\n                <div class=\"inline-help\">Shown in headers, emails, and your customer portal.<\/div>\r\n              <\/div>\r\n              <div class=\"field\">\r\n                <label for=\"timezone\">Timezone *<\/label>\r\n                <select id=\"timezone\" name=\"timezone\" required><\/select>\r\n                <div class=\"error\" data-error-for=\"timezone\"><\/div>\r\n              <\/div>\r\n            <\/div>\r\n            <div class=\"grid-2\">\r\n              <div class=\"field\">\r\n                <label for=\"dateFormat\">Date Format *<\/label>\r\n                <select id=\"dateFormat\" name=\"dateFormat\" required>\r\n                  <option value=\"YYYY-MM-DD\">YYYY-MM-DD (2025-10-24)<\/option>\r\n                  <option value=\"DD\/MM\/YYYY\">DD\/MM\/YYYY (24\/10\/2025)<\/option>\r\n                  <option value=\"MM\/DD\/YYYY\">MM\/DD\/YYYY (10\/24\/2025)<\/option>\r\n                <\/select>\r\n                <div class=\"error\" data-error-for=\"dateFormat\"><\/div>\r\n                <div class=\"hint\" id=\"dateSampleHint\"><\/div>\r\n              <\/div>\r\n              <div class=\"field\">\r\n                <label for=\"regionFormat\">Region \/ Number Format *<\/label>\r\n                <select id=\"regionFormat\" name=\"regionFormat\" required>\r\n                  <option value=\"en-PH\">English (Philippines) \u2013 en-PH<\/option>\r\n                  <option value=\"fil-PH\">Filipino \u2013 fil-PH<\/option>\r\n                  <option value=\"en-US\">English (United States) \u2013 en-US<\/option>\r\n                  <option value=\"en-GB\">English (United Kingdom) \u2013 en-GB<\/option>\r\n                  <option value=\"en-AU\">English (Australia) \u2013 en-AU<\/option>\r\n                  <option value=\"ja-JP\">\u65e5\u672c\u8a9e \u2013 ja-JP<\/option>\r\n                  <option value=\"de-DE\">Deutsch \u2013 de-DE<\/option>\r\n                  <option value=\"fr-FR\">Fran\u00e7ais \u2013 fr-FR<\/option>\r\n                <\/select>\r\n                <div class=\"error\" data-error-for=\"regionFormat\"><\/div>\r\n                <div class=\"hint\" id=\"numberSampleHint\"><\/div>\r\n              <\/div>\r\n            <\/div>\r\n          <\/div>\r\n        <\/section>\r\n      <\/section>\r\n\r\n      <!-- Panel: Support -->\r\n      <section id=\"panel-support\" class=\"panel\" role=\"tabpanel\" aria-labelledby=\"tab-support\" tabindex=\"0\">\r\n        <section class=\"card\">\r\n          <div class=\"card-h\">\r\n            <div class=\"card-t\">Support Contact Info<\/div>\r\n            <div class=\"card-d\">Where customers can reach your team<\/div>\r\n          <\/div>\r\n          <div class=\"card-c\">\r\n            <div class=\"grid-3\">\r\n              <div class=\"field\">\r\n                <label for=\"supportEmail\">Support Email<\/label>\r\n                <input id=\"supportEmail\" name=\"supportEmail\" type=\"email\" placeholder=\"support@company.com\"\/>\r\n                <div class=\"error\" data-error-for=\"supportEmail\"><\/div>\r\n              <\/div>\r\n              <div class=\"field\">\r\n                <label for=\"supportPhone\">Support Phone<\/label>\r\n                <input id=\"supportPhone\" name=\"supportPhone\" type=\"tel\" placeholder=\"+63 2 555 1234\"\/>\r\n              <\/div>\r\n              <div class=\"field\">\r\n                <label for=\"supportWebsite\">Support Website<\/label>\r\n                <input id=\"supportWebsite\" name=\"supportWebsite\" type=\"url\" placeholder=\"https:\/\/status.company.com\"\/>\r\n                <div class=\"error\" data-error-for=\"supportWebsite\"><\/div>\r\n              <\/div>\r\n            <\/div>\r\n          <\/div>\r\n        <\/section>\r\n      <\/section>\r\n\r\n      <!-- Panel: Branding -->\r\n      <section id=\"panel-branding\" class=\"panel\" role=\"tabpanel\" aria-labelledby=\"tab-branding\" tabindex=\"0\">\r\n        <section class=\"card\">\r\n          <div class=\"card-h\">\r\n            <div class=\"card-t\">Branding & Theme<\/div>\r\n            <div class=\"card-d\">Colors, header style, and page background<\/div>\r\n          <\/div>\r\n          <div class=\"card-c\">\r\n            <div class=\"grid-2\">\r\n              <div class=\"field\">\r\n                <label for=\"primaryColor\">Primary Color<\/label>\r\n                <div class=\"row\">\r\n                  <input id=\"primaryColor\" name=\"primaryColor\" type=\"color\" value=\"#2d6bff\" style=\"width:54px; height:42px; padding:0\"\/>\r\n                  <input id=\"primaryHex\" type=\"text\" placeholder=\"#2d6bff\" value=\"#2d6bff\"\/>\r\n                <\/div>\r\n              <\/div>\r\n              <div class=\"field\">\r\n                <label for=\"accentColor\">Accent Color<\/label>\r\n                <div class=\"row\">\r\n                  <input id=\"accentColor\" name=\"accentColor\" type=\"color\" value=\"#0ba98b\" style=\"width:54px; height:42px; padding:0\"\/>\r\n                  <input id=\"accentHex\" type=\"text\" placeholder=\"#0ba98b\" value=\"#0ba98b\"\/>\r\n                <\/div>\r\n              <\/div>\r\n            <\/div>\r\n\r\n            <div class=\"row\" style=\"margin-top:8px\">\r\n              <span class=\"pill\"><input id=\"darkMode\" type=\"checkbox\" style=\"accent-color:var(--primary)\"\/> <span>Use dark header<\/span><\/span>\r\n            <\/div>\r\n\r\n            <div class=\"sep\"><\/div>\r\n\r\n            <!-- Background controls -->\r\n            <div class=\"field\">\r\n              <label for=\"bgType\">Background<\/label>\r\n              <select id=\"bgType\" name=\"bgType\">\r\n                <option value=\"default\">Default<\/option>\r\n                <option value=\"solid\">Solid Color<\/option>\r\n                <option value=\"gradient\">Gradient<\/option>\r\n                <option value=\"image\">Image<\/option>\r\n              <\/select>\r\n              <div class=\"hint\">Affects the page background behind cards.<\/div>\r\n            <\/div>\r\n\r\n            <!-- Solid -->\r\n            <div id=\"bgSolidGroup\" class=\"bg-grid\" style=\"display:none\">\r\n              <div class=\"field\">\r\n                <label for=\"bgSolidColor\">Solid Color<\/label>\r\n                <div class=\"row\">\r\n                  <input id=\"bgSolidColor\" type=\"color\" value=\"#f6f8fb\" style=\"width:54px; height:42px; padding:0\"\/>\r\n                  <input id=\"bgSolidHex\" type=\"text\" placeholder=\"#f6f8fb\" value=\"#f6f8fb\"\/>\r\n                <\/div>\r\n              <\/div>\r\n            <\/div>\r\n\r\n            <!-- Gradient -->\r\n            <div id=\"bgGradientGroup\" class=\"bg-grid-3\" style=\"display:none\">\r\n              <div class=\"field\">\r\n                <label for=\"bgGradStart\">Start<\/label>\r\n                <div class=\"row\">\r\n                  <input id=\"bgGradStart\" type=\"color\" value=\"#f6f8fb\" style=\"width:54px; height:42px; padding:0\"\/>\r\n                  <input id=\"bgGradStartHex\" type=\"text\" placeholder=\"#f6f8fb\" value=\"#f6f8fb\"\/>\r\n                <\/div>\r\n              <\/div>\r\n              <div class=\"field\">\r\n                <label for=\"bgGradEnd\">End<\/label>\r\n                <div class=\"row\">\r\n                  <input id=\"bgGradEnd\" type=\"color\" value=\"#ffffff\" style=\"width:54px; height:42px; padding:0\"\/>\r\n                  <input id=\"bgGradEndHex\" type=\"text\" placeholder=\"#ffffff\" value=\"#ffffff\"\/>\r\n                <\/div>\r\n              <\/div>\r\n              <div class=\"field\">\r\n                <label for=\"bgGradAngle\">Angle<\/label>\r\n                <input id=\"bgGradAngle\" type=\"range\" min=\"0\" max=\"360\" value=\"180\"\/>\r\n                <div class=\"hint\"><span id=\"bgGradAngleVal\">180<\/span>\u00b0<\/div>\r\n              <\/div>\r\n            <\/div>\r\n\r\n            <!-- Image -->\r\n            <div id=\"bgImageGroup\" style=\"display:none\">\r\n              <div class=\"upload\" data-upload=\"bgImage\">\r\n                <input type=\"file\" accept=\"image\/*\"\/>\r\n                <div>Click or drop a background image here<\/div>\r\n              <\/div>\r\n              <div class=\"grid-2\" style=\"margin-top:12px\">\r\n                <div class=\"field\">\r\n                  <label for=\"bgImageMode\">Sizing<\/label>\r\n                  <select id=\"bgImageMode\">\r\n                    <option value=\"cover\">Cover<\/option>\r\n                    <option value=\"contain\">Contain<\/option>\r\n                    <option value=\"auto\">Auto<\/option>\r\n                  <\/select>\r\n                <\/div>\r\n                <div class=\"field\">\r\n                  <label for=\"bgImagePos\">Position<\/label>\r\n                  <select id=\"bgImagePos\">\r\n                    <option value=\"center center\">Center<\/option>\r\n                    <option value=\"top center\">Top<\/option>\r\n                    <option value=\"bottom center\">Bottom<\/option>\r\n                    <option value=\"center left\">Left<\/option>\r\n                    <option value=\"center right\">Right<\/option>\r\n                  <\/select>\r\n                <\/div>\r\n              <\/div>\r\n              <input id=\"bgImage\" type=\"hidden\" \/>\r\n              <div class=\"hint\">Large images work best. Consider a subtle abstract for corporate look.<\/div>\r\n            <\/div>\r\n          <\/div>\r\n        <\/section>\r\n\r\n        <!-- Actions -->\r\n        <div class=\"toolbar\">\r\n          <button type=\"button\" class=\"btn danger\" id=\"resetBtn\">Restore defaults<\/button>\r\n          <button type=\"reset\" class=\"btn ghost\" id=\"cancelBtn\">Cancel<\/button>\r\n          <button type=\"submit\" class=\"btn primary\" id=\"saveBtn\" disabled>\r\n            <span id=\"saveSpinner\" class=\"spinner\" style=\"display:none\"><\/span>\r\n            <span id=\"saveText\">Save Changes<\/span>\r\n          <\/button>\r\n        <\/div>\r\n      <\/section>\r\n    <\/div>\r\n\r\n    <!-- RIGHT: Branding preview (Localization preview removed) -->\r\n    <aside aria-label=\"Branding Preview\">\r\n      <section class=\"card\">\r\n        <div class=\"card-h\">\r\n          <div class=\"card-t\">Branding Preview<\/div>\r\n          <div class=\"card-d\">Logo, colors, and header style<\/div>\r\n        <\/div>\r\n        <div class=\"card-c\">\r\n          <div id=\"brandPreview\" class=\"brand-preview\">\r\n            <div id=\"brandHeader\" class=\"brand-header\">Acme Support<\/div>\r\n            <div style=\"display:flex; gap:12px; padding:12px 14px; align-items:center\">\r\n              <img id=\"brandLogo\" class=\"logo\" alt=\"logo\"\/>\r\n              <div style=\"flex:1\">\r\n                <div style=\"font-weight:700; margin-bottom:6px\">Welcome back, <span id=\"brandName\">Jane Doe<\/span><\/div>\r\n                <div class=\"subtle\" id=\"brandSub\">Your workspace is using en-PH \u00b7 Asia\/Manila<\/div>\r\n              <\/div>\r\n              <button class=\"btn\" type=\"button\">Primary Button<\/button>\r\n              <button class=\"btn\" type=\"button\" style=\"border-color:transparent; background:var(--accent); color:#fff\">Accent<\/button>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      <\/section>\r\n    <\/aside>\r\n  <\/form>\r\n\r\n  <div id=\"toast\" class=\"toast\" role=\"status\" aria-live=\"polite\"><\/div>\r\n\r\n<script>\r\n\/* ===========================\r\n   Helpers & Defaults\r\n=========================== *\/\r\nconst STORAGE_KEY = \"ticketing.admin.profile.org\";\r\nconst $ = (sel, ctx=document) => ctx.querySelector(sel);\r\nconst $$ = (sel, ctx=document) => Array.from(ctx.querySelectorAll(sel));\r\nconst setText = (el, t) => el && (el.textContent = t ?? \"\");\r\n\r\nconst defaults = {\r\n  \/\/ Admin\r\n  name: \"Jane Doe\",\r\n  username: \"janedoe\",\r\n  email: \"jane@acme.test\",\r\n  phone: \"+63 900 000 0000\",\r\n  designation: \"Support Lead\",\r\n  photo: \"\",\r\n  \/\/ Org\r\n  companyName: \"Acme Support\",\r\n  timezone: \"Asia\/Manila\",\r\n  dateFormat: \"YYYY-MM-DD\",\r\n  regionFormat: \"en-PH\",\r\n  supportEmail: \"support@acme.test\",\r\n  supportPhone: \"+63 2 555 1234\",\r\n  supportWebsite: \"https:\/\/status.acme.test\",\r\n  logo: \"\",\r\n  \/\/ Branding\r\n  primaryColor: \"#2d6bff\",\r\n  accentColor: \"#0ba98b\",\r\n  darkMode: false,\r\n\r\n  \/\/ Background\r\n  bgType: \"default\",              \/\/ default | solid | gradient | image\r\n  bgSolidColor: \"#f6f8fb\",\r\n  bgGradStart: \"#f6f8fb\",\r\n  bgGradEnd: \"#ffffff\",\r\n  bgGradAngle: 180,\r\n  bgImage: \"\",                    \/\/ dataURL\r\n  bgImageMode: \"cover\",           \/\/ cover | contain | auto\r\n  bgImagePos: \"center center\"\r\n};\r\n\r\nconst TIMEZONES = [\r\n  \"UTC\",\r\n  \"Pacific\/Auckland\",\"Australia\/Sydney\",\"Asia\/Tokyo\",\"Asia\/Manila\",\"Asia\/Singapore\",\"Asia\/Hong_Kong\",\"Asia\/Kolkata\",\r\n  \"Asia\/Dubai\",\"Europe\/Moscow\",\"Europe\/Berlin\",\"Europe\/Paris\",\"Europe\/London\",\r\n  \"Africa\/Johannesburg\",\"Atlantic\/Reykjavik\",\r\n  \"America\/Sao_Paulo\",\"America\/New_York\",\"America\/Chicago\",\"America\/Denver\",\"America\/Los_Angeles\",\"America\/Vancouver\"\r\n];\r\n\r\nfunction showToast(msg){\r\n  const t = $(\"#toast\");\r\n  t.textContent = msg;\r\n  t.classList.add(\"show\");\r\n  setTimeout(()=>t.classList.remove(\"show\"), 1700);\r\n}\r\n\r\nfunction readFileAsDataURL(file){\r\n  return new Promise((res, rej)=>{\r\n    const fr = new FileReader();\r\n    fr.onload = () => res(fr.result);\r\n    fr.onerror = rej;\r\n    fr.readAsDataURL(file);\r\n  });\r\n}\r\n\r\nfunction formatWithPattern(date, pattern){\r\n  const yyyy = String(date.getFullYear());\r\n  const mm = String(date.getMonth()+1).padStart(2,\"0\");\r\n  const dd = String(date.getDate()).padStart(2,\"0\");\r\n  switch(pattern){\r\n    case \"YYYY-MM-DD\": return `${yyyy}-${mm}-${dd}`;\r\n    case \"DD\/MM\/YYYY\": return `${dd}\/${mm}\/${yyyy}`;\r\n    case \"MM\/DD\/YYYY\": return `${mm}\/${dd}\/${yyyy}`;\r\n    default: return date.toISOString();\r\n  }\r\n}\r\n\r\n\/* ===========================\r\n   Tabs (mouse, keyboard, hash)\r\n=========================== *\/\r\nconst TAB_IDS = [\"profile\",\"organization\",\"support\",\"branding\"];\r\nfunction setActiveTab(id, {focusPanel=true, pushHash=true}={}){\r\n  TAB_IDS.forEach(t=>{\r\n    const tab = $(`#tab-${t}`);\r\n    const panel = $(`#panel-${t}`);\r\n    const sel = t === id;\r\n    tab.setAttribute(\"aria-selected\", sel ? \"true\" : \"false\");\r\n    panel.classList.toggle(\"active\", sel);\r\n  });\r\n  if(focusPanel) $(`#panel-${id}`).focus();\r\n  if(pushHash){\r\n    history.replaceState(null,\"\",`#tab=${id}`);\r\n  }\r\n}\r\nfunction currentTabFromHash(){\r\n  const m = location.hash.match(\/tab=([a-z]+)\/i);\r\n  return (m && TAB_IDS.includes(m[1])) ? m[1] : TAB_IDS[0];\r\n}\r\n\r\n\/* ===========================\r\n   Dirty state & Buttons\r\n=========================== *\/\r\nlet lastSaved = null;\r\nlet isDirty = false;\r\n\r\nfunction markDirty(){\r\n  if(!isDirty){\r\n    isDirty = true;\r\n    $(\"#saveBtn\").disabled = false;\r\n  }\r\n}\r\nfunction clearDirty(){\r\n  isDirty = false;\r\n  $(\"#saveBtn\").disabled = true;\r\n}\r\n\r\n\/* ===========================\r\n   Init selects & load data\r\n=========================== *\/\r\nfunction populateSelects(){\r\n  const tz = $(\"#timezone\");\r\n  tz.innerHTML = TIMEZONES.map(z => `<option value=\"${z}\">${z}<\/option>`).join(\"\");\r\n}\r\n\r\nfunction loadState(){\r\n  const saved = localStorage.getItem(STORAGE_KEY);\r\n  return saved ? JSON.parse(saved) : {...defaults};\r\n}\r\n\r\nfunction saveState(data){\r\n  localStorage.setItem(STORAGE_KEY, JSON.stringify(data));\r\n}\r\n\r\nfunction setFormValues(data){\r\n  for (const [k,v] of Object.entries(data)){\r\n    const el = document.getElementsByName(k)[0];\r\n    if(!el) continue;\r\n    if(el.type === \"checkbox\") el.checked = !!v;\r\n    else el.value = v ?? \"\";\r\n  }\r\n\r\n  \/\/ background controls (non-name inputs)\r\n  $(\"#bgType\").value = data.bgType || defaults.bgType;\r\n\r\n  $(\"#bgSolidColor\").value = data.bgSolidColor || defaults.bgSolidColor;\r\n  $(\"#bgSolidHex\").value   = data.bgSolidColor || defaults.bgSolidColor;\r\n\r\n  $(\"#bgGradStart\").value   = data.bgGradStart || defaults.bgGradStart;\r\n  $(\"#bgGradStartHex\").value= data.bgGradStart || defaults.bgGradStart;\r\n  $(\"#bgGradEnd\").value     = data.bgGradEnd || defaults.bgGradEnd;\r\n  $(\"#bgGradEndHex\").value  = data.bgGradEnd || defaults.bgGradEnd;\r\n  $(\"#bgGradAngle\").value   = data.bgGradAngle ?? defaults.bgGradAngle;\r\n  $(\"#bgGradAngleVal\").textContent = $(\"#bgGradAngle\").value;\r\n\r\n  $(\"#bgImage\").value      = data.bgImage || \"\";\r\n  $(\"#bgImageMode\").value  = data.bgImageMode || defaults.bgImageMode;\r\n  $(\"#bgImagePos\").value   = data.bgImagePos || defaults.bgImagePos;\r\n\r\n  \/\/ color hex <-> picker sync\r\n  $(\"#primaryHex\").value = data.primaryColor || defaults.primaryColor;\r\n  $(\"#primaryColor\").value = data.primaryColor || defaults.primaryColor;\r\n  $(\"#accentHex\").value  = data.accentColor || defaults.accentColor;\r\n  $(\"#accentColor\").value= data.accentColor || defaults.accentColor;\r\n\r\n  \/\/ previews\r\n  if(data.photo) $(\"#photoPreview\").src = data.photo; else $(\"#photoPreview\").removeAttribute(\"src\");\r\n  if(data.logo) $(\"#logoPreview\").src = data.logo; else $(\"#logoPreview\").removeAttribute(\"src\");\r\n\r\n  \/\/ Show\/hide bg groups per type\r\n  toggleBgGroups($(\"#bgType\").value);\r\n\r\n  applyBackground();     \/\/ apply page background\r\n  updateBrandPreview();  \/\/ apply header\/logo preview\r\n  updateFormatHints();   \/\/ update small hints for date\/number\r\n}\r\n\r\nfunction getFormValues(){\r\n  const form = $(\"#settingsForm\");\r\n  const data = {...defaults};\r\n  $$(\"input, select\", form).forEach(el=>{\r\n    if(!el.name) return;\r\n    data[el.name] = (el.type===\"checkbox\") ? el.checked : el.value.trim();\r\n  });\r\n\r\n  \/\/ sync brand color hex inputs\r\n  data.primaryColor = $(\"#primaryHex\").value.trim() || defaults.primaryColor;\r\n  data.accentColor  = $(\"#accentHex\").value.trim()  || defaults.accentColor;\r\n\r\n  \/\/ background controls\r\n  data.bgType       = $(\"#bgType\").value;\r\n  data.bgSolidColor = $(\"#bgSolidHex\").value.trim() || $(\"#bgSolidColor\").value || defaults.bgSolidColor;\r\n\r\n  data.bgGradStart  = $(\"#bgGradStartHex\").value.trim() || $(\"#bgGradStart\").value || defaults.bgGradStart;\r\n  data.bgGradEnd    = $(\"#bgGradEndHex\").value.trim()   || $(\"#bgGradEnd\").value   || defaults.bgGradEnd;\r\n  data.bgGradAngle  = parseInt($(\"#bgGradAngle\").value || defaults.bgGradAngle, 10);\r\n\r\n  data.bgImage      = $(\"#bgImage\").value || \"\";\r\n  data.bgImageMode  = $(\"#bgImageMode\").value || defaults.bgImageMode;\r\n  data.bgImagePos   = $(\"#bgImagePos\").value || defaults.bgImagePos;\r\n\r\n  return data;\r\n}\r\n\r\n\/* ===========================\r\n   Validation\r\n=========================== *\/\r\nconst emailRegex = \/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$\/;\r\nconst urlRegex = \/^https?:\\\/\\\/[^\\s]+$\/i;\r\n\r\nfunction clearErrors(){\r\n  $$(\".error\").forEach(e=>e.textContent=\"\");\r\n}\r\n\r\nfunction setError(name, msg){\r\n  const holder = document.querySelector(`.error[data-error-for=\"${name}\"]`);\r\n  if(holder) holder.textContent = msg;\r\n}\r\n\r\nfunction validate(data){\r\n  clearErrors();\r\n  let ok = true;\r\n  if(!data.name)      { setError(\"name\",\"Required\"); ok=false; }\r\n  if(!data.username)  { setError(\"username\",\"Required\"); ok=false; }\r\n  if(!data.companyName){ setError(\"companyName\",\"Required\"); ok=false; }\r\n  if(!data.timezone)  { setError(\"timezone\",\"Required\"); ok=false; }\r\n  if(!data.dateFormat){ setError(\"dateFormat\",\"Required\"); ok=false; }\r\n  if(!data.regionFormat){ setError(\"regionFormat\",\"Required\"); ok=false; }\r\n  if(!data.email || !emailRegex.test(data.email)){ setError(\"email\",\"Enter a valid email\"); ok=false; }\r\n  if(data.supportEmail && !emailRegex.test(data.supportEmail)){ setError(\"supportEmail\",\"Invalid email\"); ok=false; }\r\n  if(data.supportWebsite && !urlRegex.test(data.supportWebsite)){ setError(\"supportWebsite\",\"Invalid URL (https:\/\/...)\"); ok=false; }\r\n  return ok;\r\n}\r\n\r\n\/* ===========================\r\n   Uploads (photo, logo, background image)\r\n=========================== *\/\r\nfunction handleUpload(boxId, hiddenId, previewId){\r\n  const box = document.querySelector(`.upload[data-upload=\"${boxId}\"]`);\r\n  const input = $(\"input\", box);\r\n  const hidden = hiddenId ? $(\"#\"+hiddenId) : null;\r\n  const preview = previewId ? $(\"#\"+previewId) : null;\r\n\r\n  function applyFile(file){\r\n    if(!file) return;\r\n    if(file.size > 4_000_000){ showToast(\"Image too large (~4MB max)\"); return; }\r\n    readFileAsDataURL(file).then(dataUrl=>{\r\n      if(hidden) hidden.value = dataUrl;\r\n      if(preview){ preview.src = dataUrl; }\r\n      if(boxId === \"bgImage\"){ applyBackground(); }\r\n      else { updateBrandPreview(); }\r\n      markDirty();\r\n    });\r\n  }\r\n\r\n  box.addEventListener(\"dragover\", e=>{ e.preventDefault(); box.style.borderColor=\"var(--primary)\"; });\r\n  box.addEventListener(\"dragleave\", ()=> box.style.borderColor=\"#dfe5ef\");\r\n  box.addEventListener(\"drop\", e=>{\r\n    e.preventDefault(); box.style.borderColor=\"#dfe5ef\";\r\n    applyFile(e.dataTransfer.files[0]);\r\n  });\r\n  input.addEventListener(\"change\", e=> applyFile(e.target.files[0]));\r\n}\r\n\r\nfunction removeImage(hiddenId, previewId){\r\n  $(\"#\"+hiddenId).value = \"\";\r\n  if(previewId) $(\"#\"+previewId).removeAttribute(\"src\");\r\n  updateBrandPreview();\r\n  applyBackground();\r\n  markDirty();\r\n}\r\n\r\n\/* ===========================\r\n   Background application\r\n=========================== *\/\r\nfunction toggleBgGroups(type){\r\n  $(\"#bgSolidGroup\").style.display    = (type===\"solid\")    ? \"grid\" : \"none\";\r\n  $(\"#bgGradientGroup\").style.display = (type===\"gradient\") ? \"grid\" : \"none\";\r\n  $(\"#bgImageGroup\").style.display    = (type===\"image\")    ? \"block\" : \"none\";\r\n}\r\n\r\nfunction applyBackground(){\r\n  const type = $(\"#bgType\").value;\r\n  if(type === \"default\"){\r\n    document.body.style.background = defaults.bgSolidColor;\r\n    return;\r\n  }\r\n  if(type === \"solid\"){\r\n    const c = $(\"#bgSolidHex\").value || $(\"#bgSolidColor\").value || defaults.bgSolidColor;\r\n    document.body.style.background = c;\r\n    return;\r\n  }\r\n  if(type === \"gradient\"){\r\n    const a = parseInt($(\"#bgGradAngle\").value || defaults.bgGradAngle, 10);\r\n    const s = $(\"#bgGradStartHex\").value || $(\"#bgGradStart\").value || defaults.bgGradStart;\r\n    const e = $(\"#bgGradEndHex\").value   || $(\"#bgGradEnd\").value   || defaults.bgGradEnd;\r\n    document.body.style.background = `linear-gradient(${a}deg, ${s}, ${e})`;\r\n    return;\r\n  }\r\n  if(type === \"image\"){\r\n    const dataUrl = $(\"#bgImage\").value;\r\n    if(!dataUrl){ document.body.style.background = defaults.bgSolidColor; return; }\r\n    const size = $(\"#bgImageMode\").value;\r\n    const pos  = $(\"#bgImagePos\").value;\r\n    document.body.style.background = `url(${dataUrl}) no-repeat ${pos} \/ ${size} ${defaults.bgSolidColor}`;\r\n    return;\r\n  }\r\n}\r\n\r\n\/* ===========================\r\n   Small hints (date & number) \u2014 replaces removed localization card\r\n=========================== *\/\r\nfunction updateFormatHints(){\r\n  const region = $(\"#regionFormat\").value || defaults.regionFormat;\r\n  const now = new Date();\r\n  $(\"#dateSampleHint\").textContent = `Preview: ${formatWithPattern(now, $(\"#dateFormat\").value)}`;\r\n  $(\"#numberSampleHint\").textContent = `Preview: ${new Intl.NumberFormat(region).format(1234567.89)}`;\r\n}\r\n\r\n\/* ===========================\r\n   Brand Preview\r\n=========================== *\/\r\nfunction updateBrandPreview(){\r\n  const name = $(\"#name\").value || defaults.name;\r\n  const company = $(\"#companyName\").value || defaults.companyName;\r\n  const tz = $(\"#timezone\").value || defaults.timezone;\r\n  const region = $(\"#regionFormat\").value || defaults.regionFormat;\r\n  const primary = $(\"#primaryHex\").value || defaults.primaryColor;\r\n  const accent  = $(\"#accentHex\").value || defaults.accentColor;\r\n  const dark = $(\"#darkMode\").checked;\r\n\r\n  \/\/ live theme updates\r\n  document.documentElement.style.setProperty(\"--primary\", primary);\r\n  document.documentElement.style.setProperty(\"--accent\", accent);\r\n  document.documentElement.style.setProperty(\"--focus\", hexToRgba(primary, .18));\r\n\r\n  $(\"#brandHeader\").style.background = dark ? \"var(--primary)\" : \"#f6f8fe\";\r\n  $(\"#brandHeader\").style.color = dark ? \"#ffffff\" : \"var(--text)\";\r\n  $(\"#brandHeader\").textContent = company;\r\n  setText($(\"#brandName\"), name);\r\n  setText($(\"#brandSub\"), `Your workspace is using ${region} \u00b7 ${tz}`);\r\n\r\n  const logo = $(\"#logo\").value;\r\n  const img = $(\"#brandLogo\");\r\n  if(logo){ img.src = logo; img.style.display=\"block\"; } else { img.removeAttribute(\"src\"); img.style.display=\"none\"; }\r\n}\r\n\r\n\/* Utility: convert HEX to rgba alpha for nicer focus ring *\/\r\nfunction hexToRgba(hex, a){\r\n  const h = hex.replace('#','');\r\n  const bigint = parseInt(h.length===3 ? h.split('').map(x=>x+x).join('') : h, 16);\r\n  const r = (bigint >> 16) & 255, g = (bigint >> 8) & 255, b = bigint & 255;\r\n  return `rgba(${r},${g},${b},${a})`;\r\n}\r\n\r\n\/* ===========================\r\n   Wire up\r\n=========================== *\/\r\ndocument.addEventListener(\"DOMContentLoaded\", ()=>{\r\n  \/\/ Tabs init\r\n  const initial = (location.hash.match(\/tab=([a-z]+)\/i)?.[1]) || \"profile\";\r\n  setActiveTab(initial, {focusPanel:false, pushHash:false});\r\n  $$(\".tab\").forEach((btn, i)=>{\r\n    btn.addEventListener(\"click\", ()=> setActiveTab([\"profile\",\"organization\",\"support\",\"branding\"][i]));\r\n    btn.addEventListener(\"keydown\", (e)=>{\r\n      if(e.key === \"ArrowRight\"){ e.preventDefault(); setActiveTab([\"profile\",\"organization\",\"support\",\"branding\"][(i+1)%4]); }\r\n      if(e.key === \"ArrowLeft\"){ e.preventDefault(); setActiveTab([\"profile\",\"organization\",\"support\",\"branding\"][(i+3)%4]); }\r\n    });\r\n  });\r\n  window.addEventListener(\"hashchange\", ()=>{\r\n    const id = (location.hash.match(\/tab=([a-z]+)\/i)?.[1]) || \"profile\";\r\n    setActiveTab(id);\r\n  });\r\n\r\n  populateSelects();\r\n\r\n  \/\/ sync brand color pickers <-> hex inputs\r\n  $(\"#primaryColor\").addEventListener(\"input\", e=> { $(\"#primaryHex\").value = e.target.value; updateBrandPreview(); markDirty(); });\r\n  $(\"#accentColor\").addEventListener(\"input\", e=> { $(\"#accentHex\").value = e.target.value; updateBrandPreview(); markDirty(); });\r\n  $(\"#primaryHex\").addEventListener(\"input\", e=> { $(\"#primaryColor\").value = e.target.value; updateBrandPreview(); markDirty(); });\r\n  $(\"#accentHex\").addEventListener(\"input\", e=> { $(\"#accentColor\").value = e.target.value; updateBrandPreview(); markDirty(); });\r\n\r\n  \/\/ background: show\/hide groups\r\n  $(\"#bgType\").addEventListener(\"change\", ()=>{ toggleBgGroups($(\"#bgType\").value); applyBackground(); markDirty(); });\r\n\r\n  \/\/ solid\r\n  $(\"#bgSolidColor\").addEventListener(\"input\", e=> { $(\"#bgSolidHex\").value = e.target.value; applyBackground(); markDirty(); });\r\n  $(\"#bgSolidHex\").addEventListener(\"input\", e=> { $(\"#bgSolidColor\").value = e.target.value; applyBackground(); markDirty(); });\r\n\r\n  \/\/ gradient\r\n  $(\"#bgGradStart\").addEventListener(\"input\", e=> { $(\"#bgGradStartHex\").value = e.target.value; applyBackground(); markDirty(); });\r\n  $(\"#bgGradStartHex\").addEventListener(\"input\", e=> { $(\"#bgGradStart\").value = e.target.value; applyBackground(); markDirty(); });\r\n  $(\"#bgGradEnd\").addEventListener(\"input\", e=> { $(\"#bgGradEndHex\").value = e.target.value; applyBackground(); markDirty(); });\r\n  $(\"#bgGradEndHex\").addEventListener(\"input\", e=> { $(\"#bgGradEnd\").value = e.target.value; applyBackground(); markDirty(); });\r\n  $(\"#bgGradAngle\").addEventListener(\"input\", e=> { $(\"#bgGradAngleVal\").textContent = e.target.value; applyBackground(); markDirty(); });\r\n\r\n  \/\/ image upload + controls\r\n  handleUpload(\"bgImage\",\"bgImage\", null);\r\n  $(\"#bgImageMode\").addEventListener(\"change\", ()=>{ applyBackground(); markDirty(); });\r\n  $(\"#bgImagePos\").addEventListener(\"change\", ()=>{ applyBackground(); markDirty(); });\r\n\r\n  \/\/ uploads (photo, logo)\r\n  handleUpload(\"photo\",\"photo\",\"photoPreview\");\r\n  handleUpload(\"logo\",\"logo\",\"logoPreview\");\r\n  $(\"#photoRemove\").addEventListener(\"click\", ()=> removeImage(\"photo\",\"photoPreview\"));\r\n  $(\"#logoRemove\").addEventListener(\"click\", ()=> removeImage(\"logo\",\"logoPreview\"));\r\n\r\n  \/\/ load saved\/defaults\r\n  const state = loadState();\r\n  setFormValues(state);\r\n  lastSaved = getFormValues(); \/\/ snapshot\r\n\r\n  \/\/ mark dirty on any change of named inputs\/selects\r\n  $$(\"input, select\").forEach(el=>{\r\n    el.addEventListener(el.type===\"checkbox\"?\"change\":\"input\", ()=>{\r\n      updateBrandPreview();\r\n      updateFormatHints();\r\n      markDirty();\r\n    });\r\n  });\r\n\r\n  \/\/ submit\r\n  $(\"#settingsForm\").addEventListener(\"submit\", async (e)=>{\r\n    e.preventDefault();\r\n    const data = getFormValues();\r\n    if(!validate(data)) { showToast(\"Please fix the errors\"); return; }\r\n\r\n    \/\/ Save loading state\r\n    $(\"#saveSpinner\").style.display = \"inline-block\";\r\n    $(\"#saveText\").textContent = \"Saving\u2026\";\r\n    $(\"#saveBtn\").disabled = true;\r\n\r\n    \/\/ simulate short save delay\r\n    await new Promise(r=>setTimeout(r, 600));\r\n\r\n    saveState(data);\r\n    lastSaved = data;\r\n    clearDirty();\r\n    applyBackground();\r\n    updateBrandPreview();\r\n    updateFormatHints();\r\n    $(\"#saveSpinner\").style.display = \"none\";\r\n    $(\"#saveText\").textContent = \"Save Changes\";\r\n    showToast(\"Saved \u2713\");\r\n  });\r\n\r\n  \/\/ cancel (reset to last saved)\r\n  $(\"#cancelBtn\").addEventListener(\"click\", (e)=>{\r\n    if(isDirty){\r\n      const confirmCancel = confirm(\"Discard unsaved changes?\");\r\n      if(!confirmCancel){ e.preventDefault(); return; }\r\n    }\r\n  });\r\n  $(\"#settingsForm\").addEventListener(\"reset\", ()=>{\r\n    \/\/ restore snapshot\r\n    setTimeout(()=> {\r\n      setFormValues(lastSaved || loadState());\r\n      clearDirty();\r\n      showToast(\"Changes reverted\");\r\n    }, 0);\r\n  });\r\n\r\n  \/\/ restore defaults (not saved)\r\n  $(\"#resetBtn\").addEventListener(\"click\", ()=>{\r\n    const ok = confirm(\"Restore default values? This won\u2019t be saved until you click Save.\");\r\n    if(!ok) return;\r\n    setFormValues({...defaults});\r\n    markDirty();\r\n    showToast(\"Defaults restored (not saved yet)\");\r\n  });\r\n\r\n  \/\/ Warn on page unload if dirty\r\n  window.addEventListener(\"beforeunload\", (e)=>{\r\n    if(isDirty){\r\n      e.preventDefault();\r\n      e.returnValue = \"\";\r\n    }\r\n  });\r\n});\r\n<\/script>\r\n<\/body>\r\n<\/html>\r\n\r\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div id=\"e-n-tab-content-113480932\" role=\"tabpanel\" aria-labelledby=\"e-n-tab-title-113480932\" data-tab-index=\"2\" style=\"--n-tabs-title-order: 2;\" class=\" elementor-element elementor-element-1b1cb25 e-con-full e-flex e-con e-child\" data-id=\"1b1cb25\" data-element_type=\"container\" data-settings=\"{&quot;position&quot;:&quot;absolute&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-cad77bb elementor-widget elementor-widget-html\" data-id=\"cad77bb\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n<meta charset=\"UTF-8\"\/>\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\/>\r\n<title>Security & Login \u2013 Settings<\/title>\r\n<style>\r\n  :root{\r\n    --bg:#f6f8fb;\r\n    --surface:#ffffff;\r\n    --text:#1e2430;\r\n    --muted:#6b7280;\r\n    --line:#e7eaf2;\r\n    --primary:#2d6bff;\r\n    --focus:rgba(45,107,255,.18);\r\n    --danger:#d92d20;\r\n    --good:#16a34a;\r\n    --radius-lg:16px;\r\n    --radius-md:12px;\r\n    --shadow-sm:0 1px 2px rgba(16,24,40,.06);\r\n    --shadow-md:0 6px 18px rgba(16,24,40,.08);\r\n  }\r\n  *{box-sizing:border-box}\r\n  body{\r\n    margin:0;\r\n    font-family:Inter,ui-sans-serif,system-ui;\r\n    -webkit-font-smoothing:antialiased;\r\n    color:var(--text);\r\n    background:var(--bg);\r\n    padding:28px\r\n  }\r\n  header{\r\n    max-width:1100px;\r\n    margin:0 auto 20px\r\n    text-align: left;\r\n  }\r\n  .h1{\r\n    font-size:22px;\r\n    font-weight:700;\r\n    margin:0 0 6px\r\n    letter-spacing:.2px;\r\n    text-align:left;\r\n    white-space:nowrap;        \r\n    display:block;\r\n  }\r\n  .subtle{\r\n    color:var(--muted)\r\n  }\r\n  .container{\r\n    max-width:1100px;\r\n    margin:0 auto;\r\n    display:grid;\r\n    gap:22px\r\n  }\r\n\r\n  .card{\r\n    background:var(--surface);\r\n    border:1px solid var(--line);\r\n    border-radius:var(--radius-lg);\r\n    box-shadow:var(--shadow-sm);\r\n    overflow:hidden\r\n  }\r\n  .card-h{\r\n    padding:18px 20px 12px;\r\n    border-bottom:1px solid var(--line);\r\n    background:linear-gradient(180deg,#fff,#fafbff)\r\n  }\r\n  .card-t{\r\n    font-weight:700\r\n  }\r\n  .card-d{\r\n    color:var(--muted);\r\n    font-size:13px;\r\n    margin-top:2px\r\n  }\r\n  .card-c{\r\n    padding:18px 20px\r\n  }\r\n\r\n  .grid-2{\r\n    display:grid;\r\n    grid-template-columns:1fr 1fr;\r\n    gap:14px\r\n  }\r\n  @media(max-width:860px){.grid-2{grid-template-columns:1fr}}\r\n\r\n  label{\r\n    display:block;\r\n    font-weight:600;\r\n    font-size:12px;\r\n    letter-spacing:.28px;\r\n    text-transform:uppercase;\r\n    color:#7b8497;\r\n    margin:6px 0 8px\r\n  }\r\n  input[type=\"text\"],\r\n  input[type=\"password\"],\r\n  input[type=\"tel\"]{\r\n    width:100%;\r\n    background:#fff;\r\n    border:1px solid var(--line);\r\n    color:var(--text);\r\n    padding:12px;\r\n    border-radius:var(--radius-md);\r\n    outline:none;\r\n    transition:border-color .18s,box-shadow .18s\r\n  }\r\n  input:focus{\r\n    border-color:var(--primary);\r\n    box-shadow:0 0 0 4px var(--focus)\r\n  }\r\n  .row{\r\n    display:flex;\r\n    gap:10px;\r\n    align-items:center;\r\n    flex-wrap:wrap\r\n  }\r\n  .right{\r\n    margin-left:auto\r\n  }\r\n\r\n  .btn{\r\n    border:1px solid var(--line);\r\n    background:#fff;\r\n    color:var(--text);\r\n    padding:10px 14px;\r\n    border-radius:10px;\r\n    cursor:pointer;\r\n    font-weight:600;\r\n    transition:all .15s\r\n  }\r\n  .btn:hover{\r\n    background:#f9fafe\r\n  }\r\n  .btn.primary{\r\n    background:var(--primary);\r\n    border-color:#275de0;\r\n    color:#fff\r\n  }\r\n  .btn.danger{\r\n    background:#fff5f5;\r\n    border-color:#ffd6d6;\r\n    color:#b42318\r\n  }\r\n  .btn.small{\r\n    padding:7px 10px\r\n  }\r\n  .btn[disabled]{\r\n    opacity:.6;\r\n    cursor:not-allowed\r\n  }\r\n\r\n  .hint{\r\n    color:var(--muted);\r\n    font-size:12px;\r\n    margin-top:6px\r\n  }\r\n  .error{\r\n    color:#b42318;\r\n    font-size:12px;\r\n    margin-top:6px\r\n  }\r\n  .badge{\r\n    display:inline-flex;\r\n    padding:5px 8px;\r\n    font-size:12px;\r\n    border-radius:999px;\r\n    border:1px solid var(--line);\r\n    background:#f7f8fc;\r\n    color:#4b5563\r\n  }\r\n  .badge.good{\r\n    background:#ecfdf5;\r\n    border-color:#a7f3d0;\r\n    color:#065f46\r\n  }\r\n  .badge.warn{\r\n    background:#fffbeb;\r\n    border-color:#fde68a;\r\n    color:#92400e\r\n  }\r\n  .sep{\r\n    height:1px;\r\n    background:var(--line);\r\n    margin:12px 0\r\n  }\r\n\r\n  table{\r\n    width:100%;\r\n    border-collapse:separate;\r\n    border-spacing:0 8px\r\n  }\r\n  th{\r\n    font-size:12px;\r\n    color:#7b8497;\r\n    text-align:left;\r\n    padding:0 10px\r\n  }\r\n  td{\r\n    background:#fff;\r\n    border:1px solid var(--line);\r\n    padding:10px;\r\n    border-radius:8px\r\n  }\r\n\r\n  .toast{\r\n    position:fixed;\r\n    right:20px;\r\n    bottom:20px;\r\n    background:#243b7b;\r\n    border:1px solid #314b95;\r\n    color:#e8efff;\r\n    padding:12px 14px;\r\n    border-radius:12px;\r\n    box-shadow:var(--shadow-md);\r\n    opacity:0;\r\n    transform:translateY(8px);\r\n    transition:.25s}\r\n  .toast.show{\r\n    opacity:1;\r\n    transform:translateY(0)\r\n  }\r\n\r\n  .strength{\r\n    height:8px;\r\n    border-radius:6px;\r\n    background:#eef1f7;\r\n    overflow:hidden\r\n  }\r\n  .strength>span{\r\n    display:block;\r\n    height:100%;\r\n    width:0;\r\n    transition:width .25s;\r\n    background:linear-gradient(90deg,#ef4444,#f59e0b,#22c55e)\r\n  }\r\n\r\n  \/* Modal *\/\r\n  .modal{\r\n    position:fixed;\r\n    inset:0;\r\n    display:none;\r\n    align-items:center;\r\n    justify-content:center;\r\n    background:rgba(2,8,23,.45);\r\n    z-index:50;\r\n    padding:22px\r\n  }\r\n  .modal.open{\r\n    display:flex\r\n  }\r\n  .dialog{\r\n    width:min(560px,96vw);\r\n    background:#fff;\r\n    border:1px solid var(--line);\r\n    border-radius:16px;\r\n    box-shadow:var(--shadow-md)\r\n  }\r\n  .dh{\r\n    padding:16px 18px;\r\n    border-bottom:1px solid var(--line)\r\n  }\r\n  .dc{\r\n    padding:16px 18px}\r\n  .df{\r\n    padding:14px 18px;\r\n    border-top:1px solid var(--line);\r\n    display:flex;gap:10px;\r\n    justify-content:flex-end\r\n  }\r\n  .token{\r\n    font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\r\n    background:#f7f8fc;\r\n    border:1px solid var(--line);\r\n    padding:8px 10px;\r\n    border-radius:8px\r\n    }\r\n<\/style>\r\n<\/head>\r\n<body>\r\n<header>\r\n  <div class=\"h1\">Security & Login<\/div>\r\n<\/header>\r\n\r\n<main class=\"container\">\r\n  <!-- Password -->\r\n  <section class=\"card\" aria-labelledby=\"pw-title\">\r\n    <div class=\"card-h\">\r\n      <div id=\"pw-title\" class=\"card-t\">Password Management<\/div>\r\n      <div class=\"card-d\">Change your password and keep your account secure<\/div>\r\n    <\/div>\r\n    <div class=\"card-c\">\r\n      <div class=\"grid-2\">\r\n        <div>\r\n          <label for=\"currentPw\">Current Password<\/label>\r\n          <div class=\"row\">\r\n            <input id=\"currentPw\" type=\"password\" placeholder=\"\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\" autocomplete=\"current-password\" \/>\r\n            <button type=\"button\" class=\"btn small\" data-toggle=\"currentPw\">Show<\/button>\r\n          <\/div>\r\n          <div class=\"error\" id=\"err-current\"><\/div>\r\n        <\/div>\r\n        <div><\/div>\r\n      <\/div>\r\n\r\n      <div class=\"grid-2\">\r\n        <div>\r\n          <label for=\"newPw\">New Password<\/label>\r\n          <div class=\"row\">\r\n            <input id=\"newPw\" type=\"password\" placeholder=\"At least 8 characters\" autocomplete=\"new-password\"\/>\r\n            <button type=\"button\" class=\"btn small\" data-toggle=\"newPw\">Show<\/button>\r\n          <\/div>\r\n          <div class=\"hint\">Use upper\/lowercase, number, and a symbol.<\/div>\r\n          <div class=\"strength\" style=\"margin-top:8px\"><span id=\"pwBar\"><\/span><\/div>\r\n          <div class=\"error\" id=\"err-new\"><\/div>\r\n        <\/div>\r\n        <div>\r\n          <label for=\"confirmPw\">Confirm New Password<\/label>\r\n          <div class=\"row\">\r\n            <input id=\"confirmPw\" type=\"password\" placeholder=\"Re-enter new password\" autocomplete=\"new-password\"\/>\r\n            <button type=\"button\" class=\"btn small\" data-toggle=\"confirmPw\">Show<\/button>\r\n          <\/div>\r\n          <div class=\"error\" id=\"err-confirm\"><\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <div class=\"row\" style=\"margin-top:10px\">\r\n        <button id=\"changePwBtn\" class=\"btn primary\">Change Password<\/button>\r\n        <span id=\"pwStatus\" class=\"hint\"><\/span>\r\n      <\/div>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- 2FA (SMS) -->\r\n  <section class=\"card\" aria-labelledby=\"sms-title\">\r\n    <div class=\"card-h\">\r\n      <div id=\"sms-title\" class=\"card-t\">Two-Factor Authentication (SMS)<\/div>\r\n      <div class=\"card-d\">Receive a one-time code via SMS when you sign in<\/div>\r\n    <\/div>\r\n    <div class=\"card-c\" id=\"twofaBlock\">\r\n      <div class=\"row\" style=\"margin-bottom:8px\">\r\n        <div id=\"twofaBadge\" class=\"badge warn\">2FA: <span id=\"twofaState\">Disabled<\/span><\/div>\r\n        <span id=\"twofaPhoneInfo\" class=\"hint\" style=\"margin-left:8px\"><\/span>\r\n        <button id=\"setup2faBtn\" class=\"btn primary right\">Enable SMS 2FA<\/button>\r\n        <button id=\"disable2faBtn\" class=\"btn danger right\" style=\"display:none\">Disable 2FA<\/button>\r\n      <\/div>\r\n      <div class=\"hint\">We\u2019ll send a 6-digit code to your mobile number when logging in.<\/div>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- Sessions -->\r\n  <section class=\"card\" aria-labelledby=\"sess-title\">\r\n    <div class=\"card-h\">\r\n      <div id=\"sess-title\" class=\"card-t\">Session Management<\/div>\r\n      <div class=\"card-d\">Review active sessions and sign out from devices you don\u2019t recognize<\/div>\r\n    <\/div>\r\n    <div class=\"card-c\">\r\n      <div class=\"row\" style=\"margin-bottom:8px\">\r\n        <div class=\"badge good\">Signed in<\/div>\r\n        <button id=\"logoutAllBtn\" class=\"btn danger right\">Logout from all devices<\/button>\r\n      <\/div>\r\n      <table aria-describedby=\"sess-title\">\r\n        <thead>\r\n          <tr><th>Device<\/th><th>Location<\/th><th>Last Active<\/th><th><\/th><\/tr>\r\n        <\/thead>\r\n        <tbody id=\"sessionsTbody\"><\/tbody>\r\n      <\/table>\r\n      <div class=\"hint\">Location is approximate (IP-based).<\/div>\r\n    <\/div>\r\n  <\/section>\r\n<\/main>\r\n\r\n<!-- SMS 2FA Modal -->\r\n<div class=\"modal\" id=\"twofaModal\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"twofaTitle\" aria-describedby=\"twofaDesc\">\r\n  <div class=\"dialog\">\r\n    <div class=\"dh\">\r\n      <div id=\"twofaTitle\" class=\"card-t\">Enable SMS Two-Factor Authentication<\/div>\r\n      <div id=\"twofaDesc\" class=\"card-d\">Enter your mobile number to receive a verification code<\/div>\r\n    <\/div>\r\n    <div class=\"dc\">\r\n      <div class=\"grid-2\">\r\n        <div>\r\n          <label for=\"smsPhone\">Mobile Number<\/label>\r\n          <input id=\"smsPhone\" type=\"tel\" placeholder=\"+63 900 000 0000\" \/>\r\n          <div class=\"hint\">Use international format (e.g., <strong>+63<\/strong> for PH). We\u2019ll mask it after saving.<\/div>\r\n          <div class=\"error\" id=\"err-phone\"><\/div>\r\n        <\/div>\r\n        <div>\r\n          <label for=\"smsCode\">Verification Code<\/label>\r\n          <div class=\"row\">\r\n            <input id=\"smsCode\" type=\"text\" inputmode=\"numeric\" maxlength=\"6\" placeholder=\"123456\" \/>\r\n            <button id=\"sendCodeBtn\" class=\"btn small\">Send Code<\/button>\r\n          <\/div>\r\n          <div class=\"hint\" id=\"smsHint\">A 6-digit code will be sent to your phone. <span id=\"demoCode\" class=\"token\" style=\"display:none\"><\/span><\/div>\r\n          <div class=\"error\" id=\"err-code\"><\/div>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n    <div class=\"df\">\r\n      <button class=\"btn\" id=\"cancel2faBtn\">Cancel<\/button>\r\n      <button class=\"btn primary\" id=\"enable2faConfirm\">Enable 2FA<\/button>\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<div id=\"toast\" class=\"toast\" role=\"status\" aria-live=\"polite\"><\/div>\r\n\r\n<script>\r\n\/* ===========================\r\n   Utilities & State\r\n=========================== *\/\r\nconst $ = (s,ctx=document)=>ctx.querySelector(s);\r\nconst $$ = (s,ctx=document)=>Array.from(ctx.querySelectorAll(s));\r\nconst STORAGE_KEY = \"security.sms2fa.v1\";\r\nconst defaultState = {\r\n  passwordHash: \"demo\",\r\n  twoFA: { enabled:false, method:null, phone:null, enabledAt:null },\r\n  sessions: [\r\n    { id:id(), device:\"MacBook Pro \u00b7 Safari\", location:\"Makati, PH\", last:\"Just now\", current:true },\r\n    { id:id(), device:\"iPhone 14 \u00b7 Safari\",  location:\"Taguig, PH\", last:\"2 hours ago\", current:false },\r\n    { id:id(), device:\"Windows 11 \u00b7 Chrome\", location:\"Quezon City, PH\", last:\"Yesterday 09:22\", current:false },\r\n  ],\r\n};\r\nlet state = load();\r\n\r\nfunction load(){ const s=localStorage.getItem(STORAGE_KEY); return s? JSON.parse(s) : structuredClone(defaultState); }\r\nfunction save(){ localStorage.setItem(STORAGE_KEY, JSON.stringify(state)); }\r\nfunction id(){ return Math.random().toString(36).slice(2,10); }\r\nfunction toast(msg){ const t=$(\"#toast\"); t.textContent=msg; t.classList.add(\"show\"); setTimeout(()=>t.classList.remove(\"show\"),1500); }\r\nfunction maskPhone(p){ if(!p) return \"\"; const d=p.replace(\/\\D\/g,\"\"); return p.startsWith(\"+\") ? p.slice(0,3)+\"\u2022\u2022\u2022\"+p.slice(-3) : d.slice(0,2)+\"\u2022\u2022\u2022\"+d.slice(-3); }\r\n\r\n\/* ===========================\r\n   Password Management\r\n=========================== *\/\r\nfunction toggleVis(btn){\r\n  const id = btn.getAttribute(\"data-toggle\");\r\n  const input = $(\"#\"+id);\r\n  input.type = input.type===\"password\" ? \"text\" : \"password\";\r\n  btn.textContent = input.type===\"password\" ? \"Show\" : \"Hide\";\r\n}\r\nfunction score(p){\r\n  let s=0; if(!p) return 0;\r\n  if(p.length>=8) s++; if(p.length>=12) s++;\r\n  if(\/[a-z]\/.test(p)&&\/[A-Z]\/.test(p)) s++;\r\n  if(\/\\d\/.test(p)) s++; if(\/[^\\w]\/.test(p)) s++;\r\n  return Math.min(s,5);\r\n}\r\nfunction renderStrength(){ $(\"#pwBar\").style.width = (score($(\"#newPw\").value)*20)+\"%\"; }\r\nfunction changePassword(e){\r\n  e.preventDefault();\r\n  $(\"#err-current\").textContent=$(\"#err-new\").textContent=$(\"#err-confirm\").textContent=\"\";\r\n  const cur=$(\"#currentPw\").value, nw=$(\"#newPw\").value, cf=$(\"#confirmPw\").value;\r\n  if(!cur){ $(\"#err-current\").textContent=\"Current password is required\"; return; }\r\n  if(nw.length<8){ $(\"#err-new\").textContent=\"Use at least 8 characters\"; return; }\r\n  if(nw!==cf){ $(\"#err-confirm\").textContent=\"Passwords do not match\"; return; }\r\n  state.passwordHash = \"hash-\"+id(); save();\r\n  $(\"#currentPw\").value=$(\"#newPw\").value=$(\"#confirmPw\").value=\"\";\r\n  $(\"#pwStatus\").textContent=\"Password changed successfully\"; toast(\"Password updated \u2713\");\r\n  setTimeout(()=>$(\"#pwStatus\").textContent=\"\",1500);\r\n}\r\n\r\n\/* ===========================\r\n   SMS 2FA\r\n=========================== *\/\r\nlet sentCode = null;\r\nlet countdown = 0;\r\nlet timerId = null;\r\n\r\nfunction open2faModal(prefill=false){\r\n  $(\"#err-phone\").textContent = $(\"#err-code\").textContent = \"\";\r\n  $(\"#smsPhone\").value = prefill && state.twoFA.phone ? state.twoFA.phone : \"\";\r\n  $(\"#smsCode\").value = \"\";\r\n  $(\"#demoCode\").style.display = \"none\";\r\n  $(\"#sendCodeBtn\").disabled = false;\r\n  $(\"#sendCodeBtn\").textContent = \"Send Code\";\r\n  clearInterval(timerId); timerId=null; countdown=0;\r\n  $(\"#twofaModal\").classList.add(\"open\");\r\n}\r\nfunction close2faModal(){ $(\"#twofaModal\").classList.remove(\"open\"); }\r\n\r\nfunction validE164(p){\r\n  \/\/ Very loose E.164-ish check: starts with +, 8\u201315 digits in total\r\n  return \/^\\+\\d{8,15}$\/.test(p.replace(\/\\s+\/g,\"\"));\r\n}\r\nfunction sendCode(e){\r\n  e.preventDefault();\r\n  $(\"#err-phone\").textContent = \"\";\r\n  const phone = $(\"#smsPhone\").value.trim();\r\n  if(!validE164(phone)){ $(\"#err-phone\").textContent=\"Enter a valid phone in international format (e.g., +639001234567)\"; return; }\r\n  \/\/ Generate 6-digit\r\n  sentCode = (\"\"+Math.floor(100000 + Math.random()*900000));\r\n  \/\/ Demo surface\r\n  $(\"#demoCode\").textContent = `(demo) ${sentCode}`;\r\n  $(\"#demoCode\").style.display = \"inline-block\";\r\n  toast(\"Verification code sent\");\r\n  \/\/ Start cooldown\r\n  startCooldown(30);\r\n}\r\nfunction startCooldown(sec){\r\n  countdown = sec;\r\n  $(\"#sendCodeBtn\").disabled = true;\r\n  updateSendBtn();\r\n  clearInterval(timerId);\r\n  timerId = setInterval(()=>{\r\n    countdown--;\r\n    updateSendBtn();\r\n    if(countdown<=0){ clearInterval(timerId); timerId=null; $(\"#sendCodeBtn\").disabled=false; $(\"#sendCodeBtn\").textContent=\"Resend Code\"; }\r\n  },1000);\r\n}\r\nfunction updateSendBtn(){\r\n  $(\"#sendCodeBtn\").textContent = countdown>0 ? `Resend in ${countdown}s` : \"Send Code\";\r\n}\r\nfunction enable2FA(e){\r\n  e.preventDefault();\r\n  $(\"#err-phone\").textContent = $(\"#err-code\").textContent = \"\";\r\n  const phone = $(\"#smsPhone\").value.trim().replace(\/\\s+\/g,\"\");\r\n  const code = $(\"#smsCode\").value.trim();\r\n  if(!validE164(phone)){ $(\"#err-phone\").textContent=\"Enter a valid phone in international format\"; return; }\r\n  if(!\/^\\d{6}$\/.test(code)){ $(\"#err-code\").textContent=\"Enter the 6-digit code\"; return; }\r\n  if(!sentCode){ $(\"#err-code\").textContent=\"Please request a code first\"; return; }\r\n  if(code !== sentCode){ $(\"#err-code\").textContent=\"Incorrect code\"; return; }\r\n\r\n  state.twoFA = { enabled:true, method:\"sms\", phone, enabledAt:new Date().toISOString() };\r\n  save();\r\n  render2FA();\r\n  close2faModal();\r\n  toast(\"SMS 2FA enabled \u2713\");\r\n}\r\nfunction render2FA(){\r\n  const on = state.twoFA.enabled && state.twoFA.method===\"sms\";\r\n  $(\"#twofaState\").textContent = on ? \"Enabled\" : \"Disabled\";\r\n  $(\"#twofaBadge\").className = \"badge \" + (on ? \"good\":\"warn\");\r\n  $(\"#setup2faBtn\").style.display = on ? \"none\":\"inline-block\";\r\n  $(\"#disable2faBtn\").style.display = on ? \"inline-block\":\"none\";\r\n  $(\"#twofaPhoneInfo\").textContent = on ? `Number: ${maskPhone(state.twoFA.phone)}` : \"\";\r\n}\r\nfunction disable2FA(e){\r\n  e.preventDefault();\r\n  if(!confirm(\"Disable SMS two-factor authentication?\")) return;\r\n  state.twoFA = { enabled:false, method:null, phone:null, enabledAt:null };\r\n  save();\r\n  render2FA();\r\n  toast(\"2FA disabled\");\r\n}\r\n\r\n\/* ===========================\r\n   Sessions\r\n=========================== *\/\r\nfunction renderSessions(){\r\n  const tbody = $(\"#sessionsTbody\"); tbody.innerHTML = \"\";\r\n  if(state.sessions.length===0){\r\n    const tr=document.createElement(\"tr\");\r\n    const td=document.createElement(\"td\"); td.colSpan=4; td.textContent=\"No active sessions.\"; td.style.textAlign=\"center\"; td.style.background=\"#fafbff\";\r\n    tr.appendChild(td); tbody.appendChild(tr); return;\r\n  }\r\n  state.sessions.forEach(s=>{\r\n    const tr=document.createElement(\"tr\");\r\n    tr.innerHTML = `\r\n      <td>${s.device}${s.current ? ' <span class=\"badge good\">This device<\/span>':''}<\/td>\r\n      <td>${s.location}<\/td>\r\n      <td>${s.last}<\/td>\r\n      <td style=\"text-align:right\"><button class=\"btn small danger\" data-revoke=\"${s.id}\">Sign out<\/button><\/td>\r\n    `;\r\n    tbody.appendChild(tr);\r\n  });\r\n  $$('[data-revoke]').forEach(btn=>{\r\n    btn.addEventListener('click', ()=>{\r\n      const id = btn.getAttribute('data-revoke');\r\n      if(!confirm(\"Sign out this session?\")) return;\r\n      state.sessions = state.sessions.filter(x=>x.id!==id);\r\n      save(); renderSessions(); toast(\"Session revoked\");\r\n    });\r\n  });\r\n}\r\nfunction logoutAll(e){\r\n  e.preventDefault();\r\n  if(!confirm(\"Logout from all devices (including this one)?\")) return;\r\n  state.sessions = []; save(); renderSessions(); toast(\"Logged out from all devices\");\r\n}\r\n\r\n\/* ===========================\r\n   Init & Events\r\n=========================== *\/\r\ndocument.addEventListener(\"DOMContentLoaded\", ()=>{\r\n  \/\/ Password\r\n  $$('[data-toggle]').forEach(btn=> btn.addEventListener(\"click\", ()=> toggleVis(btn)));\r\n  $(\"#newPw\").addEventListener(\"input\", renderStrength);\r\n  $(\"#changePwBtn\").addEventListener(\"click\", changePassword);\r\n\r\n  \/\/ 2FA\r\n  $(\"#setup2faBtn\").addEventListener(\"click\", ()=> open2faModal(true));\r\n  $(\"#disable2faBtn\").addEventListener(\"click\", disable2FA);\r\n  $(\"#cancel2faBtn\").addEventListener(\"click\", ()=> close2faModal());\r\n  $(\"#sendCodeBtn\").addEventListener(\"click\", sendCode);\r\n  $(\"#enable2faConfirm\").addEventListener(\"click\", enable2FA);\r\n\r\n  \/\/ Sessions\r\n  $(\"#logoutAllBtn\").addEventListener(\"click\", logoutAll);\r\n\r\n  \/\/ Initial renders\r\n  renderStrength();\r\n  render2FA();\r\n  renderSessions();\r\n});\r\n<\/script>\r\n<\/body>\r\n<\/html>\r\n\r\n\r\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div id=\"e-n-tab-content-113480933\" role=\"tabpanel\" aria-labelledby=\"e-n-tab-title-113480933\" data-tab-index=\"3\" style=\"--n-tabs-title-order: 3;\" class=\" elementor-element elementor-element-cb9f79d e-con-full e-flex e-con e-child\" data-id=\"cb9f79d\" data-element_type=\"container\" data-settings=\"{&quot;position&quot;:&quot;absolute&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-970e0f4 elementor-widget elementor-widget-html\" data-id=\"970e0f4\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n<meta charset=\"UTF-8\"\/>\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\/>\r\n<title>Users & Roles \u2013 Access Control<\/title>\r\n<style>\r\n  :root{\r\n    --bg:#f6f8fb;\r\n    --surface:#ffffff;\r\n    --text:#1e2430;\r\n    --muted:#6b7280;\r\n    --line:#e7eaf2;\r\n\r\n    --primary:#2d6bff;\r\n    --focus:rgba(45,107,255,.18);\r\n    --danger:#d92d20;\r\n    --good:#16a34a;\r\n    --warn:#f59e0b;\r\n\r\n    --radius-lg:16px;\r\n    --radius-md:12px;\r\n\r\n    --shadow-sm:0 1px 2px rgba(16,24,40,.06);\r\n    --shadow-md:0 6px 18px rgba(16,24,40,.08);\r\n  }\r\n\r\n  *{box-sizing:border-box}\r\n  html,body{\r\n    height:100%\r\n  }\r\n  body{\r\n    margin:0; \r\n    font:14px\/1.55 Inter, ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, Arial;\r\n    color:var(--text); \r\n    background:var(--bg); \r\n    padding:28px;\r\n  }\r\n\r\n  header{\r\n    max-width:1200px;\r\n    margin:0 auto 18px\r\n    text-align:left;\r\n  }\r\n  .h1{\r\n    font-size:22px;\r\n    font-weight:700;\r\n    margin:0 0 6px; \r\n    letter-spacing:.2px;\r\n    text-align:left;\r\n    white-space:nowrap; \r\n    display:block; \r\n  }\r\n  .subtle{\r\n    color:var(--muted)\r\n  }\r\n\r\n  .container{\r\n    max-width:1200px;\r\n    margin:0 auto;\r\n    display:grid;\r\n    gap:22px\r\n  }\r\n\r\n  .card{\r\n    background:var(--surface);\r\n    border:1px solid var(--line);\r\n    border-radius:var(--radius-lg);\r\n    box-shadow:var(--shadow-sm);\r\n    overflow:hidden;\r\n  }\r\n  .card-h{\r\n    padding:18px 20px 12px;\r\n    border-bottom:1px solid var(--line);\r\n    background:linear-gradient(180deg,#fff,#fafbff)\r\n  }\r\n  .card-t{\r\n    font-weight:700}\r\n  .card-d{\r\n    color:var(--muted);\r\n    font-size:13px;\r\n    margin-top:2px\r\n  }\r\n  .card-c{\r\n    padding:18px 20px\r\n  }\r\n\r\n  .grid-2{\r\n    display:grid;\r\n    grid-template-columns:1fr 1fr;\r\n    gap:14px\r\n  }\r\n  .grid-3{\r\n    display:grid;\r\n    grid-template-columns:repeat(3,1fr);\r\n    gap:14px\r\n  }\r\n  .grid-4{\r\n    display:grid;\r\n    grid-template-columns:repeat(4,1fr);\r\n    gap:14px\r\n  }\r\n  @media (max-width:960px){ .grid-2,.grid-3,.grid-4{grid-template-columns:1fr} }\r\n\r\n  label{\r\n    display:block;\r\n    font-weight:600;\r\n    font-size:12px;\r\n    letter-spacing:.28px;\r\n    text-transform:uppercase;\r\n    color:#7b8497;\r\n    margin:6px 0 8px\r\n  }\r\n  input[type=\"text\"], \r\n  input[type=\"email\"], \r\n  input[type=\"number\"], select{\r\n    width:100%; \r\n    background:#fff; \r\n    border:1px solid var(--line); \r\n    color:var(--text);\r\n    padding:12px; \r\n    border-radius:var(--radius-md); \r\n    outline:none; \r\n    transition:border-color .18s, box-shadow .18s;\r\n  }\r\n  input:focus, select:focus{\r\n    border-color:var(--primary); \r\n    box-shadow:0 0 0 4px var(--focus)\r\n  }\r\n  input::placeholder{\r\n    color:#9aa3b2\r\n  }\r\n\r\n  .row{\r\n    display:flex; \r\n    gap:10px; \r\n    align-items:center; \r\n    flex-wrap:wrap\r\n  }\r\n  .right{\r\n    margin-left:auto\r\n  }\r\n\r\n  .btn{\r\n    border:1px solid var(--line); \r\n    background:#fff; \r\n    color:var(--text);\r\n    padding:10px 14px; \r\n    border-radius:10px; \r\n    cursor:pointer; \r\n    font-weight:600;\r\n    transition:transform .12s, background .18s, border .18s;\r\n  }\r\n  .btn:hover{\r\n    background:#f9fafe\r\n  }\r\n  .btn:active{\r\n    transform:translateY(1px)\r\n  }\r\n  .btn.primary{\r\n    background:var(--primary); \r\n    border-color:#275de0; \r\n    color:#fff\r\n  }\r\n  .btn.danger{\r\n    background:#fff5f5; \r\n    border-color:#ffd6d6; \r\n    color:#b42318\r\n  }\r\n  .btn.ghost{\r\n    background:transparent\r\n  }\r\n  .btn.small{\r\n    padding:7px 10px\r\n  }\r\n  .btn[disabled]{\r\n    opacity:.6;\r\n    cursor:not-allowed\r\n  }\r\n\r\n  .hint{color:var(--muted); \r\n    font-size:12px; \r\n    margin-top:6px\r\n  }\r\n  .error{\r\n    color:#b42318; \r\n    font-size:12px; \r\n    margin-top:6px\r\n  }\r\n\r\n  .badge{\r\n    display:inline-flex; \r\n    padding:5px 8px; \r\n    font-size:12px; \r\n    border-radius:999px; \r\n    border:1px solid var(--line); \r\n    background:#f7f8fc; \r\n    color:#4b5563\r\n  }\r\n  .badge.good{\r\n    background:#ecfdf5; \r\n    border-color:#a7f3d0; \r\n    color:#065f46\r\n  }\r\n  .badge.warn{\r\n    background:#fffbeb; \r\n    border-color:#fde68a; \r\n    color:#92400e\r\n  }\r\n  .badge.danger{\r\n    background:#fef2f2; \r\n    border-color:#fecaca; \r\n    color:#7f1d1d\r\n  }\r\n\r\n  .sep{\r\n    height:1px; \r\n    background:var(--line); \r\n    margin:12px 0\r\n  }\r\n\r\n  \/* Tables *\/\r\n  table{\r\n    width:100%; \r\n    border-collapse:separate; \r\n    border-spacing:0 8px\r\n  }\r\n  th{\r\n    font-size:12px; \r\n    color:#7b8497; \r\n    text-align:left; \r\n    padding:0 10px\r\n  }\r\n  td{\r\n    background:#fff; \r\n    border:1px solid var(--line); \r\n    padding:10px; \r\n    border-radius:8px; \r\n    vertical-align:middle\r\n  }\r\n  tr td:first-child{\r\n    border-top-right-radius:0; \r\n    border-bottom-right-radius:0\r\n  }\r\n  tr td:last-child{\r\n    border-top-left-radius:0; \r\n    border-bottom-left-radius:0\r\n  }\r\n\r\n  \/* Permissions matrix *\/\r\n  .perm-matrix{\r\n    width:100%; \r\n    border-collapse:separate; \r\n    border-spacing:0 8px\r\n  }\r\n  .perm-matrix th, .perm-matrix td{\r\n    padding:10px\r\n  }\r\n  .perm-matrix td{\r\n    background:#fff; \r\n    border:1px solid var(--line)\r\n  }\r\n  .perm-head{\r\n    white-space:nowrap\r\n  }\r\n\r\n  \/* Modal *\/\r\n  .modal{\r\n    position:fixed; \r\n    inset:0; \r\n    display:none; \r\n    align-items:center; \r\n    justify-content:center;\r\n    background:rgba(2,8,23,.45); \r\n    z-index:50; \r\n    padding:22px;\r\n  }\r\n  .modal.open{display:flex}\r\n  .dialog{\r\n    width:min(660px, 96vw); \r\n    background:#fff; \r\n    border:1px solid var(--line);\r\n    border-radius:16px; \r\n    box-shadow:var(--shadow-md); \r\n    overflow:hidden;\r\n  }\r\n  .dh{\r\n    padding:16px 18px; \r\n    border-bottom:1px solid var(--line); \r\n    background:linear-gradient(180deg,#fff,#fafbff)\r\n  }\r\n  .dc{\r\n    padding:16px 18px\r\n  }\r\n  .df{\r\n    padding:14px 18px; \r\n    border-top:1px solid var(--line); \r\n    display:flex; \r\n    gap:10px; \r\n    justify-content:flex-end\r\n  }\r\n\r\n  .toast{\r\n    position:fixed; \r\n    right:20px; \r\n    bottom:20px; \r\n    background:#243b7b; \r\n    border:1px solid #314b95; \r\n    color:#e8efff;\r\n    padding:12px 14px; \r\n    border-radius:12px; \r\n    box-shadow:var(--shadow-md); \r\n    opacity:0; \r\n    transform:translateY(8px); \r\n    pointer-events:none; \r\n    transition:.25s\r\n  }\r\n  .toast.show{opacity:1; transform:translateY(0)}\r\n<\/style>\r\n<\/head>\r\n<body>\r\n  <header>\r\n    <div class=\"h1\">Users & Roles \u2014 Access Control<\/div>\r\n  <\/header>\r\n\r\n  <main class=\"container\">\r\n    <!-- USERS -->\r\n    <section class=\"card\" aria-labelledby=\"users-title\">\r\n      <div class=\"card-h\">\r\n        <div id=\"users-title\" class=\"card-t\">Users<\/div>\r\n        <div class=\"card-d\">Add or remove users, assign roles, and set per-user ticket caps<\/div>\r\n      <\/div>\r\n      <div class=\"card-c\">\r\n        <div class=\"row\" style=\"margin-bottom:10px\">\r\n          <button class=\"btn primary\" id=\"inviteBtn\">Invite User<\/button>\r\n          <button class=\"btn\" id=\"addUserBtn\">Add User<\/button>\r\n          <div class=\"right row\">\r\n            <label for=\"roleFilter\" style=\"margin:0;color:#7b8497;text-transform:none;letter-spacing:0\">Filter by role<\/label>\r\n            <select id=\"roleFilter\">\r\n              <option value=\"\">All roles<\/option>\r\n              <option>Admin<\/option><option>Supervisor<\/option><option>Agent<\/option><option>Viewer<\/option>\r\n            <\/select>\r\n            <input id=\"searchUser\" type=\"text\" placeholder=\"Search name or email\" style=\"min-width:220px\"\/>\r\n          <\/div>\r\n        <\/div>\r\n\r\n        <table aria-describedby=\"users-title\">\r\n          <thead>\r\n            <tr>\r\n              <th>Name<\/th>\r\n              <th>Email<\/th>\r\n              <th>Role<\/th>\r\n              <th>Status<\/th>\r\n              <th>Tickets (owned)<\/th>\r\n              <th>Max Allowed<\/th>\r\n              <th><\/th>\r\n            <\/tr>\r\n          <\/thead>\r\n          <tbody id=\"usersTbody\"><\/tbody>\r\n        <\/table>\r\n        <div class=\"hint\">Per-user max overrides the role default (see Limits & Policies).<\/div>\r\n      <\/div>\r\n    <\/section>\r\n\r\n    <!-- ROLES & PERMISSIONS -->\r\n    <section class=\"card\" aria-labelledby=\"roles-title\">\r\n      <div class=\"card-h\">\r\n        <div id=\"roles-title\" class=\"card-t\">Roles & Permissions<\/div>\r\n        <div class=\"card-d\">Configure access by role for modules like Tickets, Reports, Settings, and Users<\/div>\r\n      <\/div>\r\n      <div class=\"card-c\">\r\n        <div class=\"row\" style=\"margin-bottom:10px\">\r\n          <div class=\"badge\">Roles: Admin, Supervisor, Agent, Viewer<\/div>\r\n          <div class=\"right row\">\r\n            <button class=\"btn small\" id=\"restorePresetsBtn\">Restore Corporate Presets<\/button>\r\n            <button class=\"btn small primary\" id=\"savePermsBtn\">Save Changes<\/button>\r\n          <\/div>\r\n        <\/div>\r\n\r\n        <table class=\"perm-matrix\" aria-label=\"Permissions Matrix\">\r\n          <thead>\r\n            <tr>\r\n              <th class=\"perm-head\">Module \u00b7 Capability<\/th>\r\n              <th>Admin<\/th>\r\n              <th>Supervisor<\/th>\r\n              <th>Agent<\/th>\r\n              <th>Viewer<\/th>\r\n            <\/tr>\r\n          <\/thead>\r\n          <tbody id=\"permsTbody\">\r\n            <!-- Filled by JS -->\r\n          <\/tbody>\r\n        <\/table>\r\n\r\n        <div class=\"hint\" style=\"margin-top:8px\">Tip: click a column header to toggle an entire role on\/off for a capability row (press and hold Alt to apply to the whole module group).<\/div>\r\n      <\/div>\r\n    <\/section>\r\n\r\n    <!-- LIMITS & POLICIES -->\r\n    <section class=\"card\" aria-labelledby=\"limits-title\">\r\n      <div class=\"card-h\">\r\n        <div id=\"limits-title\" class=\"card-t\">Limits & Policies<\/div>\r\n        <div class=\"card-d\">Set default ticket ownership limits per role. Users can override individually.<\/div>\r\n      <\/div>\r\n      <div class=\"card-c\">\r\n        <div class=\"grid-4\">\r\n          <div>\r\n            <label for=\"capAdmin\">Admin \u00b7 Max Tickets<\/label>\r\n            <input id=\"capAdmin\" type=\"number\" min=\"0\" step=\"1\" placeholder=\"0 = unlimited\"\/>\r\n          <\/div>\r\n          <div>\r\n            <label for=\"capSupervisor\">Supervisor \u00b7 Max Tickets<\/label>\r\n            <input id=\"capSupervisor\" type=\"number\" min=\"0\" step=\"1\"\/>\r\n          <\/div>\r\n          <div>\r\n            <label for=\"capAgent\">Agent \u00b7 Max Tickets<\/label>\r\n            <input id=\"capAgent\" type=\"number\" min=\"0\" step=\"1\"\/>\r\n          <\/div>\r\n          <div>\r\n            <label for=\"capViewer\">Viewer \u00b7 Max Tickets<\/label>\r\n            <input id=\"capViewer\" type=\"number\" min=\"0\" step=\"1\"\/>\r\n          <\/div>\r\n        <\/div>\r\n        <div class=\"row\" style=\"margin-top:10px\">\r\n          <button class=\"btn primary\" id=\"saveCapsBtn\">Save Limits<\/button>\r\n          <button class=\"btn\" id=\"restoreCapsBtn\">Restore Defaults<\/button>\r\n          <div class=\"hint\">Zero means no cap. Agents often have caps to balance workload.<\/div>\r\n        <\/div>\r\n      <\/div>\r\n    <\/section>\r\n\r\n    <!-- INVITATIONS -->\r\n    <section class=\"card\" aria-labelledby=\"inv-title\">\r\n      <div class=\"card-h\">\r\n        <div id=\"inv-title\" class=\"card-t\">Invitations<\/div>\r\n        <div class=\"card-d\">Invite new users by email and track their status<\/div>\r\n      <\/div>\r\n      <div class=\"card-c\">\r\n        <div class=\"row\" style=\"margin-bottom:10px\">\r\n          <button class=\"btn primary\" id=\"openInviteBtn\">Invite User<\/button>\r\n          <div class=\"hint\">Invites expire automatically after the selected period.<\/div>\r\n        <\/div>\r\n\r\n        <table aria-describedby=\"inv-title\">\r\n          <thead>\r\n            <tr>\r\n              <th>Email<\/th>\r\n              <th>Role<\/th>\r\n              <th>Invited<\/th>\r\n              <th>Expires<\/th>\r\n              <th>Status<\/th>\r\n              <th>Link<\/th>\r\n              <th><\/th>\r\n            <\/tr>\r\n          <\/thead>\r\n          <tbody id=\"invitesTbody\"><\/tbody>\r\n        <\/table>\r\n      <\/div>\r\n    <\/section>\r\n  <\/main>\r\n\r\n  <!-- Modal: Invite User -->\r\n  <div class=\"modal\" id=\"inviteModal\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"inviteTitle\">\r\n    <div class=\"dialog\">\r\n      <div class=\"dh\"><div id=\"inviteTitle\" class=\"card-t\">Invite User<\/div><\/div>\r\n      <div class=\"dc\">\r\n        <div class=\"grid-2\">\r\n          <div>\r\n            <label for=\"invEmail\">Email<\/label>\r\n            <input id=\"invEmail\" type=\"email\" placeholder=\"user@company.com\"\/>\r\n            <div class=\"error\" id=\"invEmailErr\"><\/div>\r\n          <\/div>\r\n          <div>\r\n            <label for=\"invRole\">Role<\/label>\r\n            <select id=\"invRole\">\r\n              <option>Agent<\/option><option>Supervisor<\/option><option>Viewer<\/option><option>Admin<\/option>\r\n            <\/select>\r\n          <\/div>\r\n        <\/div>\r\n        <div class=\"grid-2\">\r\n          <div>\r\n            <label for=\"invExpiry\">Expires In<\/label>\r\n            <select id=\"invExpiry\">\r\n              <option value=\"7\">7 days<\/option>\r\n              <option value=\"14\">14 days<\/option>\r\n              <option value=\"30\" selected>30 days<\/option>\r\n            <\/select>\r\n          <\/div>\r\n          <div>\r\n            <label for=\"invNote\">Note (optional)<\/label>\r\n            <input id=\"invNote\" type=\"text\" placeholder=\"e.g., Welcome to the support team\"\/>\r\n          <\/div>\r\n        <\/div>\r\n        <div class=\"hint\">An email with an invite link will be sent. In this demo, a link is generated here for testing.<\/div>\r\n      <\/div>\r\n      <div class=\"df\">\r\n        <button class=\"btn\" id=\"cancelInviteBtn\">Cancel<\/button>\r\n        <button class=\"btn primary\" id=\"sendInviteBtn\">Send Invite<\/button>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- Modal: Add\/Edit User -->\r\n  <div class=\"modal\" id=\"userModal\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"userTitle\">\r\n    <div class=\"dialog\">\r\n      <div class=\"dh\"><div id=\"userTitle\" class=\"card-t\">Add User<\/div><\/div>\r\n      <div class=\"dc\">\r\n        <div class=\"grid-2\">\r\n          <div>\r\n            <label for=\"uName\">Full Name<\/label>\r\n            <input id=\"uName\" type=\"text\" placeholder=\"Jane Doe\"\/>\r\n            <div class=\"error\" id=\"uNameErr\"><\/div>\r\n          <\/div>\r\n          <div>\r\n            <label for=\"uEmail\">Email<\/label>\r\n            <input id=\"uEmail\" type=\"email\" placeholder=\"jane@company.com\"\/>\r\n            <div class=\"error\" id=\"uEmailErr\"><\/div>\r\n          <\/div>\r\n        <\/div>\r\n        <div class=\"grid-3\">\r\n          <div>\r\n            <label for=\"uRole\">Role<\/label>\r\n            <select id=\"uRole\"><option>Agent<\/option><option>Supervisor<\/option><option>Viewer<\/option><option>Admin<\/option><\/select>\r\n          <\/div>\r\n          <div>\r\n            <label for=\"uTickets\">Tickets Owned<\/label>\r\n            <input id=\"uTickets\" type=\"number\" min=\"0\" value=\"0\"\/>\r\n          <\/div>\r\n          <div>\r\n            <label for=\"uMax\">Max Tickets (override)<\/label>\r\n            <input id=\"uMax\" type=\"number\" min=\"0\" placeholder=\"0 = default\"\/>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"df\">\r\n        <button class=\"btn\" id=\"cancelUserBtn\">Cancel<\/button>\r\n        <button class=\"btn primary\" id=\"saveUserBtn\">Save<\/button>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <div id=\"toast\" class=\"toast\" role=\"status\" aria-live=\"polite\"><\/div>\r\n\r\n<script>\r\n\/* ===========================\r\n   State, Defaults, Utilities\r\n=========================== *\/\r\nconst $  = (s,ctx=document)=>ctx.querySelector(s);\r\nconst $$ = (s,ctx=document)=>Array.from(ctx.querySelectorAll(s));\r\nconst STORAGE_KEY = \"rbac.settings.v1\";\r\n\r\nconst defaultState = {\r\n  users: [\r\n    { id:id(), name:\"Jane Doe\",   email:\"jane@company.com\",   role:\"Admin\",      status:\"Active\",   tickets:3, max:0 },\r\n    { id:id(), name:\"Rico Cruz\",  email:\"rico@company.com\",   role:\"Supervisor\", status:\"Active\",   tickets:12, max:0 },\r\n    { id:id(), name:\"Mia Santos\", email:\"mia@company.com\",    role:\"Agent\",      status:\"Active\",   tickets:18, max:25 },\r\n    { id:id(), name:\"Ken Lee\",    email:\"ken@company.com\",    role:\"Viewer\",     status:\"Suspended\",tickets:0, max:0 }\r\n  ],\r\n  roles: [\"Admin\",\"Supervisor\",\"Agent\",\"Viewer\"],\r\n  \/\/ capability -> role -> boolean\r\n  permissions: {\r\n    \"tickets.view\"  : {Admin:1, Supervisor:1, Agent:1, Viewer:1},\r\n    \"tickets.create\": {Admin:1, Supervisor:1, Agent:1, Viewer:0},\r\n    \"tickets.assign\": {Admin:1, Supervisor:1, Agent:0, Viewer:0},\r\n    \"tickets.close\" : {Admin:1, Supervisor:1, Agent:1, Viewer:0},\r\n    \"reports.view\"  : {Admin:1, Supervisor:1, Agent:0, Viewer:1},\r\n    \"reports.export\": {Admin:1, Supervisor:1, Agent:0, Viewer:0},\r\n    \"settings.view\" : {Admin:1, Supervisor:1, Agent:0, Viewer:0},\r\n    \"settings.edit\" : {Admin:1, Supervisor:0, Agent:0, Viewer:0},\r\n    \"users.view\"    : {Admin:1, Supervisor:1, Agent:0, Viewer:0},\r\n    \"users.manage\"  : {Admin:1, Supervisor:0, Agent:0, Viewer:0}\r\n  },\r\n  limits: { Admin:0, Supervisor:40, Agent:25, Viewer:0 }, \/\/ 0 = unlimited\r\n  invites: [\r\n    \/\/ { id, email, role, invitedAt, expiresAt, status: \"Pending\"|\"Accepted\"|\"Expired\"|\"Revoked\", code }\r\n  ],\r\n};\r\n\r\nlet state = load();\r\nfunction load(){ const s=localStorage.getItem(STORAGE_KEY); return s? JSON.parse(s) : structuredClone(defaultState); }\r\nfunction save(){ localStorage.setItem(STORAGE_KEY, JSON.stringify(state)); }\r\n\r\nfunction id(){ return Math.random().toString(36).slice(2,10); }\r\nfunction toast(msg){ const t=$(\"#toast\"); t.textContent=msg; t.classList.add(\"show\"); setTimeout(()=>t.classList.remove(\"show\"),1500); }\r\nfunction fmtDate(iso){ return new Date(iso).toLocaleString(); }\r\nfunction addDays(d){ const x=new Date(); x.setDate(x.getDate()+d); return x.toISOString(); }\r\nfunction emailOK(e){ return \/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$\/.test(e); }\r\nfunction cap(s){ return s.charAt(0).toUpperCase()+s.slice(1); }\r\nfunction maskInvite(code){ return code.slice(0,4)+\"\u2022\u2022\u2022\u2022\"+code.slice(-4); }\r\n\r\n\/* ===========================\r\n   USERS\r\n=========================== *\/\r\nfunction renderUsers(){\r\n  const tb = $(\"#usersTbody\"); tb.innerHTML = \"\";\r\n  const q = $(\"#searchUser\").value.trim().toLowerCase();\r\n  const rf = $(\"#roleFilter\").value;\r\n\r\n  state.users\r\n    .filter(u => (!rf || u.role===rf) && (!q || (u.name.toLowerCase().includes(q) || u.email.toLowerCase().includes(q))))\r\n    .forEach(u=>{\r\n      const tr = document.createElement(\"tr\");\r\n      tr.innerHTML = `\r\n        <td>${u.name}<\/td>\r\n        <td>${u.email}<\/td>\r\n        <td>\r\n          <select data-role=\"${u.id}\">\r\n            ${state.roles.map(r=>`<option ${r===u.role?'selected':''}>${r}<\/option>`).join(\"\")}\r\n          <\/select>\r\n        <\/td>\r\n        <td>${badgeStatus(u.status)}<\/td>\r\n        <td>${u.tickets}<\/td>\r\n        <td>\r\n          <div class=\"row\">\r\n            <input type=\"number\" min=\"0\" placeholder=\"0=default\" value=\"${u.max||0}\" style=\"max-width:120px\" data-max=\"${u.id}\"\/>\r\n            <span class=\"hint\">default: ${state.limits[u.role]||0}<\/span>\r\n          <\/div>\r\n        <\/td>\r\n        <td style=\"text-align:right\">\r\n          <button class=\"btn small\" data-edit=\"${u.id}\">Edit<\/button>\r\n          <button class=\"btn small ${u.status==='Suspended'?'':'danger'}\" data-toggle=\"${u.id}\">\r\n            ${u.status==='Suspended'?'Activate':'Suspend'}\r\n          <\/button>\r\n          <button class=\"btn small ghost\" data-remove=\"${u.id}\">Remove<\/button>\r\n        <\/td>\r\n      `;\r\n      tb.appendChild(tr);\r\n    });\r\n\r\n  $$('[data-role]').forEach(sel=>{\r\n    sel.addEventListener(\"change\", ()=>{\r\n      const id = sel.getAttribute(\"data-role\");\r\n      const user = state.users.find(x=>x.id===id);\r\n      user.role = sel.value;\r\n      save(); toast(\"Role updated\");\r\n      renderUsers();\r\n    });\r\n  });\r\n  $$('[data-max]').forEach(inp=>{\r\n    inp.addEventListener(\"change\", ()=>{\r\n      const id = inp.getAttribute(\"data-max\");\r\n      const user = state.users.find(x=>x.id===id);\r\n      const v = parseInt(inp.value||\"0\",10);\r\n      user.max = isNaN(v)?0:Math.max(0,v);\r\n      save(); toast(\"Max updated\");\r\n    });\r\n  });\r\n  $$('[data-edit]').forEach(btn=>btn.addEventListener(\"click\", ()=>openUserModal(btn.getAttribute(\"data-edit\"))));\r\n  $$('[data-toggle]').forEach(btn=>btn.addEventListener(\"click\", ()=>{\r\n    const id = btn.getAttribute(\"data-toggle\");\r\n    const u = state.users.find(x=>x.id===id);\r\n    if(u.status===\"Suspended\"){ u.status=\"Active\"; } else { u.status=\"Suspended\"; }\r\n    save(); toast(`User ${u.status===\"Active\"?\"activated\":\"suspended\"}`); renderUsers();\r\n  }));\r\n  $$('[data-remove]').forEach(btn=>btn.addEventListener(\"click\", ()=>{\r\n    const id = btn.getAttribute(\"data-remove\");\r\n    const u = state.users.find(x=>x.id===id);\r\n    if(!confirm(`Remove ${u.name}?`)) return;\r\n    state.users = state.users.filter(x=>x.id!==id); save(); renderUsers(); toast(\"User removed\");\r\n  }));\r\n}\r\nfunction badgeStatus(s){\r\n  if(s===\"Active\") return `<span class=\"badge good\">Active<\/span>`;\r\n  if(s===\"Suspended\") return `<span class=\"badge danger\">Suspended<\/span>`;\r\n  if(s===\"Invited\") return `<span class=\"badge warn\">Invited<\/span>`;\r\n  return `<span class=\"badge\">${s}<\/span>`;\r\n}\r\n\r\n\/* Add\/Edit user modal *\/\r\nlet editingUserId = null;\r\nfunction openUserModal(id=null){\r\n  editingUserId = id;\r\n  $(\"#userTitle\").textContent = id? \"Edit User\" : \"Add User\";\r\n  $(\"#uNameErr\").textContent = $(\"#uEmailErr\").textContent = \"\";\r\n  if(id){\r\n    const u = state.users.find(x=>x.id===id);\r\n    $(\"#uName\").value = u.name; $(\"#uEmail\").value = u.email; $(\"#uRole\").value = u.role;\r\n    $(\"#uTickets\").value = u.tickets; $(\"#uMax\").value = u.max||0;\r\n  }else{\r\n    $(\"#uName\").value=\"\"; $(\"#uEmail\").value=\"\"; $(\"#uRole\").value=\"Agent\"; $(\"#uTickets\").value=0; $(\"#uMax\").value=\"\";\r\n  }\r\n  $(\"#userModal\").classList.add(\"open\");\r\n}\r\nfunction closeUserModal(){ $(\"#userModal\").classList.remove(\"open\"); }\r\n$(\"#cancelUserBtn\").addEventListener(\"click\", (e)=>{ e.preventDefault(); closeUserModal(); });\r\n$(\"#saveUserBtn\").addEventListener(\"click\", (e)=>{\r\n  e.preventDefault();\r\n  const name=$(\"#uName\").value.trim(), email=$(\"#uEmail\").value.trim(), role=$(\"#uRole\").value;\r\n  const tickets=parseInt($(\"#uTickets\").value||\"0\",10), max=parseInt($(\"#uMax\").value||\"0\",10);\r\n  $(\"#uNameErr\").textContent = $(\"#uEmailErr\").textContent = \"\";\r\n  if(!name){ $(\"#uNameErr\").textContent=\"Name is required\"; return; }\r\n  if(!emailOK(email)){ $(\"#uEmailErr\").textContent=\"Enter a valid email\"; return; }\r\n\r\n  if(editingUserId){\r\n    const u = state.users.find(x=>x.id===editingUserId);\r\n    Object.assign(u,{name,email,role,tickets:Math.max(0,tickets),max:Math.max(0,max)});\r\n    toast(\"User updated\");\r\n  }else{\r\n    state.users.unshift({id:id(), name, email, role, status:\"Active\", tickets:Math.max(0,tickets), max:Math.max(0,max)});\r\n    toast(\"User added\");\r\n  }\r\n  save(); renderUsers(); closeUserModal();\r\n});\r\n$(\"#addUserBtn\").addEventListener(\"click\", ()=>openUserModal());\r\n$(\"#roleFilter\").addEventListener(\"change\", renderUsers);\r\n$(\"#searchUser\").addEventListener(\"input\", renderUsers);\r\n\r\n\/* ===========================\r\n   PERMISSIONS\r\n=========================== *\/\r\nconst modules = {\r\n  \"Tickets\":[[\"tickets.view\",\"View\"],[\"tickets.create\",\"Create\"],[\"tickets.assign\",\"Assign\"],[\"tickets.close\",\"Close\"]],\r\n  \"Reports\":[[\"reports.view\",\"View\"],[\"reports.export\",\"Export\"]],\r\n  \"Settings\":[[\"settings.view\",\"View\"],[\"settings.edit\",\"Edit\"]],\r\n  \"Users\":[[\"users.view\",\"View\"],[\"users.manage\",\"Manage\"]],\r\n};\r\nfunction renderPerms(){\r\n  const tb = $(\"#permsTbody\"); tb.innerHTML = \"\";\r\n  Object.entries(modules).forEach(([group, caps])=>{\r\n    \/\/ group header row\r\n    const gh = document.createElement(\"tr\");\r\n    gh.innerHTML = `<td style=\"background:#f7f8fc;border:1px solid var(--line);font-weight:700\">${group}<\/td>\r\n      ${state.roles.map(()=>`<td style=\"background:#f7f8fc;border:1px solid var(--line)\"><\/td>`).join(\"\")}`;\r\n    tb.appendChild(gh);\r\n\r\n    caps.forEach(([capKey, label])=>{\r\n      const tr = document.createElement(\"tr\");\r\n      tr.innerHTML = `\r\n        <td class=\"perm-head\">${group} \u00b7 ${label}<\/td>\r\n        ${state.roles.map(r=>`\r\n          <td style=\"text-align:center\">\r\n            <input type=\"checkbox\" data-cap=\"${capKey}\" data-role=\"${r}\" ${state.permissions[capKey]?.[r] ? \"checked\":\"\"}\/>\r\n          <\/td>`).join(\"\")}\r\n      `;\r\n      tb.appendChild(tr);\r\n    });\r\n  });\r\n\r\n  $$('[data-cap]').forEach(cb=>{\r\n    cb.addEventListener(\"change\", ()=>{\r\n      const cap = cb.getAttribute(\"data-cap\");\r\n      const role = cb.getAttribute(\"data-role\");\r\n      state.permissions[cap][role] = cb.checked ? 1 : 0;\r\n    });\r\n  });\r\n}\r\n$(\"#savePermsBtn\").addEventListener(\"click\", ()=>{ save(); toast(\"Permissions saved \u2713\"); });\r\n$(\"#restorePresetsBtn\").addEventListener(\"click\", ()=>{\r\n  if(!confirm(\"Restore corporate preset permissions?\")) return;\r\n  state.permissions = structuredClone(defaultState.permissions);\r\n  renderPerms(); save(); toast(\"Presets restored\");\r\n});\r\n\r\n\/* ===========================\r\n   LIMITS & POLICIES\r\n=========================== *\/\r\nfunction loadCaps(){\r\n  $(\"#capAdmin\").value = state.limits.Admin;\r\n  $(\"#capSupervisor\").value = state.limits.Supervisor;\r\n  $(\"#capAgent\").value = state.limits.Agent;\r\n  $(\"#capViewer\").value = state.limits.Viewer;\r\n}\r\n$(\"#saveCapsBtn\").addEventListener(\"click\", ()=>{\r\n  const a = parseInt($(\"#capAdmin\").value||\"0\",10);\r\n  const s = parseInt($(\"#capSupervisor\").value||\"0\",10);\r\n  const g = parseInt($(\"#capAgent\").value||\"0\",10);\r\n  const v = parseInt($(\"#capViewer\").value||\"0\",10);\r\n  state.limits = { Admin:Math.max(0,a), Supervisor:Math.max(0,s), Agent:Math.max(0,g), Viewer:Math.max(0,v) };\r\n  save(); toast(\"Limits saved \u2713\"); renderUsers();\r\n});\r\n$(\"#restoreCapsBtn\").addEventListener(\"click\", ()=>{\r\n  state.limits = structuredClone(defaultState.limits); loadCaps(); save(); toast(\"Limits restored\");\r\n});\r\n\r\n\/* ===========================\r\n   INVITATIONS\r\n=========================== *\/\r\nfunction renderInvites(){\r\n  const tb=$(\"#invitesTbody\"); tb.innerHTML=\"\";\r\n  if(state.invites.length===0){\r\n    const tr=document.createElement(\"tr\");\r\n    tr.innerHTML=`<td colspan=\"7\" style=\"text-align:center;background:#fafbff;border:1px solid var(--line);border-radius:8px\">No invites yet.<\/td>`;\r\n    tb.appendChild(tr);\r\n    return;\r\n  }\r\n  state.invites.forEach(inv=>{\r\n    const link = `${location.origin}\/invite\/accept?code=${inv.code}`;\r\n    const tr=document.createElement(\"tr\");\r\n    tr.innerHTML = `\r\n      <td>${inv.email}<\/td>\r\n      <td>${inv.role}<\/td>\r\n      <td>${fmtDate(inv.invitedAt)}<\/td>\r\n      <td>${fmtDate(inv.expiresAt)}<\/td>\r\n      <td>${badgeStatus(inv.status||\"Pending\")}<\/td>\r\n      <td><span class=\"hint\" title=\"${link}\">${maskInvite(inv.code)}<\/span><\/td>\r\n      <td style=\"text-align:right\">\r\n        <button class=\"btn small\" data-copy=\"${inv.id}\">Copy<\/button>\r\n        <button class=\"btn small\" data-resend=\"${inv.id}\">Resend<\/button>\r\n        <button class=\"btn small danger\" data-revoke=\"${inv.id}\">Revoke<\/button>\r\n      <\/td>\r\n    `;\r\n    tb.appendChild(tr);\r\n  });\r\n\r\n  $$('[data-copy]').forEach(b=>b.addEventListener(\"click\", ()=>{\r\n    const inv=state.invites.find(x=>x.id===b.getAttribute(\"data-copy\"));\r\n    const link = `${location.origin}\/invite\/accept?code=${inv.code}`;\r\n    navigator.clipboard?.writeText(link).then(()=>toast(\"Invite link copied\")).catch(()=>alert(link));\r\n  }));\r\n  $$('[data-resend]').forEach(b=>b.addEventListener(\"click\", ()=>{\r\n    const inv=state.invites.find(x=>x.id===b.getAttribute(\"data-resend\"));\r\n    if(inv.status===\"Revoked\"){ toast(\"Cannot resend a revoked invite\"); return; }\r\n    \/\/ simulate resend\r\n    toast(\"Invite resent\");\r\n  }));\r\n  $$('[data-revoke]').forEach(b=>b.addEventListener(\"click\", ()=>{\r\n    const inv=state.invites.find(x=>x.id===b.getAttribute(\"data-revoke\"));\r\n    if(!confirm(`Revoke invite for ${inv.email}?`)) return;\r\n    inv.status=\"Revoked\"; save(); renderInvites(); toast(\"Invite revoked\");\r\n  }));\r\n}\r\n\r\n\/* Invite modal handlers *\/\r\nfunction openInviteModal(){\r\n  $(\"#invEmail\").value=\"\"; $(\"#invRole\").value=\"Agent\"; $(\"#invExpiry\").value=\"30\"; $(\"#invNote\").value=\"\";\r\n  $(\"#invEmailErr\").textContent=\"\";\r\n  $(\"#inviteModal\").classList.add(\"open\");\r\n}\r\nfunction closeInviteModal(){ $(\"#inviteModal\").classList.remove(\"open\"); }\r\n$(\"#inviteBtn\").addEventListener(\"click\", openInviteModal);\r\n$(\"#openInviteBtn\").addEventListener(\"click\", openInviteModal);\r\n$(\"#cancelInviteBtn\").addEventListener(\"click\", (e)=>{ e.preventDefault(); closeInviteModal(); });\r\n\r\n$(\"#sendInviteBtn\").addEventListener(\"click\", (e)=>{\r\n  e.preventDefault();\r\n  const email=$(\"#invEmail\").value.trim();\r\n  const role=$(\"#invRole\").value;\r\n  const expiryDays=parseInt($(\"#invExpiry\").value,10);\r\n  $(\"#invEmailErr\").textContent=\"\";\r\n  if(!emailOK(email)){ $(\"#invEmailErr\").textContent=\"Enter a valid email\"; return; }\r\n  const inv = {\r\n    id:id(), email, role,\r\n    invitedAt:new Date().toISOString(),\r\n    expiresAt:addDays(expiryDays),\r\n    status:\"Pending\",\r\n    code: \"inv_\"+Math.random().toString(36).slice(2,10)+Math.random().toString(36).slice(2,10)\r\n  };\r\n  state.invites.unshift(inv); save(); renderInvites(); closeInviteModal();\r\n  toast(\"Invite sent \u2713\");\r\n});\r\n\r\n\/* Expiry check (run on load) *\/\r\nfunction sweepInvites(){\r\n  const now = Date.now();\r\n  state.invites.forEach(inv=>{\r\n    if(inv.status===\"Pending\" && new Date(inv.expiresAt).getTime() < now){\r\n      inv.status=\"Expired\";\r\n    }\r\n  });\r\n}\r\n\r\n\/* ===========================\r\n   INIT\r\n=========================== *\/\r\ndocument.addEventListener(\"DOMContentLoaded\", ()=>{\r\n  \/\/ Users\r\n  $(\"#inviteBtn\"); \/\/ wired above\r\n  $(\"#addUserBtn\"); \/\/ wired above\r\n  renderUsers();\r\n\r\n  \/\/ Permissions\r\n  renderPerms();\r\n\r\n  \/\/ Limits\r\n  loadCaps();\r\n\r\n  \/\/ Invites\r\n  sweepInvites(); renderInvites();\r\n\r\n  \/\/ Search\/filter debounce-ish\r\n  let t=null; $(\"#searchUser\").addEventListener(\"input\", ()=>{ clearTimeout(t); t=setTimeout(renderUsers, 120); });\r\n\r\n  \/\/ Modal close (Esc click outside)\r\n  [$(\"#inviteModal\"), $(\"#userModal\")].forEach(mod=>{\r\n    mod.addEventListener(\"click\",(e)=>{ if(e.target===mod) mod.classList.remove(\"open\"); });\r\n    document.addEventListener(\"keydown\",(e)=>{ if(e.key===\"Escape\") mod.classList.remove(\"open\"); });\r\n  });\r\n});\r\n<\/script>\r\n<\/body>\r\n<\/html>\r\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div id=\"e-n-tab-content-113480934\" role=\"tabpanel\" aria-labelledby=\"e-n-tab-title-113480934\" data-tab-index=\"4\" style=\"--n-tabs-title-order: 4;\" class=\" elementor-element elementor-element-550ad25 e-con-full e-flex e-con e-child\" data-id=\"550ad25\" data-element_type=\"container\" data-settings=\"{&quot;position&quot;:&quot;absolute&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-51714f7 elementor-widget elementor-widget-html\" data-id=\"51714f7\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n<meta charset=\"UTF-8\"\/>\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\/>\r\n<title>Notifications & Preferences<\/title>\r\n<style>\r\n  :root{\r\n    --bg:#f6f8fb;\r\n    --surface:#ffffff;\r\n    --text:#1e2430;\r\n    --muted:#6b7280;\r\n    --line:#e7eaf2;\r\n\r\n    --primary:#2d6bff;\r\n    --focus:rgba(45,107,255,.18);\r\n    --danger:#d92d20;\r\n    --good:#16a34a;\r\n    --warn:#f59e0b;\r\n\r\n    --radius-lg:16px;\r\n    --radius-md:12px;\r\n\r\n    --shadow-sm:0 1px 2px rgba(16,24,40,.06);\r\n    --shadow-md:0 6px 18px rgba(16,24,40,.08);\r\n  }\r\n\r\n  *{box-sizing:border-box}\r\n  html,body{\r\n    height:100%\r\n  }\r\n  body{\r\n    margin:0; \r\n    font:14px\/1.55 Inter, ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, Arial;\r\n    color:var(--text); \r\n    background:var(--bg); \r\n    padding:28px;\r\n  }\r\n  header{\r\n    max-width:1200px; \r\n    margin:0 auto 18px\r\n    text-align: left;\r\n  }\r\n  .h1{\r\n    font-size:22px; \r\n    font-weight:700; \r\n    margin:0 0 6px;\r\n    letter-spacing:.2px;\r\n    text-align:left; \r\n    white-space:nowrap;   \r\n    display:block; \r\n  }\r\n  .subtle{\r\n    color:var(--muted)\r\n  }\r\n\r\n  .container{\r\n    max-width:1200px; \r\n    margin:0 auto; \r\n    display:grid; \r\n    gap:22px\r\n  }\r\n\r\n  .card{\r\n    background:var(--surface);\r\n    border:1px solid var(--line);\r\n    border-radius:var(--radius-lg);\r\n    box-shadow:var(--shadow-sm);\r\n    overflow:hidden;\r\n  }\r\n  .card-h{\r\n    padding:18px 20px 12px; \r\n    border-bottom:1px solid var(--line); \r\n    background:linear-gradient(180deg,#fff,#fafbff)\r\n  }\r\n  .card-t{\r\n    font-weight:700\r\n  }\r\n  .card-d{\r\n    color:var(--muted); \r\n    font-size:13px;\r\n    margin-top:2px\r\n  }\r\n  .card-c{\r\n    padding:18px 20px\r\n  }\r\n\r\n  .grid-2{\r\n    display:grid; \r\n    grid-template-columns:1fr 1fr; \r\n    gap:14px\r\n  }\r\n  .grid-3{\r\n    display:grid; \r\n    grid-template-columns:repeat(3,1fr); \r\n    gap:14px\r\n  }\r\n  @media (max-width:960px){ .grid-2,.grid-3{grid-template-columns:1fr} }\r\n\r\n  label{\r\n    display:block; \r\n    font-weight:600; \r\n    font-size:12px;\r\n    letter-spacing:.28px; \r\n    text-transform:uppercase; \r\n    color:#7b8497; \r\n    margin:6px 0 8px\r\n  }\r\n  input[type=\"text\"], \r\n  input[type=\"email\"], \r\n  input[type=\"number\"], \r\n  input[type=\"time\"], \r\n  select{\r\n    width:100%; \r\n    background:#fff; \r\n    border:1px solid var(--line); \r\n    color:var(--text);\r\n    padding:12px; \r\n    border-radius:var(--radius-md); \r\n    outline:none; \r\n    transition:border-color .18s, box-shadow .18s;\r\n  }\r\n  input:focus, select:focus{\r\n    border-color:var(--primary); \r\n    box-shadow:0 0 0 4px var(--focus)\r\n  }\r\n  input::placeholder{\r\n    color:#9aa3b2\r\n  }\r\n\r\n  .row{\r\n    display:flex; \r\n    gap:10px; \r\n    align-items:center; \r\n    flex-wrap:wrap\r\n  }\r\n  .right{\r\n    margin-left:auto\r\n  }\r\n  .hint{\r\n    color:var(--muted); \r\n    font-size:12px; \r\n    margin-top:6px\r\n  }\r\n\r\n  .btn{\r\n    border:1px solid var(--line); \r\n    background:#fff; \r\n    color:var(--text);\r\n    padding:10px 14px; \r\n    border-radius:10px; \r\n    cursor:pointer; \r\n    font-weight:600;\r\n    transition:transform .12s, background .18s, border .18s;\r\n  }\r\n  .btn:hover{\r\n    background:#f9fafe}\r\n  .btn:active{\r\n    transform:translateY(1px)}\r\n  .btn.primary{\r\n    background:var(--primary); \r\n    border-color:#275de0; \r\n    color:#fff\r\n  }\r\n  .btn.danger{\r\n    background:#fff5f5; \r\n    border-color:#ffd6d6; \r\n    color:#b42318\r\n  }\r\n  .btn.ghost{\r\n    background:transparent\r\n  }\r\n  .btn.small{\r\n    padding:7px 10px\r\n  }\r\n  .btn[disabled]{\r\n    opacity:.6; \r\n    cursor:not-allowed\r\n  }\r\n\r\n  .badge{\r\n    display:inline-flex; \r\n    padding:5px 8px; \r\n    font-size:12px; \r\n    border-radius:999px; \r\n    border:1px solid var(--line); \r\n    background:#f7f8fc; \r\n    color:#4b5563\r\n  }\r\n  .badge.good{\r\n    background:#ecfdf5; \r\n    border-color:#a7f3d0; \r\n    color:#065f46\r\n  }\r\n  .badge.warn{\r\n    background:#fffbeb; \r\n    border-color:#fde68a; \r\n    color:#92400e\r\n  }\r\n  .badge.danger{\r\n    background:#fef2f2; \r\n    border-color:#fecaca; \r\n    color:#7f1d1d\r\n  }\r\n\r\n  .sep{\r\n    height:1px; \r\n    background:var(--line); \r\n    margin:12px 0\r\n  }\r\n\r\n  \/* Table \/ matrix *\/\r\n  table{\r\n    width:100%; \r\n    border-collapse:separate; \r\n    border-spacing:0 8px\r\n  }\r\n  th{\r\n    font-size:12px; \r\n    color:#7b8497; \r\n    text-align:left; \r\n    padding:0 10px\r\n  }\r\n  td{\r\n    background:#fff; \r\n    border:1px solid var(--line); \r\n    padding:10px; \r\n    border-radius:8px; \r\n    vertical-align:middle\r\n  }\r\n  tr td:first-child{\r\n    border-top-right-radius:0; \r\n    border-bottom-right-radius:0\r\n  }\r\n  tr td:last-child{\r\n    border-top-left-radius:0; \r\n    border-bottom-left-radius:0\r\n  }\r\n  .matrix th,.matrix td{ \r\n    text-align:center \r\n  }\r\n  .matrix td:first-child, .matrix th:first-child{ \r\n    text-align:left \r\n  }\r\n\r\n  \/* Day chips *\/\r\n  .chip{display:inline-flex; \r\n    align-items:center; \r\n    gap:8px; \r\n    padding:8px 10px; \r\n    border:1px solid var(--line); \r\n    border-radius:999px; \r\n    background:#f7f8fc; \r\n    user-select:none; \r\n    cursor:pointer}\r\n  .chip input{\r\n    accent-color:var(--primary)\r\n  }\r\n\r\n  \/* Preview banner *\/\r\n  .banner{\r\n    border:1px dashed var(--line); \r\n    background:#fbfcff; \r\n    border-radius:12px; \r\n    padding:12px 14px; \r\n    display:flex; \r\n    align-items:center; \r\n    gap:10px\r\n  }\r\n\r\n  \/* Toast *\/\r\n  .toast{\r\n    position:fixed; \r\n    right:20px; \r\n    bottom:20px; \r\n    background:#243b7b; \r\n    border:1px solid #314b95; \r\n    color:#e8efff;\r\n    padding:12px 14px; \r\n    border-radius:12px; \r\n    box-shadow:var(--shadow-md); \r\n    opacity:0; \r\n    transform:translateY(8px); \r\n    pointer-events:none; \r\n    transition:.25s\r\n  }\r\n  .toast.show{opacity:1; transform:translateY(0)}\r\n<\/style>\r\n<\/head>\r\n<body>\r\n  <header>\r\n    <div class=\"h1\">Notifications & Preferences<\/div>\r\n  <\/header>\r\n\r\n  <main class=\"container\">\r\n    <!-- Email & Push: Topics -->\r\n    <section class=\"card\" aria-labelledby=\"topics-title\">\r\n      <div class=\"card-h\">\r\n        <div id=\"topics-title\" class=\"card-t\">Email & Push Notifications<\/div>\r\n        <div class=\"card-d\">Choose which events should alert you<\/div>\r\n      <\/div>\r\n      <div class=\"card-c\">\r\n        <div class=\"grid-3\">\r\n          <div>\r\n            <label>Tickets<\/label>\r\n            <div class=\"row\"><label class=\"chip\"><input type=\"checkbox\" data-topic=\"ticket_updates\"\/> Ticket updates<\/label><\/div>\r\n            <div class=\"row\"><label class=\"chip\"><input type=\"checkbox\" data-topic=\"new_assignments\"\/> New assignments<\/label><\/div>\r\n            <div class=\"row\"><label class=\"chip\"><input type=\"checkbox\" data-topic=\"sla_breaches\"\/> SLA breaches<\/label><\/div>\r\n          <\/div>\r\n          <div>\r\n            <label>Collaboration<\/label>\r\n            <div class=\"row\"><label class=\"chip\"><input type=\"checkbox\" data-topic=\"customer_replies\"\/> Customer replies<\/label><\/div>\r\n            <div class=\"row\"><label class=\"chip\"><input type=\"checkbox\" data-topic=\"mentions\"\/> Mentions (@you)<\/label><\/div>\r\n            <div class=\"row\"><label class=\"chip\"><input type=\"checkbox\" data-topic=\"escalations\"\/> Escalations<\/label><\/div>\r\n          <\/div>\r\n          <div>\r\n            <label>Digest<\/label>\r\n            <div class=\"row\"><label class=\"chip\"><input type=\"checkbox\" data-topic=\"daily_digest\"\/> Daily summary (email)<\/label><\/div>\r\n            <div class=\"row\"><label class=\"chip\"><input type=\"checkbox\" data-topic=\"weekly_digest\"\/> Weekly summary (email)<\/label><\/div>\r\n          <\/div>\r\n        <\/div>\r\n        <div class=\"sep\"><\/div>\r\n        <div class=\"banner\">\r\n          <span class=\"badge\">Tip<\/span>\r\n          Toggle event topics above, then map them to channels in the matrix below.\r\n        <\/div>\r\n      <\/div>\r\n    <\/section>\r\n\r\n    <!-- Channels Matrix -->\r\n    <section class=\"card\" aria-labelledby=\"channels-title\">\r\n      <div class=\"card-h\">\r\n        <div id=\"channels-title\" class=\"card-t\">Channels<\/div>\r\n        <div class=\"card-d\">Select how each event notifies you<\/div>\r\n      <\/div>\r\n      <div class=\"card-c\">\r\n        <div class=\"row\" style=\"margin-bottom:10px\">\r\n          <div class=\"badge\">Channels: Email, In-App, SMS, Slack, Push<\/div>\r\n          <div class=\"right row\">\r\n            <button class=\"btn small\" id=\"matrixAllOn\">Enable All<\/button>\r\n            <button class=\"btn small\" id=\"matrixAllOff\">Disable All<\/button>\r\n            <button class=\"btn small primary\" id=\"testNotifBtn\">Send Test Notification<\/button>\r\n          <\/div>\r\n        <\/div>\r\n        <table class=\"matrix\" aria-label=\"Notification Channel Matrix\">\r\n          <thead>\r\n            <tr>\r\n              <th>Event<\/th>\r\n              <th>Email<\/th>\r\n              <th>In-App<\/th>\r\n              <th>SMS<\/th>\r\n              <th>Slack<\/th>\r\n              <th>Push<\/th>\r\n            <\/tr>\r\n          <\/thead>\r\n          <tbody id=\"matrixTbody\"><\/tbody>\r\n        <\/table>\r\n        <div class=\"hint\" style=\"margin-top:8px\">Hold <strong>Alt<\/strong> and click a channel header to toggle the entire column.<\/div>\r\n      <\/div>\r\n    <\/section>\r\n\r\n    <!-- Custom Rules -->\r\n    <section class=\"card\" aria-labelledby=\"rules-title\">\r\n      <div class=\"card-h\">\r\n        <div id=\"rules-title\" class=\"card-t\">Custom Rules<\/div>\r\n        <div class=\"card-d\">Granular controls & Do Not Disturb<\/div>\r\n      <\/div>\r\n      <div class=\"card-c\">\r\n        <div class=\"grid-3\">\r\n          <div>\r\n            <label>Triggers<\/label>\r\n            <div class=\"row\"><label class=\"chip\"><input type=\"checkbox\" data-rule=\"high_priority_only\"\/> Only high-priority tickets<\/label><\/div>\r\n            <div class=\"row\"><label class=\"chip\"><input type=\"checkbox\" data-rule=\"own_tickets_only\"\/> Only tickets I own<\/label><\/div>\r\n            <div class=\"row\"><label class=\"chip\"><input type=\"checkbox\" data-rule=\"followed_tags\"\/> Followed tags only<\/label><\/div>\r\n          <\/div>\r\n          <div>\r\n            <label>Do Not Disturb<\/label>\r\n            <div class=\"row\">\r\n              <label class=\"chip\"><input type=\"checkbox\" id=\"dndEnabled\"\/> Enable DND schedule<\/label>\r\n            <\/div>\r\n            <div class=\"row\">\r\n              <input id=\"dndStart\" type=\"time\" value=\"22:00\" style=\"max-width:140px\"\/>\r\n              <span>to<\/span>\r\n              <input id=\"dndEnd\" type=\"time\" value=\"07:00\" style=\"max-width:140px\"\/>\r\n            <\/div>\r\n            <div class=\"row\" style=\"gap:8px; margin-top:6px\" id=\"dndDays\">\r\n              <!-- Day chips -->\r\n            <\/div>\r\n            <div class=\"hint\">Notifications are silenced during DND hours for selected days.<\/div>\r\n          <\/div>\r\n          <div>\r\n            <label>Temporary Mute<\/label>\r\n            <div class=\"row\">\r\n              <select id=\"muteFor\" style=\"min-width:180px\">\r\n                <option value=\"0\">Select duration\u2026<\/option>\r\n                <option value=\"30\">Mute for 30 minutes<\/option>\r\n                <option value=\"60\">Mute for 1 hour<\/option>\r\n                <option value=\"480\">Mute for 8 hours<\/option>\r\n              <\/select>\r\n              <button class=\"btn\" id=\"muteBtn\">Mute<\/button>\r\n              <button class=\"btn ghost\" id=\"unmuteBtn\">Unmute<\/button>\r\n            <\/div>\r\n            <div class=\"hint\" id=\"muteHint\">Not muted.<\/div>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n    <\/section>\r\n\r\n    <!-- Sound & Alerts -->\r\n    <section class=\"card\" aria-labelledby=\"sound-title\">\r\n      <div class=\"card-h\">\r\n        <div id=\"sound-title\" class=\"card-t\">Sound & Alert Settings<\/div>\r\n        <div class=\"card-d\">Fine-tune audible + visual alerts<\/div>\r\n      <\/div>\r\n      <div class=\"card-c\">\r\n        <div class=\"grid-3\">\r\n          <div>\r\n            <label>Notification Sound<\/label>\r\n            <div class=\"row\">\r\n              <label class=\"chip\"><input type=\"checkbox\" id=\"soundEnabled\"\/> Enable sound<\/label>\r\n            <\/div>\r\n            <div class=\"row\" style=\"margin-top:8px\">\r\n              <select id=\"soundPreset\" style=\"min-width:180px\">\r\n                <option value=\"chime\">Chime<\/option>\r\n                <option value=\"ding\">Ding<\/option>\r\n                <option value=\"ping\">Ping<\/option>\r\n              <\/select>\r\n              <button class=\"btn\" id=\"testSoundBtn\">Test Sound<\/button>\r\n            <\/div>\r\n          <\/div>\r\n          <div>\r\n            <label>Visual Alerts<\/label>\r\n            <div class=\"row\"><label class=\"chip\"><input type=\"checkbox\" id=\"desktopBadge\"\/> Desktop badge count<\/label><\/div>\r\n            <div class=\"row\"><label class=\"chip\"><input type=\"checkbox\" id=\"showToasts\" checked\/> Show toast popups<\/label><\/div>\r\n          <\/div>\r\n          <div>\r\n            <label>Escalation Nudge<\/label>\r\n            <div class=\"row\"><label class=\"chip\"><input type=\"checkbox\" id=\"repeatEscalations\"\/> Repeat escalations every 10 min<\/label><\/div>\r\n            <div class=\"row\"><label class=\"chip\"><input type=\"checkbox\" id=\"snoozeAfterFocus\"\/> Snooze alerts when in a meeting<\/label><\/div>\r\n          <\/div>\r\n        <\/div>\r\n\r\n        <div class=\"sep\"><\/div>\r\n\r\n        <div class=\"row\">\r\n          <button class=\"btn danger\" id=\"restoreBtn\">Restore Defaults<\/button>\r\n          <div class=\"right\">\r\n            <button class=\"btn\" id=\"cancelBtn\">Cancel<\/button>\r\n            <button class=\"btn primary\" id=\"saveBtn\">Save Changes<\/button>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n    <\/section>\r\n\r\n    <!-- Live status -->\r\n    <section class=\"card\" aria-labelledby=\"status-title\">\r\n      <div class=\"card-h\">\r\n        <div id=\"status-title\" class=\"card-t\">Status<\/div>\r\n        <div class=\"card-d\">Current delivery posture (honors DND and Mute)<\/div>\r\n      <\/div>\r\n      <div class=\"card-c\">\r\n        <div id=\"statusBanner\" class=\"banner\">\r\n          <span class=\"badge good\">Active<\/span>\r\n          <div id=\"statusText\">Notifications are being delivered.<\/div>\r\n        <\/div>\r\n      <\/div>\r\n    <\/section>\r\n  <\/main>\r\n\r\n  <div id=\"toast\" class=\"toast\" role=\"status\" aria-live=\"polite\"><\/div>\r\n\r\n<script>\r\n\/* ===========================\r\n   State & Utilities\r\n=========================== *\/\r\nconst $=(s,ctx=document)=>ctx.querySelector(s);\r\nconst $$=(s,ctx=document)=>Array.from(ctx.querySelectorAll(s));\r\nconst STORAGE_KEY=\"notify.prefs.v1\";\r\n\r\nconst TOPICS = [\r\n  [\"ticket_updates\",\"Ticket updates\"],\r\n  [\"new_assignments\",\"New assignments\"],\r\n  [\"sla_breaches\",\"SLA breaches\"],\r\n  [\"customer_replies\",\"Customer replies\"],\r\n  [\"mentions\",\"Mentions\"],\r\n  [\"escalations\",\"Escalations\"],\r\n  [\"daily_digest\",\"Daily digest\"],\r\n  [\"weekly_digest\",\"Weekly digest\"],\r\n];\r\n\r\nconst CHANNELS = [\"email\",\"inapp\",\"sms\",\"slack\",\"push\"];\r\nconst DAYS = [\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\",\"Sat\",\"Sun\"];\r\n\r\nconst defaults = {\r\n  topics: {\r\n    ticket_updates:true, new_assignments:true, sla_breaches:true,\r\n    customer_replies:true, mentions:true, escalations:true,\r\n    daily_digest:false, weekly_digest:true\r\n  },\r\n  matrix: { }, \/\/ filled below with defaults\r\n  rules: { high_priority_only:false, own_tickets_only:false, followed_tags:false },\r\n  dnd: { enabled:false, start:\"22:00\", end:\"07:00\", days:[\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\"] },\r\n  mute: { until:0 }, \/\/ epoch ms\r\n  sound: { enabled:true, preset:\"chime\" },\r\n  alerts: { desktopBadge:false, showToasts:true, repeatEscalations:false, snoozeAfterFocus:true }\r\n};\r\n\/\/ default matrix: important events enabled for email+inapp, escalations also SMS+push\r\nTOPICS.forEach(([k])=>{\r\n  defaults.matrix[k] = { email:false, inapp:false, sms:false, slack:false, push:false };\r\n});\r\n[\"ticket_updates\",\"new_assignments\",\"customer_replies\",\"mentions\"].forEach(k=>{\r\n  defaults.matrix[k].email = true; defaults.matrix[k].inapp = true;\r\n});\r\n[\"sla_breaches\",\"escalations\"].forEach(k=>{\r\n  defaults.matrix[k].email = true; defaults.matrix[k].inapp = true; defaults.matrix[k].push = true; defaults.matrix[k].sms = (k===\"escalations\");\r\n});\r\ndefaults.matrix[\"daily_digest\"].email = true;\r\ndefaults.matrix[\"weekly_digest\"].email = true;\r\n\r\nlet state = load();\r\nlet snapshot = JSON.parse(JSON.stringify(state)); \/\/ for Cancel\r\n\r\nfunction load(){\r\n  const raw = localStorage.getItem(STORAGE_KEY);\r\n  return raw ? JSON.parse(raw) : structuredClone(defaults);\r\n}\r\nfunction save(){\r\n  localStorage.setItem(STORAGE_KEY, JSON.stringify(state));\r\n  snapshot = JSON.parse(JSON.stringify(state));\r\n  toast(\"Saved \u2713\");\r\n}\r\nfunction restoreDefaults(){\r\n  state = structuredClone(defaults);\r\n  save();\r\n  renderAll();\r\n}\r\nfunction toast(msg){\r\n  const t=$(\"#toast\"); t.textContent=msg; t.classList.add(\"show\");\r\n  setTimeout(()=>t.classList.remove(\"show\"),1500);\r\n}\r\n\r\n\/* ===========================\r\n   Renderers\r\n=========================== *\/\r\nfunction renderTopics(){\r\n  TOPICS.forEach(([key])=>{\r\n    const cb = document.querySelector(`[data-topic=\"${key}\"]`);\r\n    if(cb){ cb.checked = !!state.topics[key]; }\r\n  });\r\n}\r\n\r\nfunction renderMatrix(){\r\n  const tb = $(\"#matrixTbody\"); tb.innerHTML = \"\";\r\n  TOPICS.forEach(([key,label])=>{\r\n    const tr = document.createElement(\"tr\");\r\n    const disabled = !state.topics[key];\r\n    tr.innerHTML = `\r\n      <td style=\"text-align:left; ${disabled?'opacity:.55':''}\">\r\n        <label class=\"chip\"><input type=\"checkbox\" data-topic=\"${key}\" ${state.topics[key]?'checked':''}\/> ${label}<\/label>\r\n      <\/td>\r\n      ${CHANNELS.map(ch=>{\r\n        const on = !!state.matrix[key][ch];\r\n        return `<td><input type=\"checkbox\" ${on?'checked':''} data-matrix=\"${key}:${ch}\" ${disabled?'disabled':''}\/><\/td>`\r\n      }).join(\"\")}\r\n    `;\r\n    tb.appendChild(tr);\r\n  });\r\n\r\n  \/\/ (Re)bind\r\n  $$('[data-topic]').forEach(cb=>{\r\n    cb.addEventListener('change', ()=>{\r\n      state.topics[cb.getAttribute('data-topic')] = cb.checked;\r\n      renderMatrix(); \/\/ refresh row disabled states\r\n    });\r\n  });\r\n  $$('[data-matrix]').forEach(cb=>{\r\n    cb.addEventListener('change', ()=>{\r\n      const [k,ch] = cb.getAttribute('data-matrix').split(':');\r\n      state.matrix[k][ch] = cb.checked;\r\n    });\r\n  });\r\n}\r\n\r\nfunction renderRules(){\r\n  \/\/ Triggers\r\n  $$('[data-rule]').forEach(cb=> cb.checked = !!state.rules[cb.getAttribute('data-rule')]);\r\n\r\n  \/\/ DND\r\n  $(\"#dndEnabled\").checked = state.dnd.enabled;\r\n  $(\"#dndStart\").value = state.dnd.start;\r\n  $(\"#dndEnd\").value = state.dnd.end;\r\n\r\n  const daysWrap = $(\"#dndDays\"); daysWrap.innerHTML=\"\";\r\n  DAYS.forEach(d=>{\r\n    const id = \"dnd-\"+d;\r\n    const el = document.createElement(\"label\");\r\n    el.className = \"chip\";\r\n    el.innerHTML = `<input type=\"checkbox\" id=\"${id}\" ${state.dnd.days.includes(d)?'checked':''}\/> ${d}`;\r\n    daysWrap.appendChild(el);\r\n    el.querySelector(\"input\").addEventListener(\"change\", (e)=>{\r\n      const on=e.target.checked;\r\n      const has = state.dnd.days.includes(d);\r\n      if(on && !has) state.dnd.days.push(d);\r\n      if(!on && has) state.dnd.days = state.dnd.days.filter(x=>x!==d);\r\n      updateStatus();\r\n    });\r\n  });\r\n}\r\n\r\nfunction renderSound(){\r\n  $(\"#soundEnabled\").checked = !!state.sound.enabled;\r\n  $(\"#soundPreset\").value = state.sound.preset;\r\n  $(\"#desktopBadge\").checked = !!state.alerts.desktopBadge;\r\n  $(\"#showToasts\").checked = !!state.alerts.showToasts;\r\n  $(\"#repeatEscalations\").checked = !!state.alerts.repeatEscalations;\r\n  $(\"#snoozeAfterFocus\").checked = !!state.alerts.snoozeAfterFocus;\r\n}\r\n\r\nfunction renderMute(){\r\n  const now = Date.now();\r\n  if(state.mute.until && state.mute.until>now){\r\n    $(\"#muteHint\").textContent = \"Muted until \" + new Date(state.mute.until).toLocaleString();\r\n  }else{\r\n    $(\"#muteHint\").textContent = \"Not muted.\";\r\n  }\r\n}\r\n\r\nfunction updateStatus(){\r\n  const banner = $(\"#statusBanner\");\r\n  const text = $(\"#statusText\");\r\n  const now = new Date();\r\n  const day = DAYS[(now.getDay()+6)%7]; \/\/ Mon=0\r\n  const time = now.toTimeString().slice(0,5);\r\n\r\n  const muted = state.mute.until && state.mute.until > Date.now();\r\n  const inDND = state.dnd.enabled && state.dnd.days.includes(day) && isWithinDND(time, state.dnd.start, state.dnd.end);\r\n\r\n  if(muted){\r\n    banner.querySelector(\".badge\").className=\"badge warn\";\r\n    banner.querySelector(\".badge\").textContent=\"Muted\";\r\n    text.textContent=\"Temporary mute is active. Notifications are paused.\";\r\n  }else if(inDND){\r\n    banner.querySelector(\".badge\").className=\"badge warn\";\r\n    banner.querySelector(\".badge\").textContent=\"DND\";\r\n    text.textContent=`Do Not Disturb active (${state.dnd.start}\u2013${state.dnd.end} on selected days).`;\r\n  }else{\r\n    banner.querySelector(\".badge\").className=\"badge good\";\r\n    banner.querySelector(\".badge\").textContent=\"Active\";\r\n    text.textContent=\"Notifications are being delivered.\";\r\n  }\r\n}\r\n\r\nfunction renderAll(){\r\n  renderTopics();\r\n  renderMatrix();\r\n  renderRules();\r\n  renderSound();\r\n  renderMute();\r\n  updateStatus();\r\n}\r\n\r\n\/* ===========================\r\n   Helpers\r\n=========================== *\/\r\nfunction isWithinDND(current, start, end){\r\n  \/\/ times: \"HH:MM\"\r\n  const toMin = t => {\r\n    const [h,m]=t.split(\":\").map(Number);\r\n    return h*60+m;\r\n  };\r\n  const cur = toMin(current), s=toMin(start), e=toMin(end);\r\n  if(s<=e) return cur>=s && cur<e; \/\/ same day window\r\n  return cur>=s || cur<e;         \/\/ overnight window\r\n}\r\n\r\nfunction applyColumnToggle(index, on){\r\n  \/\/ index: 1..5 (Email..Push) matches CHANNELS order\r\n  const ch = CHANNELS[index-1];\r\n  TOPICS.forEach(([k])=>{\r\n    if(!state.topics[k]) return;\r\n    state.matrix[k][ch] = on;\r\n  });\r\n  renderMatrix();\r\n}\r\n\r\n\/* ===========================\r\n   Events \/ Wiring\r\n=========================== *\/\r\ndocument.addEventListener(\"DOMContentLoaded\", ()=>{\r\n  \/\/ Load \u2192 render\r\n  renderAll();\r\n\r\n  \/\/ Topics panel direct toggles\r\n  $$('[data-topic]').forEach(cb=>{\r\n    cb.addEventListener('change', ()=>{\r\n      state.topics[cb.getAttribute('data-topic')] = cb.checked;\r\n      renderMatrix();\r\n    });\r\n  });\r\n\r\n  \/\/ Matrix column toggle (Alt+click on header)\r\n  const heads = $$(\"#channels-title ~ .card-c thead th\");\r\n  heads.forEach((th,i)=>{\r\n    if(i===0) return; \/\/ \"Event\"\r\n    th.style.cursor=\"pointer\";\r\n    th.title=\"Alt+Click: Toggle entire column\";\r\n    th.addEventListener(\"click\", (e)=>{\r\n      if(!e.altKey) return;\r\n      \/\/ Determine current majority state to flip\r\n      const ch = CHANNELS[i-1];\r\n      const vals = TOPICS.filter(([k])=>state.topics[k]).map(([k])=>state.matrix[k][ch]);\r\n      const on = !(vals.filter(Boolean).length > vals.length\/2);\r\n      applyColumnToggle(i, on);\r\n      toast(`${ch.toUpperCase()} column ${on?'enabled':'disabled'}`);\r\n    });\r\n  });\r\n\r\n  \/\/ Rules\r\n  $$('[data-rule]').forEach(cb=>{\r\n    cb.addEventListener('change', ()=> state.rules[cb.getAttribute('data-rule')] = cb.checked);\r\n  });\r\n  $(\"#dndEnabled\").addEventListener(\"change\", ()=>{ state.dnd.enabled = $(\"#dndEnabled\").checked; updateStatus(); });\r\n  $(\"#dndStart\").addEventListener(\"change\", ()=>{ state.dnd.start = $(\"#dndStart\").value; updateStatus(); });\r\n  $(\"#dndEnd\").addEventListener(\"change\", ()=>{ state.dnd.end = $(\"#dndEnd\").value; updateStatus(); });\r\n\r\n  \/\/ Mute\r\n  $(\"#muteBtn\").addEventListener(\"click\", ()=>{\r\n    const mins = parseInt($(\"#muteFor\").value,10);\r\n    if(!mins){ toast(\"Select a mute duration\"); return; }\r\n    state.mute.until = Date.now() + mins*60*1000;\r\n    renderMute(); updateStatus(); toast(\"Muted\");\r\n  });\r\n  $(\"#unmuteBtn\").addEventListener(\"click\", ()=>{\r\n    state.mute.until = 0; renderMute(); updateStatus(); toast(\"Unmuted\");\r\n  });\r\n\r\n  \/\/ Sound & Alerts\r\n  $(\"#soundEnabled\").addEventListener(\"change\", ()=> state.sound.enabled = $(\"#soundEnabled\").checked);\r\n  $(\"#soundPreset\").addEventListener(\"change\", ()=> state.sound.preset = $(\"#soundPreset\").value);\r\n  $(\"#desktopBadge\").addEventListener(\"change\", ()=> state.alerts.desktopBadge = $(\"#desktopBadge\").checked);\r\n  $(\"#showToasts\").addEventListener(\"change\", ()=> state.alerts.showToasts = $(\"#showToasts\").checked);\r\n  $(\"#repeatEscalations\").addEventListener(\"change\", ()=> state.alerts.repeatEscalations = $(\"#repeatEscalations\").checked);\r\n  $(\"#snoozeAfterFocus\").addEventListener(\"change\", ()=> state.alerts.snoozeAfterFocus = $(\"#snoozeAfterFocus\").checked);\r\n\r\n  \/\/ Matrix all on\/off\r\n  $(\"#matrixAllOn\").addEventListener(\"click\", ()=>{\r\n    TOPICS.forEach(([k])=>{\r\n      if(!state.topics[k]) return;\r\n      CHANNELS.forEach(ch=> state.matrix[k][ch]=true);\r\n    });\r\n    renderMatrix(); toast(\"All channels enabled for active events\");\r\n  });\r\n  $(\"#matrixAllOff\").addEventListener(\"click\", ()=>{\r\n    TOPICS.forEach(([k])=>{\r\n      CHANNELS.forEach(ch=> state.matrix[k][ch]=false);\r\n    });\r\n    renderMatrix(); toast(\"All channels disabled\");\r\n  });\r\n\r\n  \/\/ Test sound\r\n  $(\"#testSoundBtn\").addEventListener(\"click\", ()=> playSound(state.sound.preset, state.sound.enabled));\r\n\r\n  \/\/ Test notification\r\n  $(\"#testNotifBtn\").addEventListener(\"click\", sendTestNotification);\r\n\r\n  \/\/ Save \/ Cancel \/ Restore\r\n  $(\"#saveBtn\").addEventListener(\"click\", ()=>{ save(); updateStatus(); });\r\n  $(\"#cancelBtn\").addEventListener(\"click\", ()=>{\r\n    state = JSON.parse(JSON.stringify(snapshot));\r\n    renderAll();\r\n    toast(\"Changes reverted\");\r\n  });\r\n  $(\"#restoreBtn\").addEventListener(\"click\", ()=>{\r\n    if(confirm(\"Restore default preferences?\")) restoreDefaults();\r\n  });\r\n\r\n  \/\/ Keep status live (DND window)\r\n  setInterval(updateStatus, 30_000);\r\n});\r\n\r\n\/* ===========================\r\n   Sounds via WebAudio\r\n=========================== *\/\r\nfunction playSound(preset=\"chime\", enabled=true){\r\n  if(!enabled) { toast(\"Sound is disabled\"); return; }\r\n  try{\r\n    const ctx = new (window.AudioContext||window.webkitAudioContext)();\r\n    const o = ctx.createOscillator();\r\n    const g = ctx.createGain();\r\n    o.connect(g); g.connect(ctx.destination);\r\n\r\n    let freq=660, dur=0.2, pattern=[1];\r\n    if(preset===\"ding\"){ freq=880; dur=0.15; pattern=[1,1.1]; }\r\n    if(preset===\"ping\"){ freq=1046; dur=0.12; pattern=[1,1.18,0.9]; }\r\n\r\n    let t=ctx.currentTime;\r\n    pattern.forEach((p,i)=>{\r\n      o.frequency.setValueAtTime(freq*p, t);\r\n      g.gain.setValueAtTime(0.0001, t);\r\n      g.gain.exponentialRampToValueAtTime(0.5, t+0.02);\r\n      g.gain.exponentialRampToValueAtTime(0.0001, t+dur);\r\n      t += dur + 0.05;\r\n    });\r\n    o.start(); o.stop(t+0.01);\r\n  }catch(e){ console.warn(e); }\r\n}\r\n\r\n\/* ===========================\r\n   Test Notification (honors DND & Mute)\r\n=========================== *\/\r\nfunction isSuppressed(){\r\n  const muted = state.mute.until && state.mute.until > Date.now();\r\n  const now = new Date();\r\n  const day = DAYS[(now.getDay()+6)%7];\r\n  const time = now.toTimeString().slice(0,5);\r\n  const inDND = state.dnd.enabled && state.dnd.days.includes(day) && isWithinDND(time, state.dnd.start, state.dnd.end);\r\n  return muted || inDND;\r\n}\r\n\r\nfunction sendTestNotification(){\r\n  if(isSuppressed()){\r\n    toast(\"Suppressed by DND \/ Mute\");\r\n    return;\r\n  }\r\n  \/\/ find channels enabled for a representative event\r\n  const sample = \"ticket_updates\";\r\n  const chs = Object.entries(state.matrix[sample]).filter(([,v])=>v).map(([k])=>k.toUpperCase());\r\n  if(chs.length===0){ toast(\"No channels enabled for Ticket updates\"); return; }\r\n\r\n  if(state.alerts.showToasts) toast(\"Test notification via: \" + chs.join(\", \"));\r\n  playSound(state.sound.preset, state.sound.enabled);\r\n}\r\n<\/script>\r\n<\/body>\r\n<\/html>\r\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div id=\"e-n-tab-content-113480935\" role=\"tabpanel\" aria-labelledby=\"e-n-tab-title-113480935\" data-tab-index=\"5\" style=\"--n-tabs-title-order: 5;\" class=\" elementor-element elementor-element-13aa4bb e-con-full e-flex e-con e-child\" data-id=\"13aa4bb\" data-element_type=\"container\" data-settings=\"{&quot;position&quot;:&quot;absolute&quot;}\">\n\t\t\t\t<div class=\"elementor-element elementor-element-a6f2219 elementor-widget elementor-widget-html\" data-id=\"a6f2219\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n<meta charset=\"UTF-8\"\/>\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\/>\r\n<title>Automation & Workflows<\/title>\r\n<style>\r\n  :root{\r\n    --bg:#f6f8fb;\r\n    --surface:#ffffff;\r\n    --text:#1e2430;\r\n    --muted:#6b7280;\r\n    --line:#e7eaf2;\r\n\r\n    --primary:#2d6bff;\r\n    --focus:rgba(45,107,255,.18);\r\n    --accent:#0ba98b;\r\n    --danger:#d92d20;\r\n    --warn:#f59e0b;\r\n    --good:#16a34a;\r\n\r\n    --radius-lg:16px;\r\n    --radius-md:12px;\r\n\r\n    --shadow-sm:0 1px 2px rgba(16,24,40,.06);\r\n    --shadow-md:0 6px 18px rgba(16,24,40,.08);\r\n  }\r\n\r\n  *{box-sizing:border-box}\r\n  html,body{\r\n    height:100%\r\n  }\r\n  body{\r\n    margin:0; \r\n    font:14px\/1.55 Inter, ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, Arial;\r\n    color:var(--text); \r\n    background:var(--bg); \r\n    padding:28px;\r\n  }\r\n\r\n  header{\r\n    max-width:1200px; \r\n    margin:0 auto 18px\r\n  }\r\n  .h1{\r\n    font-size:22px; \r\n    font-weight:700; \r\n    margin:0 0 6px}\r\n  .subtle{\r\n    color:var(--muted)\r\n  }\r\n\r\n  .container{\r\n    max-width:1200px; \r\n    margin:0 auto; \r\n    display:grid; \r\n    gap:22px\r\n  }\r\n\r\n  .card{\r\n    background:var(--surface);\r\n    border:1px solid var(--line);\r\n    border-radius:var(--radius-lg);\r\n    box-shadow:var(--shadow-sm);\r\n    overflow:hidden;\r\n  }\r\n  .card-h{\r\n    padding:18px 20px 12px; \r\n    border-bottom:1px solid var(--line); \r\n    background:linear-gradient(180deg,#fff,#fafbff)\r\n  }\r\n  .card-t{\r\n    font-weight:700\r\n  }\r\n  .card-d{\r\n    color:var(--muted); \r\n    font-size:13px; \r\n    margin-top:2px\r\n  }\r\n  .card-c{\r\n    padding:18px 20px\r\n  }\r\n\r\n  .grid-2{\r\n    display:grid; \r\n    grid-template-columns:1fr 1fr; \r\n    gap:14px\r\n  }\r\n  .grid-3{\r\n    display:grid; \r\n    grid-template-columns:repeat(3,1fr); \r\n    gap:14px\r\n  }\r\n  .grid-4{\r\n    display:grid; \r\n    grid-template-columns:repeat(4,1fr); \r\n    gap:14px\r\n  }\r\n  @media (max-width:980px){ .grid-2,.grid-3,.grid-4{grid-template-columns:1fr} }\r\n\r\n  label{\r\n    display:block; \r\n    font-weight:600; \r\n    font-size:12px; \r\n    letter-spacing:.28px; \r\n    text-transform:uppercase; \r\n    color:#7b8497; \r\n    margin:6px 0 8px\r\n  }\r\n  input[type=\"text\"],\r\n  input[type=\"number\"],\r\n  input[type=\"search\"],\r\n  input[type=\"time\"],\r\n  input[type=\"date\"],\r\n  select,textarea{\r\n    width:100%; \r\n    background:#fff; \r\n    border:1px solid var(--line); \r\n    color:var(--text);\r\n    padding:12px; \r\n    border-radius:var(--radius-md); \r\n    outline:none; \r\n    transition:border-color .18s, box-shadow .18s;\r\n  }\r\n  textarea{\r\n    min-height:120px; \r\n    resize:vertical\r\n  }\r\n  input:focus,select:focus,textarea:focus{\r\n    border-color:var(--primary); \r\n    box-shadow:0 0 0 4px var(--focus)\r\n  }\r\n  input::placeholder,textarea::placeholder{\r\n    color:#9aa3b2\r\n  }\r\n\r\n  .row{\r\n    display:flex; \r\n    gap:10px; \r\n    align-items:center; \r\n    flex-wrap:wrap\r\n  }\r\n  .right{\r\n    margin-left:auto\r\n  }\r\n  .hint{\r\n    color:var(--muted); \r\n    font-size:12px; \r\n    margin-top:6px\r\n  }\r\n\r\n  .btn{\r\n    border:1px solid var(--line); \r\n    background:#fff; \r\n    color:var(--text);\r\n    padding:10px 14px; \r\n    border-radius:10px; \r\n    cursor:pointer; \r\n    font-weight:600;\r\n    transition:transform .12s, background .18s, border .18s;\r\n  }\r\n  .btn:hover{\r\n    background:#f9fafe\r\n  }\r\n  .btn:active{\r\n    transform:translateY(1px)\r\n  }\r\n  .btn.primary{\r\n    background:var(--primary); \r\n    border-color:#275de0; \r\n    color:#fff\r\n  }\r\n  .btn.accent{\r\n    background:var(--accent); \r\n    border-color:#089e80; \r\n    color:#fff\r\n  }\r\n  .btn.danger{\r\n    background:#fff5f5; \r\n    border-color:#ffd6d6; \r\n    color:#b42318\r\n  }\r\n  .btn.small{\r\n    padding:7px 10px\r\n  }\r\n  .btn.ghost{\r\n    background:transparent\r\n  }\r\n  .btn[disabled]{\r\n    opacity:.6; \r\n    cursor:not-allowed\r\n  }\r\n\r\n  .badge{\r\n    display:inline-flex; \r\n    padding:5px 8px; \r\n    font-size:12px; \r\n    border-radius:999px; \r\n    border:1px solid var(--line); \r\n    background:#f7f8fc; \r\n    color:#4b5563\r\n  }\r\n  .badge.good{\r\n    background:#ecfdf5; \r\n    border-color:#a7f3d0; \r\n    color:#065f46\r\n  }\r\n  .badge.warn{\r\n    background:#fffbeb; \r\n    border-color:#fde68a; \r\n    color:#92400e\r\n  }\r\n  .badge.danger{\r\n    background:#fef2f2; \r\n    border-color:#fecaca; \r\n    color:#7f1d1d\r\n  }\r\n\r\n  .sep{height:1px; \r\n    background:var(--line); \r\n    margin:12px 0\r\n  }\r\n\r\n  \/* Tables *\/\r\n  table{\r\n    width:100%; \r\n    border-collapse:separate; \r\n    border-spacing:0 8px\r\n  }\r\n  th{\r\n    font-size:12px;\r\n    color:#7b8497;\r\n    text-align:left; \r\n    padding:0 10px\r\n  }\r\n  td{\r\n    background:#fff; \r\n    border:1px solid var(--line); \r\n    padding:10px; \r\n    border-radius:8px; \r\n    vertical-align:middle\r\n  }\r\n  tr td:first-child{\r\n    border-top-right-radius:0; \r\n    border-bottom-right-radius:0\r\n  }\r\n  tr td:last-child{\r\n    border-top-left-radius:0; \r\n    border-bottom-left-radius:0\r\n  }\r\n\r\n  \/* Pills \/ chips *\/\r\n  .chip{\r\n    display:inline-flex; \r\n    align-items:center; gap:8px; \r\n    padding:8px 10px; \r\n    border:1px solid var(--line); \r\n    border-radius:999px; \r\n    background:#f7f8fc; \r\n    user-select:none\r\n  }\r\n  .chip input{\r\n    accent-color:var(--primary)\r\n  }\r\n\r\n  \/* Tiny code style *\/\r\n  code{\r\n    background:#f7f8fc; \r\n    border:1px solid var(--line); \r\n    padding:2px 6px; \r\n    border-radius:6px\r\n  }\r\n\r\n  \/* Modal *\/\r\n  .modal{\r\n    position:fixed; \r\n    inset:0; \r\n    display:none; \r\n    align-items:center; \r\n    justify-content:center; \r\n    background:rgba(2,8,23,.45); \r\n    z-index:50; \r\n    padding:22px\r\n  }\r\n  .modal.open{\r\n    display:flex\r\n  }\r\n  .dialog{\r\n    width:min(760px,96vw); \r\n    background:#fff; \r\n    border:1px solid var(--line); \r\n    border-radius:16px; \r\n    box-shadow:var(--shadow-md); \r\n    overflow:hidden\r\n  }\r\n  .dh{\r\n    padding:16px 18px; \r\n    border-bottom:1px solid var(--line); \r\n    background:linear-gradient(180deg,#fff,#fafbff)\r\n  }\r\n  .dc{\r\n    padding:16px 18px\r\n  }\r\n  .df{\r\n    padding:14px 18px; \r\n    border-top:1px solid var(--line); \r\n    display:flex; \r\n    gap:10px; \r\n    justify-content:flex-end\r\n  }\r\n\r\n  .token{\r\n    font-family:ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; \r\n    background:#f7f8fc; \r\n    border:1px solid var(--line); \r\n    padding:8px 10px; \r\n    border-radius:8px\r\n  }\r\n\r\n  .toast{\r\n    position:fixed; \r\n    right:20px; \r\n    bottom:20px; \r\n    background:#243b7b; \r\n    border:1px solid #314b95; \r\n    color:#e8efff; \r\n    padding:12px 14px; \r\n    border-radius:12px; \r\n    box-shadow:var(--shadow-md); \r\n    opacity:0; \r\n    transform:translateY(8px); \r\n    transition:.25s\r\n  }\r\n  .toast.show{\r\n    opacity:1; \r\n    transform:translateY(0)\r\n    }\r\n<\/style>\r\n<\/head>\r\n<body>\r\n  <header>\r\n    <div class=\"h1\">Automation & Workflows<\/div>\r\n  <\/header>\r\n\r\n  <main class=\"container\">\r\n    <!-- TRIGGERS -->\r\n    <section class=\"card\" aria-labelledby=\"trig-title\">\r\n      <div class=\"card-h\">\r\n        <div id=\"trig-title\" class=\"card-t\">Ticket Triggers<\/div>\r\n        <div class=\"card-d\">When conditions match, run actions automatically<\/div>\r\n      <\/div>\r\n      <div class=\"card-c\">\r\n        <div class=\"row\" style=\"margin-bottom:10px\">\r\n          <button class=\"btn primary\" id=\"newTriggerBtn\">New Trigger<\/button>\r\n          <button class=\"btn\" id=\"testTriggerBtn\">Open Test Runner<\/button>\r\n          <div class=\"right row\">\r\n            <input id=\"searchTriggers\" type=\"search\" placeholder=\"Search triggers\u2026\" style=\"min-width:240px\"\/>\r\n          <\/div>\r\n        <\/div>\r\n\r\n        <table aria-label=\"Triggers\">\r\n          <thead>\r\n            <tr>\r\n              <th style=\"width:40px\">#<\/th>\r\n              <th>Name<\/th>\r\n              <th>Conditions<\/th>\r\n              <th>Actions<\/th>\r\n              <th>Status<\/th>\r\n              <th style=\"width:210px\"><\/th>\r\n            <\/tr>\r\n          <\/thead>\r\n          <tbody id=\"triggersTbody\"><\/tbody>\r\n        <\/table>\r\n        <div class=\"hint\">Order matters\u2014rules run from top to bottom. Use \u25b2\/\u25bc to reorder.<\/div>\r\n      <\/div>\r\n    <\/section>\r\n\r\n    <!-- MACROS -->\r\n    <section class=\"card\" aria-labelledby=\"macro-title\">\r\n      <div class=\"card-h\">\r\n        <div id=\"macro-title\" class=\"card-t\">Custom Macros<\/div>\r\n        <div class=\"card-d\">Predefined response templates for faster replies<\/div>\r\n      <\/div>\r\n      <div class=\"card-c\">\r\n        <div class=\"row\" style=\"margin-bottom:10px\">\r\n          <button class=\"btn primary\" id=\"newMacroBtn\">New Macro<\/button>\r\n          <div class=\"right row\">\r\n            <input id=\"searchMacros\" type=\"search\" placeholder=\"Search macros\u2026\" style=\"min-width:240px\"\/>\r\n          <\/div>\r\n        <\/div>\r\n        <table aria-label=\"Macros\">\r\n          <thead>\r\n            <tr><th>Title<\/th><th>Shortcut<\/th><th>Preview<\/th><th style=\"width:210px\"><\/th><\/tr>\r\n          <\/thead>\r\n          <tbody id=\"macrosTbody\"><\/tbody>\r\n        <\/table>\r\n        <div class=\"hint\">Variables supported: <code>{{ticket.id}}<\/code>, <code>{{customer.name}}<\/code>, <code>{{agent.name}}<\/code>, <code>{{company.name}}<\/code>.<\/div>\r\n      <\/div>\r\n    <\/section>\r\n\r\n    <!-- SLA -->\r\n    <section class=\"card\" aria-labelledby=\"sla-title\">\r\n      <div class=\"card-h\">\r\n        <div id=\"sla-title\" class=\"card-t\">SLA & Escalation Rules<\/div>\r\n        <div class=\"card-d\">Response & resolution targets, plus automatic escalations<\/div>\r\n      <\/div>\r\n      <div class=\"card-c\">\r\n        <div class=\"grid-4\">\r\n          <div>\r\n            <label>First Response (min)<\/label>\r\n            <input id=\"slaFirst\" type=\"number\" min=\"1\" value=\"30\"\/>\r\n          <\/div>\r\n          <div>\r\n            <label>Next Response (min)<\/label>\r\n            <input id=\"slaNext\" type=\"number\" min=\"1\" value=\"60\"\/>\r\n          <\/div>\r\n          <div>\r\n            <label>Resolution (hours)<\/label>\r\n            <input id=\"slaResolution\" type=\"number\" min=\"1\" value=\"24\"\/>\r\n          <\/div>\r\n          <div>\r\n            <label>Business Hours Only<\/label>\r\n            <div class=\"row\"><label class=\"chip\"><input id=\"slaBiz\" type=\"checkbox\" checked\/> 9\u20136, Mon\u2013Fri<\/label><\/div>\r\n          <\/div>\r\n        <\/div>\r\n\r\n        <div class=\"sep\"><\/div>\r\n\r\n        <div class=\"grid-3\">\r\n          <div>\r\n            <label>Escalate After (min)<\/label>\r\n            <input id=\"escAfter\" type=\"number\" min=\"5\" value=\"30\"\/>\r\n          <\/div>\r\n          <div>\r\n            <label>Escalate To<\/label>\r\n            <select id=\"escTarget\">\r\n              <option value=\"Supervisor\">Supervisor<\/option>\r\n              <option value=\"Admin\">Admin<\/option>\r\n              <option value=\"On-call\">On-call Rotation<\/option>\r\n              <option value=\"Email\">Email: support-leads@company.com<\/option>\r\n            <\/select>\r\n          <\/div>\r\n          <div>\r\n            <label>Notify Channels<\/label>\r\n            <div class=\"row\" id=\"escChannels\">\r\n              <label class=\"chip\"><input type=\"checkbox\" value=\"email\" checked\/> Email<\/label>\r\n              <label class=\"chip\"><input type=\"checkbox\" value=\"inapp\" checked\/> In-app<\/label>\r\n              <label class=\"chip\"><input type=\"checkbox\" value=\"sms\"\/> SMS<\/label>\r\n              <label class=\"chip\"><input type=\"checkbox\" value=\"slack\"\/> Slack<\/label>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n\r\n        <div class=\"row\" style=\"margin-top:10px\">\r\n          <button class=\"btn primary\" id=\"saveSlaBtn\">Save SLA Rules<\/button>\r\n          <button class=\"btn\" id=\"restoreSlaBtn\">Restore Defaults<\/button>\r\n          <div class=\"right badge\">Breach alerts will be sent via selected channels.<\/div>\r\n        <\/div>\r\n      <\/div>\r\n    <\/section>\r\n\r\n    <!-- CUSTOM FIELDS -->\r\n    <section class=\"card\" aria-labelledby=\"fields-title\">\r\n      <div class=\"card-h\">\r\n        <div id=\"fields-title\" class=\"card-t\">Custom Fields<\/div>\r\n        <div class=\"card-d\">Create and manage ticket field types<\/div>\r\n      <\/div>\r\n      <div class=\"card-c\">\r\n        <div class=\"row\" style=\"margin-bottom:10px\">\r\n          <button class=\"btn primary\" id=\"newFieldBtn\">New Field<\/button>\r\n          <div class=\"right row\">\r\n            <button class=\"btn small\" id=\"exportSchemaBtn\">Export Schema<\/button>\r\n            <button class=\"btn small\" id=\"importSchemaBtn\">Import Schema<\/button>\r\n            <input id=\"schemaFile\" type=\"file\" accept=\"application\/json\" style=\"display:none\"\/>\r\n          <\/div>\r\n        <\/div>\r\n\r\n        <table aria-label=\"Custom Fields\">\r\n          <thead>\r\n            <tr>\r\n              <th style=\"width:40px\">#<\/th>\r\n              <th>Name<\/th>\r\n              <th>Key<\/th>\r\n              <th>Type<\/th>\r\n              <th>Required<\/th>\r\n              <th>Visibility<\/th>\r\n              <th style=\"width:210px\"><\/th>\r\n            <\/tr>\r\n          <\/thead>\r\n          <tbody id=\"fieldsTbody\"><\/tbody>\r\n        <\/table>\r\n        <div class=\"hint\">Drag order with \u25b2\/\u25bc. Keys must be unique (used in APIs).<\/div>\r\n      <\/div>\r\n    <\/section>\r\n  <\/main>\r\n\r\n  <!-- MODALS -->\r\n\r\n  <!-- Trigger modal -->\r\n  <div class=\"modal\" id=\"triggerModal\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"triggerTitle\">\r\n    <div class=\"dialog\">\r\n      <div class=\"dh\">\r\n        <div id=\"triggerTitle\" class=\"card-t\">New Trigger<\/div>\r\n      <\/div>\r\n      <div class=\"dc\">\r\n        <div class=\"grid-2\">\r\n          <div>\r\n            <label for=\"trigName\">Name<\/label>\r\n            <input id=\"trigName\" type=\"text\" placeholder=\"Auto-assign Priority P1 to L1\"\/>\r\n          <\/div>\r\n          <div>\r\n            <label>Status<\/label>\r\n            <div class=\"row\"><label class=\"chip\"><input id=\"trigEnabled\" type=\"checkbox\" checked\/> Enabled<\/label><\/div>\r\n          <\/div>\r\n        <\/div>\r\n\r\n        <div class=\"sep\"><\/div>\r\n\r\n        <div class=\"grid-2\">\r\n          <div>\r\n            <label>Conditions<\/label>\r\n            <div class=\"row\">\r\n              <select id=\"condField\" style=\"min-width:180px\">\r\n                <option value=\"category\">Category<\/option>\r\n                <option value=\"priority\">Priority<\/option>\r\n                <option value=\"channel\">Channel<\/option>\r\n                <option value=\"requester\">Requester Domain<\/option>\r\n                <option value=\"tags\">Tags (contains)<\/option>\r\n              <\/select>\r\n              <select id=\"condOp\">\r\n                <option value=\"is\">is<\/option>\r\n                <option value=\"is_not\">is not<\/option>\r\n                <option value=\"contains\">contains<\/option>\r\n              <\/select>\r\n              <input id=\"condValue\" type=\"text\" placeholder=\"e.g., Billing \/ P1 \/ email \/ @vip.com \/ urgent\"\/>\r\n              <button class=\"btn small\" id=\"addCondBtn\">Add<\/button>\r\n            <\/div>\r\n            <div id=\"condList\" class=\"hint\" style=\"margin-top:8px\"><\/div>\r\n          <\/div>\r\n\r\n          <div>\r\n            <label>Actions<\/label>\r\n            <div class=\"row\">\r\n              <select id=\"actType\" style=\"min-width:180px\">\r\n                <option value=\"assign_team\">Assign team<\/option>\r\n                <option value=\"assign_agent\">Assign agent<\/option>\r\n                <option value=\"set_priority\">Set priority<\/option>\r\n                <option value=\"add_tag\">Add tag<\/option>\r\n                <option value=\"auto_close\">Auto-close after days<\/option>\r\n              <\/select>\r\n              <input id=\"actValue\" type=\"text\" placeholder=\"e.g., L1 Support \/ jane@company.com \/ P2 \/ billing \/ 7\"\/>\r\n              <button class=\"btn small\" id=\"addActBtn\">Add<\/button>\r\n            <\/div>\r\n            <div id=\"actList\" class=\"hint\" style=\"margin-top:8px\"><\/div>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"df\">\r\n        <button class=\"btn\" id=\"cancelTrigBtn\">Cancel<\/button>\r\n        <button class=\"btn primary\" id=\"saveTrigBtn\">Save Trigger<\/button>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- Trigger test runner -->\r\n  <div class=\"modal\" id=\"testModal\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"testTitle\">\r\n    <div class=\"dialog\">\r\n      <div class=\"dh\"><div id=\"testTitle\" class=\"card-t\">Trigger Test Runner<\/div><\/div>\r\n      <div class=\"dc\">\r\n        <div class=\"grid-4\">\r\n          <div>\r\n            <label>Category<\/label>\r\n            <input id=\"tCat\" type=\"text\" placeholder=\"Billing\"\/>\r\n          <\/div>\r\n          <div>\r\n            <label>Priority<\/label>\r\n            <select id=\"tPri\"><option>P1<\/option><option>P2<\/option><option>P3<\/option><option>P4<\/option><\/select>\r\n          <\/div>\r\n          <div>\r\n            <label>Channel<\/label>\r\n            <select id=\"tCh\"><option>email<\/option><option>web<\/option><option>chat<\/option><option>phone<\/option><\/select>\r\n          <\/div>\r\n          <div>\r\n            <label>Requester Email<\/label>\r\n            <input id=\"tReq\" type=\"text\" placeholder=\"vip@company.com\"\/>\r\n          <\/div>\r\n        <\/div>\r\n        <div class=\"grid-2\" style=\"margin-top:10px\">\r\n          <div>\r\n            <label>Tags (comma-separated)<\/label>\r\n            <input id=\"tTags\" type=\"text\" placeholder=\"urgent, refund\"\/>\r\n          <\/div>\r\n          <div>\r\n            <label>Result<\/label>\r\n            <textarea id=\"tResult\" readonly placeholder=\"Triggered rules & actions will appear here\u2026\"><\/textarea>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"df\">\r\n        <button class=\"btn\" id=\"closeTestBtn\">Close<\/button>\r\n        <button class=\"btn primary\" id=\"runTestBtn\">Run<\/button>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- Macro modal -->\r\n  <div class=\"modal\" id=\"macroModal\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"macroTitle\">\r\n    <div class=\"dialog\">\r\n      <div class=\"dh\"><div id=\"macroTitle\" class=\"card-t\">New Macro<\/div><\/div>\r\n      <div class=\"dc\">\r\n        <div class=\"grid-3\">\r\n          <div>\r\n            <label>Title<\/label>\r\n            <input id=\"mTitle\" type=\"text\" placeholder=\"Acknowledge receipt\"\/>\r\n          <\/div>\r\n          <div>\r\n            <label>Shortcut<\/label>\r\n            <input id=\"mShortcut\" type=\"text\" placeholder=\"ctrl+shift+A\"\/>\r\n            <div class=\"hint\">Display only; not captured by browser in this demo.<\/div>\r\n          <\/div>\r\n          <div>\r\n            <label>Insert Variables<\/label>\r\n            <div class=\"row\" id=\"varsRow\">\r\n              <button class=\"btn small\" data-var=\"{{ticket.id}}\">ticket.id<\/button>\r\n              <button class=\"btn small\" data-var=\"{{customer.name}}\">customer.name<\/button>\r\n              <button class=\"btn small\" data-var=\"{{agent.name}}\">agent.name<\/button>\r\n              <button class=\"btn small\" data-var=\"{{company.name}}\">company.name<\/button>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n        <div class=\"grid-2\" style=\"margin-top:10px\">\r\n          <div>\r\n            <label>Body (Markdown)<\/label>\r\n            <textarea id=\"mBody\" placeholder=\"Hi {{customer.name}},&#10;&#10;We\u2019ve received your ticket (ID: {{ticket.id}}) and will get back shortly.\"><\/textarea>\r\n          <\/div>\r\n          <div>\r\n            <label>Preview<\/label>\r\n            <div id=\"mPreview\" class=\"token\" style=\"min-height:120px; white-space:pre-wrap\"><\/div>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"df\">\r\n        <button class=\"btn\" id=\"cancelMacroBtn\">Cancel<\/button>\r\n        <button class=\"btn primary\" id=\"saveMacroBtn\">Save Macro<\/button>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- Field modal -->\r\n  <div class=\"modal\" id=\"fieldModal\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"fieldTitle\">\r\n    <div class=\"dialog\">\r\n      <div class=\"dh\"><div id=\"fieldTitle\" class=\"card-t\">New Field<\/div><\/div>\r\n      <div class=\"dc\">\r\n        <div class=\"grid-3\">\r\n          <div>\r\n            <label>Name<\/label>\r\n            <input id=\"fName\" type=\"text\" placeholder=\"Department\"\/>\r\n          <\/div>\r\n          <div>\r\n            <label>Key<\/label>\r\n            <input id=\"fKey\" type=\"text\" placeholder=\"dept\"\/>\r\n            <div class=\"hint\">Used in APIs; must be unique.<\/div>\r\n          <\/div>\r\n          <div>\r\n            <label>Type<\/label>\r\n            <select id=\"fType\">\r\n              <option value=\"text\">Text<\/option>\r\n              <option value=\"number\">Number<\/option>\r\n              <option value=\"dropdown\">Dropdown<\/option>\r\n              <option value=\"checkbox\">Checkbox<\/option>\r\n              <option value=\"date\">Date<\/option>\r\n            <\/select>\r\n          <\/div>\r\n        <\/div>\r\n        <div class=\"grid-3\" style=\"margin-top:10px\">\r\n          <div>\r\n            <label>Required<\/label>\r\n            <div class=\"row\"><label class=\"chip\"><input id=\"fReq\" type=\"checkbox\"\/> Required<\/label><\/div>\r\n          <\/div>\r\n          <div>\r\n            <label>Visibility<\/label>\r\n            <select id=\"fVis\">\r\n              <option value=\"agent_customer\">Agent & Customer<\/option>\r\n              <option value=\"agent_only\">Agent Only<\/option>\r\n              <option value=\"hidden\">Hidden<\/option>\r\n            <\/select>\r\n          <\/div>\r\n          <div id=\"optWrap\" style=\"display:none\">\r\n            <label>Dropdown Options<\/label>\r\n            <input id=\"fOpts\" type=\"text\" placeholder=\"Comma-separated e.g., Billing, Sales, Tech\"\/>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"df\">\r\n        <button class=\"btn\" id=\"cancelFieldBtn\">Cancel<\/button>\r\n        <button class=\"btn primary\" id=\"saveFieldBtn\">Save Field<\/button>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <div id=\"toast\" class=\"toast\" role=\"status\" aria-live=\"polite\"><\/div>\r\n\r\n<script>\r\n\/* ===========================\r\n   State & Utilities\r\n=========================== *\/\r\nconst $=(s,ctx=document)=>ctx.querySelector(s);\r\nconst $$=(s,ctx=document)=>Array.from(ctx.querySelectorAll(s));\r\nconst STORE=\"automation.workflows.v1\";\r\n\r\nconst defaults = {\r\n  triggers: [\r\n    {\r\n      id:id(), name:\"Auto-assign Billing tickets to L1\", enabled:true, order:1,\r\n      conditions:[{f:\"category\",op:\"is\",v:\"Billing\"}],\r\n      actions:[{t:\"assign_team\",v:\"L1 Support\"},{t:\"add_tag\",v:\"billing\"}]\r\n    },\r\n    {\r\n      id:id(), name:\"Escalate urgent (P1) to Supervisor\", enabled:true, order:2,\r\n      conditions:[{f:\"priority\",op:\"is\",v:\"P1\"}],\r\n      actions:[{t:\"assign_team\",v:\"Supervisor\"},{t:\"set_priority\",v:\"P1\"}]\r\n    },\r\n    {\r\n      id:id(), name:\"Auto-close resolved after 7 days\", enabled:true, order:3,\r\n      conditions:[{f:\"tags\",op:\"contains\",v:\"resolved\"}],\r\n      actions:[{t:\"auto_close\",v:\"7\"}]\r\n    }\r\n  ],\r\n  macros: [\r\n    { id:id(), title:\"Acknowledge Receipt\", shortcut:\"ctrl+shift+A\",\r\n      body:\"Hi {{customer.name}},\\n\\nWe\u2019ve received your ticket (ID: {{ticket.id}}). Our {{company.name}} support team will get back shortly.\\n\\nThanks,\\n{{agent.name}}\"\r\n    },\r\n    { id:id(), title:\"Request More Info\", shortcut:\"ctrl+shift+R\",\r\n      body:\"Hi {{customer.name}},\\n\\nCould you please share additional details or screenshots so we can investigate?\\n\\nBest,\\n{{agent.name}}\"\r\n    }\r\n  ],\r\n  sla: {\r\n    firstResp:30, nextResp:60, resolutionHrs:24, bizHours:true,\r\n    escalateAfter:30, escalateTo:\"Supervisor\", channels:[\"email\",\"inapp\"]\r\n  },\r\n  fields: [\r\n    { id:id(), order:1, name:\"Department\", key:\"dept\", type:\"dropdown\", required:true, vis:\"agent_customer\", opts:[\"Billing\",\"Sales\",\"Tech\"] },\r\n    { id:id(), order:2, name:\"Customer Priority\", key:\"cust_priority\", type:\"dropdown\", required:false, vis:\"agent_only\", opts:[\"Normal\",\"VIP\"] },\r\n    { id:id(), order:3, name:\"Onsite Required\", key:\"onsite\", type:\"checkbox\", required:false, vis:\"agent_only\" }\r\n  ]\r\n};\r\n\r\nlet state = load();\r\nlet editing = { trigger:null, macro:null, field:null };\r\n\r\nfunction id(){ return Math.random().toString(36).slice(2,10); }\r\nfunction load(){ const s=localStorage.getItem(STORE); return s? JSON.parse(s) : structuredClone(defaults); }\r\nfunction save(){ localStorage.setItem(STORE, JSON.stringify(state)); toast(\"Saved \u2713\"); }\r\nfunction toast(msg){ const t=$(\"#toast\"); t.textContent=msg; t.classList.add(\"show\"); setTimeout(()=>t.classList.remove(\"show\"),1500); }\r\nfunction summarizeConds(conds){\r\n  if(!conds?.length) return \"\u2014\";\r\n  return conds.map(c=>`${c.f} ${c.op.replace(\"_\",\" \")} \"${c.v}\"`).join(\"; \");\r\n}\r\nfunction summarizeActs(acts){\r\n  if(!acts?.length) return \"\u2014\";\r\n  const map={assign_team:\"Assign team\",assign_agent:\"Assign agent\",set_priority:\"Set priority\",add_tag:\"Add tag\",auto_close:\"Auto-close\"};\r\n  return acts.map(a=>`${map[a.t]||a.t}: ${a.v}`).join(\"; \");\r\n}\r\n\r\n\/* ===========================\r\n   TRIGGERS\r\n=========================== *\/\r\nfunction renderTriggers(){\r\n  const tb=$(\"#triggersTbody\"); tb.innerHTML=\"\";\r\n  const q=$(\"#searchTriggers\").value.trim().toLowerCase();\r\n  const sorted = [...state.triggers].sort((a,b)=>a.order-b.order);\r\n  sorted\r\n    .filter(t=>!q || t.name.toLowerCase().includes(q))\r\n    .forEach((t,i)=>{\r\n      const tr=document.createElement(\"tr\");\r\n      tr.innerHTML=`\r\n        <td>${t.order}<\/td>\r\n        <td>${t.name}<\/td>\r\n        <td>${summarizeConds(t.conditions)}<\/td>\r\n        <td>${summarizeActs(t.actions)}<\/td>\r\n        <td>${t.enabled?'<span class=\"badge good\">Enabled<\/span>':'<span class=\"badge warn\">Disabled<\/span>'}<\/td>\r\n        <td style=\"text-align:right\">\r\n          <button class=\"btn small\" data-up=\"${t.id}\">\u25b2<\/button>\r\n          <button class=\"btn small\" data-down=\"${t.id}\">\u25bc<\/button>\r\n          <button class=\"btn small\" data-edit=\"${t.id}\">Edit<\/button>\r\n          <button class=\"btn small ${t.enabled?'danger':''}\" data-toggle=\"${t.id}\">${t.enabled?'Disable':'Enable'}<\/button>\r\n          <button class=\"btn small ghost\" data-del=\"${t.id}\">Remove<\/button>\r\n        <\/td>`;\r\n      tb.appendChild(tr);\r\n    });\r\n\r\n  $$('[data-edit]').forEach(b=> b.onclick=()=> openTriggerModal(b.getAttribute('data-edit')));\r\n  $$('[data-del]').forEach(b=> b.onclick=()=> delTrigger(b.getAttribute('data-del')));\r\n  $$('[data-toggle]').forEach(b=> b.onclick=()=> toggleTrigger(b.getAttribute('data-toggle')));\r\n  $$('[data-up]').forEach(b=> b.onclick=()=> moveTrigger(b.getAttribute('data-up'), -1));\r\n  $$('[data-down]').forEach(b=> b.onclick=()=> moveTrigger(b.getAttribute('data-down'), +1));\r\n}\r\nfunction openTriggerModal(id=null){\r\n  editing.trigger = id;\r\n  $(\"#triggerTitle\").textContent = id ? \"Edit Trigger\" : \"New Trigger\";\r\n  $(\"#trigName\").value = \"\"; $(\"#trigEnabled\").checked = true;\r\n  $(\"#condList\").innerHTML=\"\"; $(\"#actList\").innerHTML=\"\";\r\n\r\n  if(id){\r\n    const t = state.triggers.find(x=>x.id===id);\r\n    $(\"#trigName\").value = t.name; $(\"#trigEnabled\").checked = !!t.enabled;\r\n    t.conditions.forEach(addCondChip);\r\n    t.actions.forEach(addActChip);\r\n  }\r\n  $(\"#triggerModal\").classList.add(\"open\");\r\n}\r\nfunction closeTriggerModal(){ $(\"#triggerModal\").classList.remove(\"open\"); }\r\nfunction addCondChip(c){ const wrap=$(\"#condList\"); const el=document.createElement(\"span\"); el.className=\"chip\"; el.textContent=`${c.f} ${c.op} ${c.v}`; el.dataset.payload=JSON.stringify(c); const x=document.createElement(\"button\"); x.className=\"btn small ghost\"; x.textContent=\"\u00d7\"; x.onclick=()=>el.remove(); el.appendChild(x); wrap.appendChild(el); }\r\nfunction addActChip(a){ const wrap=$(\"#actList\"); const el=document.createElement(\"span\"); el.className=\"chip\"; el.textContent=`${a.t} \u2192 ${a.v}`; el.dataset.payload=JSON.stringify(a); const x=document.createElement(\"button\"); x.className=\"btn small ghost\"; x.textContent=\"\u00d7\"; x.onclick=()=>el.remove(); el.appendChild(x); wrap.appendChild(el); }\r\n$(\"#addCondBtn\").onclick=()=>{\r\n  const f=$(\"#condField\").value, op=$(\"#condOp\").value, v=$(\"#condValue\").value.trim();\r\n  if(!v) return; addCondChip({f,op,v}); $(\"#condValue\").value=\"\";\r\n};\r\n$(\"#addActBtn\").onclick=()=>{\r\n  const t=$(\"#actType\").value, v=$(\"#actValue\").value.trim();\r\n  if(!v) return; addActChip({t,v}); $(\"#actValue\").value=\"\";\r\n};\r\n$(\"#saveTrigBtn\").onclick=()=>{\r\n  const name=$(\"#trigName\").value.trim(); if(!name){ toast(\"Name required\"); return; }\r\n  const enabled=$(\"#trigEnabled\").checked;\r\n  const conds=[...$(\"#condList\").querySelectorAll(\".chip\")].map(x=>JSON.parse(x.dataset.payload||\"{}\"));\r\n  const acts=[...$(\"#actList\").querySelectorAll(\".chip\")].map(x=>JSON.parse(x.dataset.payload||\"{}\"));\r\n  if(conds.length===0 || acts.length===0){ toast(\"Add at least one condition and one action\"); return; }\r\n\r\n  if(editing.trigger){\r\n    const t=state.triggers.find(x=>x.id===editing.trigger);\r\n    Object.assign(t,{name,enabled,conditions:conds,actions:acts});\r\n  }else{\r\n    const maxOrder = Math.max(0,...state.triggers.map(x=>x.order));\r\n    state.triggers.push({id:id(), name, enabled, conditions:conds, actions:acts, order:maxOrder+1});\r\n  }\r\n  save(); renderTriggers(); closeTriggerModal();\r\n};\r\n$(\"#cancelTrigBtn\").onclick=()=> closeTriggerModal();\r\nfunction toggleTrigger(id){ const t=state.triggers.find(x=>x.id===id); t.enabled=!t.enabled; save(); renderTriggers(); }\r\nfunction delTrigger(id){ const t=state.triggers.find(x=>x.id===id); if(!confirm(`Delete \"${t.name}\"?`)) return; state.triggers=state.triggers.filter(x=>x.id!==id); reindex(); save(); renderTriggers(); }\r\nfunction moveTrigger(id,dir){ const arr=[...state.triggers].sort((a,b)=>a.order-b.order); const idx=arr.findIndex(x=>x.id===id); const ni=idx+dir; if(ni<0||ni>=arr.length) return; const tmp=arr[idx].order; arr[idx].order=arr[ni].order; arr[ni].order=tmp; \/\/ swap order\r\n  \/\/ write back\r\n  arr.forEach(a=>{ const r=state.triggers.find(x=>x.id===a.id); r.order=a.order; }); save(); renderTriggers();\r\n}\r\nfunction reindex(){ state.triggers.sort((a,b)=>a.order-b.order).forEach((t,i)=>t.order=i+1); }\r\n\r\n\/* Test runner *\/\r\n$(\"#testTriggerBtn\").onclick=()=> $(\"#testModal\").classList.add(\"open\");\r\n$(\"#closeTestBtn\").onclick=()=> $(\"#testModal\").classList.remove(\"open\");\r\n$(\"#runTestBtn\").onclick=()=>{\r\n  const input = {\r\n    category: $(\"#tCat\").value.trim().toLowerCase(),\r\n    priority: $(\"#tPri\").value,\r\n    channel: $(\"#tCh\").value,\r\n    requester: $(\"#tReq\").value.trim().toLowerCase(),\r\n    tags: ($(\"#tTags\").value||\"\").split(\",\").map(x=>x.trim().toLowerCase()).filter(Boolean)\r\n  };\r\n  const hits=[];\r\n  [...state.triggers].sort((a,b)=>a.order-b.order).forEach(t=>{\r\n    if(!t.enabled) return;\r\n    const passed = t.conditions.every(c=> evalCond(input,c));\r\n    if(passed) hits.push({name:t.name,actions:t.actions});\r\n  });\r\n  const lines = hits.length? hits.map(h=>`\u2022 ${h.name}\\n  \u2192 ${summarizeActs(h.actions)}`).join(\"\\n\\n\") : \"No triggers matched.\";\r\n  $(\"#tResult\").value = lines;\r\n};\r\nfunction evalCond(input,c){\r\n  const v = (c.f===\"tags\")? input.tags : (c.f===\"requester\")? (input.requester.split(\"@\")[1]||\"\") : input[c.f];\r\n  const val = (typeof v===\"string\")? v.toLowerCase() : v;\r\n  const rhs = String(c.v||\"\").toLowerCase();\r\n  switch(c.op){\r\n    case \"is\": return val===rhs;\r\n    case \"is_not\": return val!==rhs;\r\n    case \"contains\":\r\n      if(Array.isArray(val)) return val.includes(rhs);\r\n      return String(val||\"\").includes(rhs);\r\n    default: return false;\r\n  }\r\n}\r\n\r\n\/* ===========================\r\n   MACROS\r\n=========================== *\/\r\nfunction renderMacros(){\r\n  const tb=$(\"#macrosTbody\"); tb.innerHTML=\"\";\r\n  const q=$(\"#searchMacros\").value.trim().toLowerCase();\r\n  state.macros\r\n    .filter(m=>!q || m.title.toLowerCase().includes(q) || (m.shortcut||\"\").toLowerCase().includes(q))\r\n    .forEach(m=>{\r\n      const prev = (m.body||\"\").slice(0,80).replace(\/\\n\/g,\" \");\r\n      const tr=document.createElement(\"tr\");\r\n      tr.innerHTML=`\r\n        <td>${m.title}<\/td>\r\n        <td>${m.shortcut||\"\u2014\"}<\/td>\r\n        <td title=\"${m.body.replace(\/\"\/g,'&quot;')}\">${prev}${m.body.length>80?\"\u2026\":\"\"}<\/td>\r\n        <td style=\"text-align:right\">\r\n          <button class=\"btn small\" data-preview=\"${m.id}\">Preview<\/button>\r\n          <button class=\"btn small\" data-editm=\"${m.id}\">Edit<\/button>\r\n          <button class=\"btn small danger\" data-delm=\"${m.id}\">Remove<\/button>\r\n        <\/td>`;\r\n      tb.appendChild(tr);\r\n    });\r\n  $$('[data-editm]').forEach(b=> b.onclick=()=> openMacroModal(b.getAttribute('data-editm')));\r\n  $$('[data-delm]').forEach(b=> b.onclick=()=> delMacro(b.getAttribute('data-delm')));\r\n  $$('[data-preview]').forEach(b=> b.onclick=()=> previewMacro(b.getAttribute('data-preview')));\r\n}\r\nfunction openMacroModal(id=null){\r\n  editing.macro=id;\r\n  $(\"#macroTitle\").textContent = id ? \"Edit Macro\" : \"New Macro\";\r\n  $(\"#mTitle\").value=\"\"; $(\"#mShortcut\").value=\"\"; $(\"#mBody\").value=\"\"; renderMacroPreview();\r\n  if(id){\r\n    const m=state.macros.find(x=>x.id===id);\r\n    $(\"#mTitle\").value=m.title; $(\"#mShortcut\").value=m.shortcut||\"\"; $(\"#mBody\").value=m.body||\"\"; renderMacroPreview();\r\n  }\r\n  $(\"#macroModal\").classList.add(\"open\");\r\n}\r\nfunction closeMacroModal(){ $(\"#macroModal\").classList.remove(\"open\"); }\r\nfunction delMacro(id){ const m=state.macros.find(x=>x.id===id); if(!confirm(`Delete macro \"${m.title}\"?`)) return; state.macros=state.macros.filter(x=>x.id!==id); save(); renderMacros(); }\r\nfunction renderMacroPreview(){\r\n  const tpl=$(\"#mBody\").value;\r\n  const ctx={ticket:{id:\"12345\"}, customer:{name:\"Alex\"}, agent:{name:\"You\"}, company:{name:\"Acme\"}};\r\n  const out = tpl.replace(\/\\{\\{([\\w\\.]+)\\}\\}\/g, (_,k)=> k.split(\".\").reduce((o,p)=>o?.[p],ctx) ?? \"\");\r\n  $(\"#mPreview\").textContent = out;\r\n}\r\n$(\"#mBody\").addEventListener(\"input\", renderMacroPreview);\r\n$(\"#varsRow\").addEventListener(\"click\", (e)=>{\r\n  if(e.target.dataset.var){\r\n    const t=$(\"#mBody\"); const v=e.target.dataset.var; const s=t.selectionStart||t.value.length;\r\n    t.value = t.value.slice(0,s)+v+t.value.slice(s); renderMacroPreview(); t.focus();\r\n  }\r\n});\r\n$(\"#saveMacroBtn\").onclick=()=>{\r\n  const title=$(\"#mTitle\").value.trim(); if(!title){ toast(\"Title required\"); return; }\r\n  const shortcut=$(\"#mShortcut\").value.trim(); const body=$(\"#mBody\").value;\r\n  if(editing.macro){\r\n    const m=state.macros.find(x=>x.id===editing.macro);\r\n    Object.assign(m,{title,shortcut,body});\r\n  }else{\r\n    state.macros.unshift({id:id(), title, shortcut, body});\r\n  }\r\n  save(); renderMacros(); closeMacroModal();\r\n};\r\n$(\"#cancelMacroBtn\").onclick=()=> closeMacroModal();\r\nfunction previewMacro(id){\r\n  const m=state.macros.find(x=>x.id===id);\r\n  const ctx={ticket:{id:\"56789\"}, customer:{name:\"Taylor\"}, agent:{name:\"Ava\"}, company:{name:\"Acme\"}};\r\n  const out = (m.body||\"\").replace(\/\\{\\{([\\w\\.]+)\\}\\}\/g, (_,k)=> k.split(\".\").reduce((o,p)=>o?.[p],ctx) ?? \"\");\r\n  alert(\"Preview:\\n\\n\"+out);\r\n}\r\n\r\n\/* ===========================\r\n   SLA & ESCALATION\r\n=========================== *\/\r\nfunction renderSLA(){\r\n  $(\"#slaFirst\").value = state.sla.firstResp;\r\n  $(\"#slaNext\").value = state.sla.nextResp;\r\n  $(\"#slaResolution\").value = state.sla.resolutionHrs;\r\n  $(\"#slaBiz\").checked = !!state.sla.bizHours;\r\n  $(\"#escAfter\").value = state.sla.escalateAfter;\r\n  $(\"#escTarget\").value = state.sla.escalateTo;\r\n  $$(\"#escChannels input[type=checkbox]\").forEach(cb=> cb.checked = state.sla.channels.includes(cb.value));\r\n}\r\n$(\"#saveSlaBtn\").onclick=()=>{\r\n  state.sla.firstResp = +$(\"#slaFirst\").value||30;\r\n  state.sla.nextResp = +$(\"#slaNext\").value||60;\r\n  state.sla.resolutionHrs = +$(\"#slaResolution\").value||24;\r\n  state.sla.bizHours = $(\"#slaBiz\").checked;\r\n  state.sla.escalateAfter = +$(\"#escAfter\").value||30;\r\n  state.sla.escalateTo = $(\"#escTarget\").value;\r\n  state.sla.channels = $$(\"#escChannels input:checked\").map(x=>x.value);\r\n  save();\r\n};\r\n$(\"#restoreSlaBtn\").onclick=()=>{ state.sla = structuredClone(defaults.sla); renderSLA(); save(); };\r\n\r\n\/* ===========================\r\n   CUSTOM FIELDS\r\n=========================== *\/\r\nfunction renderFields(){\r\n  const tb=$(\"#fieldsTbody\"); tb.innerHTML=\"\";\r\n  [...state.fields].sort((a,b)=>a.order-b.order).forEach(f=>{\r\n    const tr=document.createElement(\"tr\");\r\n    tr.innerHTML=`\r\n      <td>${f.order}<\/td>\r\n      <td>${f.name}<\/td>\r\n      <td><code>${f.key}<\/code><\/td>\r\n      <td>${f.type}<\/td>\r\n      <td>${f.required?'<span class=\"badge good\">Yes<\/span>':'No'}<\/td>\r\n      <td>${f.vis.replace(\"_\",\" \/ \")}<\/td>\r\n      <td style=\"text-align:right\">\r\n        <button class=\"btn small\" data-upf=\"${f.id}\">\u25b2<\/button>\r\n        <button class=\"btn small\" data-downf=\"${f.id}\">\u25bc<\/button>\r\n        <button class=\"btn small\" data-editf=\"${f.id}\">Edit<\/button>\r\n        <button class=\"btn small danger\" data-delf=\"${f.id}\">Remove<\/button>\r\n      <\/td>`;\r\n    tb.appendChild(tr);\r\n  });\r\n  $$('[data-editf]').forEach(b=> b.onclick=()=> openFieldModal(b.getAttribute('data-editf')));\r\n  $$('[data-delf]').forEach(b=> b.onclick=()=> delField(b.getAttribute('data-delf')));\r\n  $$('[data-upf]').forEach(b=> b.onclick=()=> moveField(b.getAttribute('data-upf'), -1));\r\n  $$('[data-downf]').forEach(b=> b.onclick=()=> moveField(b.getAttribute('data-downf'), +1));\r\n}\r\nfunction openFieldModal(id=null){\r\n  editing.field=id;\r\n  $(\"#fieldTitle\").textContent = id ? \"Edit Field\" : \"New Field\";\r\n  $(\"#fName\").value=\"\"; $(\"#fKey\").value=\"\"; $(\"#fType\").value=\"text\"; $(\"#fReq\").checked=false; $(\"#fVis\").value=\"agent_customer\";\r\n  $(\"#fOpts\").value=\"\"; $(\"#optWrap\").style.display=\"none\";\r\n  if(id){\r\n    const f=state.fields.find(x=>x.id===id);\r\n    $(\"#fName\").value=f.name; $(\"#fKey\").value=f.key; $(\"#fType\").value=f.type; $(\"#fReq\").checked=!!f.required; $(\"#fVis\").value=f.vis;\r\n    $(\"#optWrap\").style.display = f.type===\"dropdown\" ? \"block\":\"none\";\r\n    $(\"#fOpts\").value = (f.opts||[]).join(\", \");\r\n  }\r\n  $(\"#fieldModal\").classList.add(\"open\");\r\n}\r\nfunction closeFieldModal(){ $(\"#fieldModal\").classList.remove(\"open\"); }\r\n$(\"#fType\").addEventListener(\"change\", ()=> $(\"#optWrap\").style.display = $(\"#fType\").value===\"dropdown\" ? \"block\":\"none\");\r\n$(\"#saveFieldBtn\").onclick=()=>{\r\n  const name=$(\"#fName\").value.trim(), key=$(\"#fKey\").value.trim();\r\n  if(!name||!key){ toast(\"Name and Key required\"); return; }\r\n  const type=$(\"#fType\").value, required=$(\"#fReq\").checked, vis=$(\"#fVis\").value;\r\n  const opts = type===\"dropdown\" ? ($(\"#fOpts\").value||\"\").split(\",\").map(x=>x.trim()).filter(Boolean) : undefined;\r\n  \/\/ unique key\r\n  if(!editing.field && state.fields.some(f=>f.key===key)){ toast(\"Key must be unique\"); return; }\r\n\r\n  if(editing.field){\r\n    const f=state.fields.find(x=>x.id===editing.field);\r\n    Object.assign(f,{name,key,type,required,vis});\r\n    if(type===\"dropdown\") f.opts=opts; else delete f.opts;\r\n  }else{\r\n    const maxOrder=Math.max(0,...state.fields.map(x=>x.order));\r\n    state.fields.push({id:id(), order:maxOrder+1, name, key, type, required, vis, ...(type===\"dropdown\"?{opts}:{} )});\r\n  }\r\n  save(); renderFields(); closeFieldModal();\r\n};\r\n$(\"#cancelFieldBtn\").onclick=()=> closeFieldModal();\r\nfunction delField(id){ const f=state.fields.find(x=>x.id===id); if(!confirm(`Delete field \"${f.name}\"?`)) return; state.fields=state.fields.filter(x=>x.id!==id); reorderFields(); save(); renderFields(); }\r\nfunction moveField(id,dir){ const arr=[...state.fields].sort((a,b)=>a.order-b.order); const idx=arr.findIndex(x=>x.id===id); const ni=idx+dir; if(ni<0||ni>=arr.length) return; const tmp=arr[idx].order; arr[idx].order=arr[ni].order; arr[ni].order=tmp; arr.forEach(a=>{ const r=state.fields.find(x=>x.id===a.id); r.order=a.order; }); save(); renderFields(); }\r\nfunction reorderFields(){ state.fields.sort((a,b)=>a.order-b.order).forEach((f,i)=>f.order=i+1); }\r\n\r\n\/* ===========================\r\n   Export \/ Import Schema\r\n=========================== *\/\r\n$(\"#exportSchemaBtn\").onclick=()=>{\r\n  const schema = JSON.stringify(state.fields, null, 2);\r\n  const blob = new Blob([schema], {type:\"application\/json\"});\r\n  const url = URL.createObjectURL(blob);\r\n  const a=document.createElement(\"a\"); a.href=url; a.download=\"ticket_fields.schema.json\"; a.click(); URL.revokeObjectURL(url);\r\n};\r\n$(\"#importSchemaBtn\").onclick=()=> $(\"#schemaFile\").click();\r\n$(\"#schemaFile\").addEventListener(\"change\", (e)=>{\r\n  const file=e.target.files[0]; if(!file) return;\r\n  const fr=new FileReader(); fr.onload=()=>{\r\n    try{\r\n      const arr=JSON.parse(fr.result);\r\n      if(!Array.isArray(arr)) throw new Error(\"Invalid schema\");\r\n      \/\/ rudimentary validation\r\n      arr.forEach(x=>{ if(!x.id) x.id=id(); if(typeof x.order!==\"number\") x.order=1; });\r\n      state.fields = arr; save(); renderFields(); toast(\"Schema imported \u2713\");\r\n    }catch(err){ alert(\"Failed to import: \"+err.message); }\r\n  }; fr.readAsText(file);\r\n});\r\n\r\n\/* ===========================\r\n   INIT\r\n=========================== *\/\r\ndocument.addEventListener(\"DOMContentLoaded\", ()=>{\r\n  renderTriggers(); renderMacros(); renderSLA(); renderFields();\r\n\r\n  $(\"#newTriggerBtn\").onclick=()=> openTriggerModal();\r\n  $(\"#searchTriggers\").addEventListener(\"input\", ()=> renderTriggers());\r\n\r\n  $(\"#newMacroBtn\").onclick=()=> openMacroModal();\r\n  $(\"#searchMacros\").addEventListener(\"input\", ()=> renderMacros());\r\n\r\n  $(\"#newFieldBtn\").onclick=()=> openFieldModal();\r\n\r\n  \/\/ Modal background & Esc close\r\n  [$(\"#triggerModal\"), $(\"#macroModal\"), $(\"#fieldModal\"), $(\"#testModal\")].forEach(mod=>{\r\n    mod.addEventListener(\"click\",(e)=>{ if(e.target===mod) mod.classList.remove(\"open\"); });\r\n    document.addEventListener(\"keydown\",(e)=>{ if(e.key===\"Escape\") mod.classList.remove(\"open\"); });\r\n  });\r\n});\r\n\r\n\/* ===========================\r\n   Tiny helpers\r\n=========================== *\/\r\nfunction idShort(){ return Math.random().toString(36).slice(2,6); }\r\n<\/script>\r\n<\/body>\r\n<\/html>\r\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-1e5ec52 e-flex e-con-boxed e-con e-parent\" data-id=\"1e5ec52\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\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>Account Settings Admin Profile Security &amp; Login Roles &amp; Permissions Notification Automation &amp; Workflows Account Settings \u2013 Profile &#038; Organization Account Settings &#8211; Admin Profile Profile Organization Support Branding Admin Profile Personal identity and your profile photo Name * Username * Designation Email * Contact Number Profile Photo Click or drop an image here PNG\/JPG [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-193","page","type-page","status-publish","hentry"],"acf":[],"_links":{"self":[{"href":"https:\/\/helpdesk.costbook.ph\/index.php\/wp-json\/wp\/v2\/pages\/193","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/helpdesk.costbook.ph\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/helpdesk.costbook.ph\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/helpdesk.costbook.ph\/index.php\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/helpdesk.costbook.ph\/index.php\/wp-json\/wp\/v2\/comments?post=193"}],"version-history":[{"count":62,"href":"https:\/\/helpdesk.costbook.ph\/index.php\/wp-json\/wp\/v2\/pages\/193\/revisions"}],"predecessor-version":[{"id":1479,"href":"https:\/\/helpdesk.costbook.ph\/index.php\/wp-json\/wp\/v2\/pages\/193\/revisions\/1479"}],"wp:attachment":[{"href":"https:\/\/helpdesk.costbook.ph\/index.php\/wp-json\/wp\/v2\/media?parent=193"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}