<style id="elementor-post-1343">.elementor-1343 .elementor-element.elementor-element-c58048b{--display:flex;--padding-top:0px;--padding-bottom:0px;--padding-left:0px;--padding-right:0px;}</style>{"id":1343,"date":"2026-06-24T17:24:16","date_gmt":"2026-06-24T21:24:16","guid":{"rendered":"https:\/\/rismethod.com\/?page_id=1343"},"modified":"2026-09-07T10:31:05","modified_gmt":"2026-09-07T14:31:05","slug":"leadership-friction-suite","status":"publish","type":"page","link":"https:\/\/rismethod.com\/fr\/leadership-friction-suite\/","title":{"rendered":"Leadership Friction Autopsy"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"1343\" class=\"elementor elementor-1343\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-c58048b e-flex e-con-boxed e-con e-parent\" data-id=\"c58048b\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-6b0ccbb elementor-widget elementor-widget-html\" data-id=\"6b0ccbb\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>RIS METHOD\u2122 \u00b7 Leadership Friction Suite\u2122<\/title>\n  <link href=\"https:\/\/fonts.googleapis.com\/css2?family=Playfair+Display:wght@600;700&family=Inter:wght@400;500;600&display=swap\" rel=\"stylesheet\">\n  <script src=\"https:\/\/cdn.jsdelivr.net\/npm\/@emailjs\/browser@4\/dist\/email.min.js\"><\/script>\n\n  <style>\n    * { margin: 0; padding: 0; box-sizing: border-box; }\n\n    :root {\n      --bg-primary: #0d1117;\n      --bg-secondary: #131920;\n      --bg-card: #1a2332;\n      --accent-gold: #C9A84C;\n      --accent-gold-light: #e8c96a;\n      --text-primary: #f0ede8;\n      --text-muted: #9aa3b0;\n      --border-light: rgba(201, 168, 76, 0.2);\n      --border-strong: rgba(201, 168, 76, 0.5);\n    }\n\n    body {\n      font-family: 'Inter', sans-serif;\n      background-color: var(--bg-primary);\n      color: var(--text-primary);\n      line-height: 1.6;\n      overflow-x: hidden;\n    }\n\n    h1, h2, h3, h4 { font-family: 'Playfair Display', serif; }\n\n    strong { color: var(--accent-gold-light); font-weight: 600; }\n\n    .container { max-width: 1200px; margin: 0 auto; padding: 0 20px; }\n\n    \/* ===== LANDING SCREEN ===== *\/\n    #landingScreen {\n      min-height: 100vh;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      padding: 40px 20px;\n      animation: fadeInUp 0.6s ease-out;\n    }\n\n    .landing-content {\n      max-width: 700px;\n      text-align: center;\n    }\n\n    .landing-logo {\n      width: 80px;\n      height: 80px;\n      margin: 0 auto 24px;\n      border-radius: 12px;\n      \n      padding: 16px;\n    }\n\n    .landing-logo img {\n      width: 100%;\n      height: 100%;\n      object-fit: contain;\n    }\n\n    .landing-badge {\n      display: inline-block;\n      padding: 8px 16px;\n      background: var(--bg-card);\n      border: 1px solid var(--border-light);\n      border-radius: 50px;\n      font-size: 12px;\n      letter-spacing: 1px;\n      text-transform: uppercase;\n      color: var(--accent-gold);\n      margin-bottom: 24px;\n    }\n\n    .landing-title {\n      font-size: clamp(32px, 6vw, 52px);\n      font-weight: 700;\n      margin-bottom: 16px;\n      line-height: 1.2;\n    }\n\n    .landing-subtitle {\n      font-size: 18px;\n      color: var(--text-muted);\n      margin-bottom: 32px;\n      line-height: 1.6;\n    }\n\n    .landing-meta {\n      display: flex;\n      gap: 24px;\n      justify-content: center;\n      flex-wrap: wrap;\n      margin-bottom: 40px;\n      font-size: 14px;\n    }\n\n    .landing-meta-item {\n      display: flex;\n      align-items: center;\n      gap: 8px;\n    }\n\n    .landing-meta-item::before {\n      content: '';\n      width: 6px;\n      height: 6px;\n      background: var(--accent-gold);\n      border-radius: 50%;\n    }\n\n    .quote-card {\n      background: var(--bg-card);\n      border: 1px solid var(--border-light);\n      border-radius: 20px;\n      padding: 32px;\n      margin-bottom: 40px;\n      font-style: italic;\n      font-size: 16px;\n      color: var(--text-muted);\n      line-height: 1.8;\n    }\n\n    .quote-card::before {\n      content: '\"';\n      font-size: 48px;\n      color: var(--accent-gold);\n      display: block;\n      margin-bottom: 16px;\n      line-height: 0.5;\n    }\n\n    .quote-attribution {\n      font-style: normal;\n      color: var(--accent-gold);\n      margin-top: 16px;\n      font-size: 14px;\n      font-weight: 500;\n    }\n\n    .landing-cta {\n      margin-top: 8px;\n      font-size: 16px;\n      padding: 16px 36px;\n      cursor: pointer;\n    }\n\n    \/* ===== MAIN LAYOUT ===== *\/\n    #app { display: none; }\n    #app.active { display: flex; flex-direction: column; min-height: 100vh; }\n\n    .tab-bar {\n      background: var(--bg-secondary);\n      border-bottom: 1px solid var(--border-light);\n      display: flex;\n      gap: 0;\n      padding: 0 20px;\n    }\n\n    .tab-btn {\n      flex: 1;\n      padding: 16px 20px;\n      background: none;\n      border: none;\n      color: var(--text-muted);\n      font-size: 14px;\n      font-weight: 500;\n      cursor: pointer;\n      border-bottom: 2px solid transparent;\n      transition: all 0.25s ease;\n      text-transform: uppercase;\n      letter-spacing: 0.5px;\n    }\n\n    .tab-btn.active {\n      color: var(--accent-gold);\n      border-bottom-color: var(--accent-gold);\n    }\n\n    .tab-btn:hover:not(.active) {\n      color: var(--text-primary);\n    }\n\n    .screens-container {\n      flex: 1;\n      padding: 40px 20px;\n      overflow-y: auto;\n    }\n\n    .screen {\n      display: none;\n      animation: fadeInUp 0.4s ease-out;\n    }\n\n    .screen.active { display: block; }\n\n    \/* ===== FORMS ===== *\/\n    .form-group {\n      margin-bottom: 20px;\n    }\n\n    label {\n      display: block;\n      font-size: 14px;\n      font-weight: 500;\n      margin-bottom: 8px;\n      color: var(--text-primary);\n    }\n\n    .form-required::after {\n      content: ' *';\n      color: var(--accent-gold-light);\n    }\n\n    input[type=\"text\"],\n    input[type=\"email\"],\n    input[type=\"number\"],\n    input[type=\"date\"],\n    input[type=\"password\"],\n    select {\n      width: 100%;\n      padding: 12px 16px;\n      background: var(--bg-card);\n      border: 1px solid var(--border-light);\n      border-radius: 12px;\n      color: var(--text-primary);\n      font-family: 'Inter', sans-serif;\n      font-size: 14px;\n      transition: all 0.25s ease;\n    }\n\n    input[type=\"text\"]:focus,\n    input[type=\"email\"]:focus,\n    input[type=\"number\"]:focus,\n    input[type=\"date\"]:focus,\n    input[type=\"password\"]:focus,\n    select:focus {\n      outline: none;\n      border-color: var(--accent-gold);\n      box-shadow: 0 0 0 3px rgba(201, 168, 76, 0.1);\n    }\n\n    input::placeholder {\n      color: var(--text-muted);\n    }\n\n    \/* ===== BUTTONS ===== *\/\n    .btn {\n      padding: 12px 24px;\n      border: none;\n      border-radius: 12px;\n      font-family: 'Inter', sans-serif;\n      font-size: 14px;\n      font-weight: 600;\n      cursor: pointer;\n      transition: all 0.25s ease;\n      text-transform: uppercase;\n      letter-spacing: 0.5px;\n    }\n\n    .btn-primary {\n      background: linear-gradient(135deg, var(--accent-gold), var(--accent-gold-light));\n      color: var(--bg-primary);\n    }\n\n    .btn-primary:hover {\n      box-shadow: 0 8px 24px rgba(201, 168, 76, 0.3);\n      transform: translateY(-2px);\n    }\n\n    .btn-secondary {\n      background: var(--bg-card);\n      color: var(--accent-gold);\n      border: 1px solid var(--border-strong);\n    }\n\n    .btn-secondary:hover {\n      background: var(--bg-primary);\n      border-color: var(--accent-gold);\n    }\n\n    .btn:disabled {\n      opacity: 0.5;\n      cursor: not-allowed;\n    }\n\n    .btn-circle {\n      width: 56px;\n      height: 56px;\n      padding: 0;\n      border-radius: 50%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      font-size: 18px;\n      font-weight: 600;\n    }\n\n    @media (max-width: 640px) {\n      .btn-circle { width: 48px; height: 48px; font-size: 16px; }\n    }\n\n    @media (max-width: 400px) {\n      .btn-circle { width: 44px; height: 44px; font-size: 14px; }\n    }\n\n    \/* ===== SURVEY FLOW ===== *\/\n    .progress-bar-container {\n      background: var(--bg-secondary);\n      border-bottom: 1px solid var(--border-light);\n      padding: 20px;\n    }\n\n    .progress-label {\n      font-size: 12px;\n      text-transform: uppercase;\n      letter-spacing: 1px;\n      color: var(--accent-gold);\n      margin-bottom: 12px;\n      font-weight: 600;\n    }\n\n    .progress-bar {\n      width: 100%;\n      height: 6px;\n      background: var(--bg-card);\n      border-radius: 3px;\n      overflow: hidden;\n    }\n\n    .progress-fill {\n      height: 100%;\n      background: linear-gradient(90deg, var(--accent-gold), var(--accent-gold-light));\n      border-radius: 3px;\n      transition: width 0.4s ease;\n    }\n\n    .question-card {\n      max-width: 700px;\n      margin: 0 auto;\n      background: var(--bg-card);\n      border: 1px solid var(--border-light);\n      border-radius: 20px;\n      padding: 40px;\n      animation: slideInRight 0.4s ease-out;\n    }\n\n    .zone-pill {\n      display: inline-block;\n      padding: 6px 12px;\n      border-radius: 50px;\n      font-size: 11px;\n      font-weight: 600;\n      text-transform: uppercase;\n      letter-spacing: 0.5px;\n      margin-bottom: 16px;\n    }\n\n    .zone-pill.cf { background: rgba(201, 168, 76, 0.15); color: var(--accent-gold); }\n    .zone-pill.drag { background: rgba(220, 74, 57, 0.15); color: #dc4a39; }\n\n    .question-counter {\n      font-size: 12px;\n      color: var(--text-muted);\n      text-transform: uppercase;\n      letter-spacing: 0.5px;\n      margin-bottom: 12px;\n    }\n\n    .question-text {\n      font-size: 20px;\n      font-family: 'Playfair Display', serif;\n      font-weight: 600;\n      margin-bottom: 32px;\n      line-height: 1.4;\n    }\n\n    .answer-grid {\n      margin-bottom: 40px;\n    }\n\n    \/* Scale buttons *\/\n    .scale-buttons {\n      display: flex;\n      justify-content: space-between;\n      gap: 12px;\n      margin-bottom: 20px;\n    }\n\n    .scale-label {\n      font-size: 12px;\n      color: var(--text-muted);\n      text-align: center;\n      margin-top: 8px;\n    }\n\n    .scale-label.left { text-align: left; }\n    .scale-label.center { text-align: center; }\n    .scale-label.right { text-align: right; }\n\n    \/* Option buttons *\/\n    .option-buttons {\n      display: flex;\n      flex-direction: column;\n      gap: 12px;\n    }\n\n    .option-btn {\n      display: flex;\n      align-items: center;\n      gap: 16px;\n      padding: 16px 20px;\n      background: var(--bg-primary);\n      border: 1px solid var(--border-light);\n      border-radius: 12px;\n      cursor: pointer;\n      transition: all 0.25s ease;\n      color: var(--text-primary);\n      font-size: 15px;\n      text-align: left;\n    }\n\n    .option-btn:hover {\n      border-color: var(--accent-gold);\n      background: rgba(201, 168, 76, 0.05);\n      transform: translateX(8px);\n    }\n\n    .option-btn.selected {\n      background: rgba(201, 168, 76, 0.1);\n      border-color: var(--accent-gold);\n    }\n\n    .option-radio {\n      width: 20px;\n      height: 20px;\n      border: 2px solid var(--border-light);\n      border-radius: 50%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      flex-shrink: 0;\n      transition: all 0.25s ease;\n    }\n\n    .option-btn.selected .option-radio {\n      border-color: var(--accent-gold);\n      background: var(--accent-gold);\n    }\n\n    .option-radio::after {\n      content: '';\n      width: 8px;\n      height: 8px;\n      background: var(--bg-primary);\n      border-radius: 50%;\n      opacity: 0;\n      transition: opacity 0.25s ease;\n    }\n\n    .option-btn.selected .option-radio::after {\n      opacity: 1;\n    }\n\n    .nav-buttons {\n      display: flex;\n      gap: 16px;\n      margin-top: 40px;\n      justify-content: space-between;\n    }\n\n    \/* ===== RESULTS SCREEN ===== *\/\n    .results-header {\n      max-width: 700px;\n      margin: 0 auto 40px;\n      text-align: center;\n    }\n\n    .results-title {\n      font-size: clamp(24px, 5vw, 36px);\n      margin-bottom: 8px;\n    }\n\n    .results-subtitle {\n      color: var(--text-muted);\n      font-size: 16px;\n      margin-bottom: 12px;\n    }\n\n    .results-meta {\n      display: flex;\n      gap: 16px;\n      justify-content: center;\n      flex-wrap: wrap;\n      font-size: 13px;\n      color: var(--text-muted);\n    }\n\n    .results-section {\n      max-width: 700px;\n      margin: 0 auto 40px;\n    }\n\n    .score-card {\n      background: var(--bg-card);\n      border: 1px solid var(--border-light);\n      border-radius: 20px;\n      padding: 32px;\n      text-align: center;\n      margin-bottom: 24px;\n    }\n\n    .score-visualization {\n      width: 150px;\n      height: 150px;\n      margin: 0 auto 24px;\n    }\n\n    .score-visualization svg {\n      width: 100%;\n      height: 100%;\n    }\n\n    .score-level-badge {\n      display: inline-block;\n      padding: 8px 16px;\n      border-radius: 50px;\n      font-size: 12px;\n      font-weight: 600;\n      text-transform: uppercase;\n      letter-spacing: 0.5px;\n      margin-bottom: 16px;\n    }\n\n    .level-green { background: rgba(76, 175, 80, 0.15); color: #4caf50; }\n    .level-gold { background: rgba(201, 168, 76, 0.15); color: var(--accent-gold); }\n    .level-orange { background: rgba(255, 152, 0, 0.15); color: #ff9800; }\n    .level-red { background: rgba(220, 74, 57, 0.15); color: #dc4a39; }\n\n    .score-summary {\n      font-size: 16px;\n      line-height: 1.6;\n      color: var(--text-muted);\n    }\n\n    .zone-breakdown {\n      display: grid;\n      grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));\n      gap: 16px;\n    }\n\n    .zone-card {\n      background: var(--bg-primary);\n      border: 1px solid var(--border-light);\n      border-radius: 12px;\n      padding: 20px;\n    }\n\n    .zone-name {\n      font-family: 'Playfair Display', serif;\n      font-weight: 600;\n      margin-bottom: 12px;\n      font-size: 16px;\n    }\n\n    .zone-score {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      margin-bottom: 12px;\n      font-size: 14px;\n      color: var(--text-muted);\n    }\n\n    .zone-bar {\n      width: 100%;\n      height: 8px;\n      background: var(--bg-card);\n      border-radius: 4px;\n      overflow: hidden;\n    }\n\n    .zone-bar-fill {\n      height: 100%;\n      background: linear-gradient(90deg, var(--accent-gold), var(--accent-gold-light));\n      border-radius: 4px;\n      transition: width 0.6s ease 0.2s;\n      width: 0;\n    }\n\n    .combined-read {\n      background: var(--bg-card);\n      border: 1px solid var(--border-light);\n      border-radius: 20px;\n      padding: 32px;\n      margin-top: 40px;\n      font-size: 16px;\n      line-height: 1.8;\n      color: var(--text-muted);\n    }\n\n    .combined-read-title {\n      font-family: 'Playfair Display', serif;\n      font-weight: 600;\n      color: var(--text-primary);\n      margin-bottom: 16px;\n      font-size: 18px;\n    }\n\n    .email-confirmation {\n      text-align: center;\n      font-size: 14px;\n      margin-bottom: 32px;\n    }\n\n    \/* ===== ADMIN ===== *\/\n    .admin-login-container {\n      min-height: 100vh;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      padding: 20px;\n    }\n\n    .admin-login-card {\n      background: var(--bg-card);\n      border: 1px solid var(--border-light);\n      border-radius: 20px;\n      padding: 40px;\n      max-width: 400px;\n      width: 100%;\n      text-align: center;\n    }\n\n    .admin-login-logo {\n      width: 60px;\n      height: 60px;\n      margin: 0 auto 24px;\n      background: linear-gradient(135deg, var(--accent-gold), var(--accent-gold-light));\n      border-radius: 12px;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n    }\n\n    .admin-login-title {\n      font-size: 28px;\n      margin-bottom: 8px;\n    }\n\n    .admin-login-subtitle {\n      color: var(--text-muted);\n      margin-bottom: 32px;\n      font-size: 14px;\n    }\n\n    .admin-error {\n      background: rgba(220, 74, 57, 0.1);\n      border: 1px solid rgba(220, 74, 57, 0.3);\n      color: #ff6b6b;\n      padding: 12px 16px;\n      border-radius: 8px;\n      font-size: 14px;\n      margin-bottom: 20px;\n      display: none;\n    }\n\n    .admin-error.show { display: block; }\n\n    .admin-forgot {\n      text-align: center;\n      margin-top: 20px;\n      font-size: 12px;\n      color: var(--text-muted);\n    }\n\n    .admin-forgot a {\n      color: var(--accent-gold);\n      text-decoration: none;\n    }\n\n    .admin-dashboard {\n      max-width: 1400px;\n      margin: 0 auto;\n    }\n\n    .admin-header {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      margin-bottom: 40px;\n      flex-wrap: wrap;\n      gap: 20px;\n    }\n\n    .admin-header h1 {\n      font-size: 32px;\n    }\n\n    .admin-header-actions {\n      display: flex;\n      gap: 12px;\n    }\n\n    .stats-grid {\n      display: grid;\n      grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n      gap: 20px;\n      margin-bottom: 40px;\n    }\n\n    .stat-card {\n      background: var(--bg-card);\n      border: 1px solid var(--border-light);\n      border-radius: 12px;\n      padding: 24px;\n    }\n\n    .stat-label {\n      font-size: 12px;\n      text-transform: uppercase;\n      letter-spacing: 1px;\n      color: var(--text-muted);\n      margin-bottom: 12px;\n    }\n\n    .stat-value {\n      font-size: 36px;\n      font-weight: 600;\n      color: var(--accent-gold);\n    }\n\n    .admin-section {\n      background: var(--bg-card);\n      border: 1px solid var(--border-light);\n      border-radius: 20px;\n      padding: 32px;\n      margin-bottom: 32px;\n    }\n\n    .admin-section-title {\n      font-size: 20px;\n      margin-bottom: 24px;\n      font-family: 'Playfair Display', serif;\n    }\n\n    .session-form {\n      display: grid;\n      grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n      gap: 20px;\n      margin-bottom: 20px;\n    }\n\n    .form-group-full {\n      grid-column: 1 \/ -1;\n    }\n\n    .session-generated {\n      background: var(--bg-primary);\n      border: 1px solid var(--border-light);\n      border-radius: 12px;\n      padding: 20px;\n      margin-top: 20px;\n      display: none;\n    }\n\n    .session-generated.show { display: block; }\n\n    .session-url {\n      background: var(--bg-secondary);\n      border: 1px solid var(--border-light);\n      border-radius: 8px;\n      padding: 12px 16px;\n      margin-bottom: 16px;\n      font-family: monospace;\n      font-size: 12px;\n      overflow-x: auto;\n      word-break: break-all;\n    }\n\n    .session-actions {\n      display: flex;\n      gap: 12px;\n    }\n\n    \/* ===== TABLES ===== *\/\n    .table-container {\n      overflow-x: auto;\n    }\n\n    table {\n      width: 100%;\n      border-collapse: collapse;\n      font-size: 14px;\n    }\n\n    th {\n      background: var(--bg-primary);\n      border-bottom: 1px solid var(--border-light);\n      padding: 16px;\n      text-align: left;\n      font-weight: 600;\n      text-transform: uppercase;\n      letter-spacing: 0.5px;\n      font-size: 12px;\n      color: var(--text-muted);\n    }\n\n    td {\n      border-bottom: 1px solid var(--border-light);\n      padding: 16px;\n    }\n\n    tr:hover { background: rgba(201, 168, 76, 0.03); }\n\n    .table-actions {\n      display: flex;\n      gap: 8px;\n    }\n\n    .action-btn {\n      padding: 6px 12px;\n      font-size: 12px;\n      border-radius: 6px;\n    }\n\n    .badge {\n      display: inline-block;\n      padding: 4px 12px;\n      border-radius: 50px;\n      font-size: 11px;\n      font-weight: 600;\n      text-transform: uppercase;\n      letter-spacing: 0.5px;\n    }\n\n    .badge-active {\n      background: rgba(76, 175, 80, 0.15);\n      color: #4caf50;\n    }\n\n    .badge-expired {\n      background: rgba(220, 74, 57, 0.15);\n      color: #dc4a39;\n    }\n\n    .progress-mini {\n      width: 100%;\n      height: 6px;\n      background: var(--bg-secondary);\n      border-radius: 3px;\n      overflow: hidden;\n      margin-top: 4px;\n    }\n\n    .progress-mini-fill {\n      height: 100%;\n      background: var(--accent-gold);\n    }\n\n    \/* ===== MODAL ===== *\/\n    .modal {\n      display: none;\n      position: fixed;\n      top: 0;\n      left: 0;\n      right: 0;\n      bottom: 0;\n      background: rgba(0, 0, 0, 0.7);\n      backdrop-filter: blur(4px);\n      z-index: 1000;\n      align-items: center;\n      justify-content: center;\n      padding: 20px;\n    }\n\n    .modal.active { display: flex; }\n\n    .modal-content {\n      background: var(--bg-card);\n      border: 1px solid var(--border-light);\n      border-radius: 20px;\n      padding: 40px;\n      max-width: 700px;\n      width: 100%;\n      max-height: 80vh;\n      overflow-y: auto;\n      animation: fadeInUp 0.3s ease-out;\n    }\n\n    .modal-header {\n      display: flex;\n      justify-content: space-between;\n      align-items: flex-start;\n      margin-bottom: 24px;\n    }\n\n    .modal-title {\n      font-size: 24px;\n      font-family: 'Playfair Display', serif;\n    }\n\n    .modal-close {\n      background: none;\n      border: none;\n      color: var(--text-muted);\n      font-size: 24px;\n      cursor: pointer;\n      padding: 0;\n      width: 32px;\n      height: 32px;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n    }\n\n    .modal-close:hover { color: var(--accent-gold); }\n\n    \/* ===== TOAST ===== *\/\n    .toast-container {\n      position: fixed;\n      top: 20px;\n      right: 20px;\n      z-index: 2000;\n      display: flex;\n      flex-direction: column;\n      gap: 12px;\n    }\n\n    .toast {\n      background: var(--bg-card);\n      border: 1px solid var(--border-light);\n      border-radius: 12px;\n      padding: 16px 20px;\n      display: flex;\n      gap: 12px;\n      align-items: flex-start;\n      max-width: 400px;\n      animation: slideInRight 0.3s ease-out;\n      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n    }\n\n    .toast.success { border-color: rgba(76, 175, 80, 0.3); }\n    .toast.error { border-color: rgba(220, 74, 57, 0.3); }\n\n    .toast-icon {\n      font-size: 20px;\n      flex-shrink: 0;\n    }\n\n    .toast.success .toast-icon { color: #4caf50; }\n    .toast.error .toast-icon { color: #dc4a39; }\n\n    \/* ===== ANIMATIONS ===== *\/\n    @keyframes fadeInUp {\n      from {\n        opacity: 0;\n        transform: translateY(20px);\n      }\n      to {\n        opacity: 1;\n        transform: translateY(0);\n      }\n    }\n\n    @keyframes slideInRight {\n      from {\n        opacity: 0;\n        transform: translateX(20px);\n      }\n      to {\n        opacity: 1;\n        transform: translateX(0);\n      }\n    }\n\n    \/* ===== RESPONSIVE ===== *\/\n    @media (max-width: 640px) {\n      .screens-container { padding: 24px 16px; }\n      .question-card { padding: 24px 20px; }\n      .admin-section { padding: 20px; }\n      .modal-content { padding: 24px; }\n      .zone-breakdown {\n        grid-template-columns: 1fr;\n      }\n      .tab-bar {\n        gap: 0;\n      }\n      .tab-btn {\n        padding: 12px 16px;\n        font-size: 12px;\n      }\n    }\n\n    @media (max-width: 400px) {\n      .landing-title { font-size: 28px; }\n      .landing-subtitle { font-size: 16px; }\n      .question-card { padding: 20px 16px; }\n      .question-text { font-size: 18px; }\n      .scale-buttons { gap: 8px; }\n      .btn-circle { width: 44px; height: 44px; }\n    }\n  \n\/* ===== PRINT ===== *\/\n@media print {\n  body { background: #fff !important; color: #111 !important; }\n  #landingScreen, #app, #surveyContainer, #adminLoginContainer, #adminDashboardContainer, .tab-bar, .toast-container { display: none !important; }\n  .score-card, .results-section { break-inside: avoid; background: #fff !important; border: 1px solid #ccc !important; color: #111 !important; }\n  .score-card *, .results-section * { color: #111 !important; }\n  button { display: none !important; }\n  table, th, td { border-color: #ccc !important; color: #111 !important; }\n}\n<\/style>\n<\/head>\n<body>\n\n<!-- LANDING SCREEN -->\n<div id=\"landingScreen\">\n  <div class=\"landing-content\">\n    <div class=\"landing-logo\">\n        <img decoding=\"async\" src=\"https:\/\/rismethod.com\/wp-content\/uploads\/2026\/02\/cropped-RIS_LOGO_CLASSY-removebg-preview.png\" \" width=\"250\" height=\"auto\">\n      \n            <stop offset=\"0%\" style=\"stop-color:#e8c96a;stop-opacity:1\" \/>\n            <stop offset=\"100%\" style=\"stop-color:#C9A84C;stop-opacity:1\" \/>\n          <\/linearGradient>\n        <\/defs>\n        \n      <\/svg>\n    <\/div>\n\n    <div class=\"landing-badge\">RIS METHOD\u2122 \u00b7 Leadership Diagnostics<\/div>\n    <h1 class=\"landing-title\">The Leadership Friction Suite\u2122<\/h1>\n    <p class=\"landing-subtitle\">Two diagnostics. One sharp read. Where culture is slowing execution \u2014 and where the CEO is the constraint.<\/p>\n    <div class=\"landing-meta\">\n      <div class=\"landing-meta-item\">35 Questions \u00b7 8 Minutes<\/div>\n      <div class=\"landing-meta-item\">Confidential Team Mode<\/div>\n      <div class=\"landing-meta-item\">Results by Email<\/div>\n    <\/div>\n    <div class=\"quote-card\">\n      I work quietly with a small group of CEOs who are building legacy businesses, not just sellable assets.\n      <div class=\"quote-attribution\">\u2014 Phill Muraasi \u00b7 RISMETHOD\u2122<\/div>\n    <\/div>\n    <button type=\"button\" class=\"btn btn-primary landing-cta\" onclick=\"showApp()\">Begin the Diagnostic \u2192<\/button>\n  <\/div>\n<\/div>\n\n<!-- MAIN APP -->\n<div id=\"app\">\n  <div class=\"tab-bar\">\n    <button class=\"tab-btn active\" data-tab=\"ceo\">CEO Diagnostic<\/button>\n    <button class=\"tab-btn\" data-tab=\"team\">Team Survey<\/button>\n    <button class=\"tab-btn\" data-tab=\"admin\">Admin<\/button>\n  <\/div>\n\n  <div class=\"screens-container\">\n    <!-- CEO TAB -->\n    <div id=\"ceoScreen\" class=\"screen active\">\n      <div class=\"container\">\n        <div style=\"max-width: 600px; margin: 0 auto;\">\n          <h2 style=\"font-size: 28px; margin-bottom: 8px;\">CEO Diagnostic<\/h2>\n          <p style=\"color: var(--text-muted); margin-bottom: 32px;\">Tell us about you and your company.<\/p>\n\n          <form id=\"ceoIntakeForm\">\n            <div class=\"form-group\">\n              <label class=\"form-required\">Full Name<\/label>\n              <input type=\"text\" id=\"ceoName\" placeholder=\"Your full name\" required>\n            <\/div>\n\n            <div class=\"form-group\">\n              <label class=\"form-required\">Email Address<\/label>\n              <input type=\"email\" id=\"ceoEmail\" placeholder=\"your@email.com\" required>\n            <\/div>\n\n            <div class=\"form-group\">\n              <label class=\"form-required\">Your Role<\/label>\n              <input type=\"text\" id=\"ceoRole\" placeholder=\"e.g. CEO, Founder, MD\" required>\n            <\/div>\n\n            <div class=\"form-group\">\n              <label class=\"form-required\">Company Name<\/label>\n              <input type=\"text\" id=\"ceoCompany\" placeholder=\"Your company\" required>\n            <\/div>\n\n            <div class=\"form-group\">\n              <label class=\"form-required\">Annual Revenue<\/label>\n              <select id=\"ceoRevenue\" required>\n                <option value=\"\">Select revenue range<\/option>\n                <option value=\"under5m\">Under $5M<\/option>\n                <option value=\"5-20m\">$5M\u2013$20M<\/option>\n                <option value=\"20-50m\">$20M\u2013$50M<\/option>\n                <option value=\"50-100m\">$50M\u2013$100M<\/option>\n                <option value=\"100-200m\">$100M\u2013$200M<\/option>\n                <option value=\"200-500m\">$200M\u2013$500M<\/option>\n                <option value=\"500m+\">$500M+<\/option>\n              <\/select>\n            <\/div>\n\n            <div class=\"form-group\">\n              <label class=\"form-required\">Industry<\/label>\n              <select id=\"ceoIndustry\" required>\n                <option value=\"\">Select industry<\/option>\n                <option value=\"manufacturing\">Manufacturing<\/option>\n                <option value=\"healthcare\">Healthcare<\/option>\n                <option value=\"financial\">Financial Services<\/option>\n                <option value=\"technology\">Technology<\/option>\n                <option value=\"professional\">Professional Services<\/option>\n                <option value=\"retail\">Retail<\/option>\n                <option value=\"consumer\">Consumer<\/option>\n                <option value=\"construction\">Construction<\/option>\n                <option value=\"real-estate\">Real Estate<\/option>\n                <option value=\"nonprofit\">Non-Profit<\/option>\n                <option value=\"faith\">Faith-Based<\/option>\n                <option value=\"other\">Other<\/option>\n              <\/select>\n            <\/div>\n\n            <div class=\"form-group\">\n              <label class=\"form-required\">Number of Employees<\/label>\n              <select id=\"ceoEmployees\" required>\n                <option value=\"\">Select size<\/option>\n                <option value=\"1-25\">1\u201325<\/option>\n                <option value=\"26-100\">26\u2013100<\/option>\n                <option value=\"101-300\">101\u2013300<\/option>\n                <option value=\"301-500\">301\u2013500<\/option>\n                <option value=\"500+\">500+<\/option>\n              <\/select>\n            <\/div>\n\n            <button type=\"button\" class=\"btn btn-primary\" style=\"width: 100%; padding: 14px; font-size: 16px; margin-top: 20px;\" onclick=\"startCEODiagnostic()\">Begin My Diagnostic \u2192<\/button>\n          <\/form>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- TEAM TAB -->\n    <div id=\"teamScreen\" class=\"screen\">\n      <div class=\"container\">\n        <div style=\"max-width: 600px; margin: 0 auto;\">\n          <h2 style=\"font-size: 28px; margin-bottom: 8px;\">Team Survey<\/h2>\n          <p style=\"color: var(--text-muted); margin-bottom: 32px;\">Join your leader's diagnostic session.<\/p>\n\n          <div id=\"sessionStatus\" style=\"background: var(--bg-card); border: 1px solid var(--border-light); border-radius: 12px; padding: 16px; margin-bottom: 24px; display: none;\">\n            <div style=\"font-size: 12px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px;\">Session Status<\/div>\n            <div style=\"color: #4caf50; font-weight: 600;\">\u2713 Active Team Session<\/div>\n          <\/div>\n\n          <form id=\"teamIntakeForm\">\n            <div class=\"form-group\">\n              <label class=\"form-required\">Your Role<\/label>\n              <input type=\"text\" id=\"teamRole\" placeholder=\"e.g. VP Sales, CFO, Head of Ops\" required>\n            <\/div>\n\n            <div class=\"form-group\">\n              <label class=\"form-required\">Your Email<\/label>\n              <input type=\"email\" id=\"teamEmail\" placeholder=\"your@email.com\" required>\n              <div style=\"font-size: 12px; color: var(--text-muted); margin-top: 6px;\">Used to confirm your submission. Your individual answers are never shared with your leader by name \u2014 only the aggregate picture.<\/div>\n            <\/div>\n\n            <div class=\"form-group\">\n              <label class=\"form-required\">Company Name<\/label>\n              <input type=\"text\" id=\"teamCompany\" readonly>\n            <\/div>\n\n            <button type=\"button\" class=\"btn btn-primary\" style=\"width: 100%; padding: 14px; font-size: 16px; margin-top: 20px;\" id=\"startTeamBtn\" onclick=\"startTeamDiagnostic()\" disabled>Begin Team Diagnostic \u2192<\/button>\n          <\/form>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- ADMIN TAB -->\n    <div id=\"adminScreen\" class=\"screen\"><\/div>\n  <\/div>\n<\/div>\n\n<!-- SURVEY CONTAINER -->\n<div id=\"surveyContainer\" style=\"display: none; flex-direction: column; min-height: 100vh;\">\n  <div class=\"progress-bar-container\">\n    <div class=\"progress-label\" id=\"progressLabel\">Part 1 \u00b7 Cultural Friction \u2014 Question 1 of 25<\/div>\n    <div class=\"progress-bar\">\n      <div class=\"progress-fill\" id=\"progressFill\" style=\"width: 0%;\"><\/div>\n    <\/div>\n  <\/div>\n\n  <div class=\"screens-container\">\n    <div class=\"question-card\">\n      <div class=\"zone-pill cf\" id=\"zonePill\"><\/div>\n      <div class=\"question-counter\" id=\"questionCounter\"><\/div>\n      <div class=\"question-text\" id=\"questionText\"><\/div>\n      <div class=\"answer-grid\" id=\"answerGrid\"><\/div>\n      <div class=\"nav-buttons\">\n        <button class=\"btn btn-secondary\" id=\"backBtn\" style=\"display: none;\" onclick=\"previousQuestion()\">\u2190 Back<\/button>\n        <button class=\"btn btn-primary\" id=\"nextBtn\" disabled onclick=\"nextQuestion()\">Next \u2192<\/button>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n\n<!-- RESULTS CONTAINER -->\n<div id=\"resultsContainer\" style=\"display: none; flex-direction: column; min-height: 100vh;\">\n  <div class=\"screens-container\" style=\"padding-top: 60px; padding-bottom: 60px;\">\n    <div class=\"results-header\" id=\"resultsHeader\"><\/div>\n    <div id=\"resultsContent\"><\/div>\n  <\/div>\n<\/div>\n\n<!-- ADMIN LOGIN CONTAINER -->\n<div id=\"adminLoginContainer\" style=\"display: none;\">\n  <div class=\"admin-login-container\">\n    <div class=\"admin-login-card\">\n      <div class=\"admin-login-logo\">\ud83d\udd12<\/div>\n      <h1 class=\"admin-login-title\">Admin Access<\/h1>\n      <p class=\"admin-login-subtitle\">Enter credentials to continue<\/p>\n\n      <div class=\"admin-error\" id=\"adminError\"><\/div>\n\n      <form id=\"adminLoginForm\" onsubmit=\"adminLogin(event)\">\n        <div class=\"form-group\" style=\"text-align: left;\">\n          <label>Username<\/label>\n          <input type=\"text\" id=\"adminUsername\" placeholder=\"Username\" required>\n        <\/div>\n\n        <div class=\"form-group\" style=\"text-align: left;\">\n          <label>Password<\/label>\n          <input type=\"password\" id=\"adminPassword\" placeholder=\"Password\" required>\n        <\/div>\n\n        <button type=\"submit\" class=\"btn btn-primary\" style=\"width: 100%;\">Sign In<\/button>\n      <\/form>\n\n      <div class=\"admin-forgot\">\n        Forgot credentials? Contact <a href=\"mailto:phill@rismethod.com\">phill@rismethod.com<\/a>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n\n<!-- ADMIN DASHBOARD CONTAINER -->\n<div id=\"adminDashboardContainer\" style=\"display: none;\">\n  <div class=\"screens-container\">\n    <div class=\"admin-dashboard\">\n      <div class=\"admin-header\">\n        <h1>Admin Dashboard<\/h1>\n        <div class=\"admin-header-actions\">\n          <button class=\"btn btn-secondary\" onclick=\"exportCSV()\">\ud83d\udcca Export CSV<\/button>\n          <button class=\"btn btn-secondary\" onclick=\"adminLogout()\">Sign Out<\/button>\n        <\/div>\n      <\/div>\n\n      <div class=\"stats-grid\" id=\"statsGrid\"><\/div>\n\n      <div class=\"admin-section\">\n        <h2 class=\"admin-section-title\">Generate Session Link<\/h2>\n        <form id=\"sessionForm\" onsubmit=\"generateSessionLink(event)\">\n          <div class=\"session-form\">\n            <div class=\"form-group\">\n              <label class=\"form-required\">Company Name<\/label>\n              <input type=\"text\" id=\"sessionCompany\" required>\n            <\/div>\n            <div class=\"form-group\">\n              <label class=\"form-required\">Leader Name<\/label>\n              <input type=\"text\" id=\"sessionLeader\" required>\n            <\/div>\n            <div class=\"form-group\">\n              <label class=\"form-required\">Leader Email<\/label>\n              <input type=\"email\" id=\"sessionLeaderEmail\" required>\n            <\/div>\n            <div class=\"form-group\">\n              <label>Phone Number<\/label>\n              <input type=\"text\" id=\"sessionPhone\">\n            <\/div>\n            <div class=\"form-group\">\n              <label>Industry<\/label>\n              <select id=\"sessionIndustry\">\n                <option value=\"\">Select industry<\/option>\n                <option value=\"manufacturing\">Manufacturing<\/option>\n                <option value=\"healthcare\">Healthcare<\/option>\n                <option value=\"financial\">Financial Services<\/option>\n                <option value=\"technology\">Technology<\/option>\n                <option value=\"professional\">Professional Services<\/option>\n                <option value=\"retail\">Retail<\/option>\n                <option value=\"consumer\">Consumer<\/option>\n                <option value=\"construction\">Construction<\/option>\n                <option value=\"real-estate\">Real Estate<\/option>\n                <option value=\"nonprofit\">Non-Profit<\/option>\n                <option value=\"faith\">Faith-Based<\/option>\n                <option value=\"other\">Other<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"form-group\">\n              <label>Annual Revenue<\/label>\n              <select id=\"sessionRevenue\">\n                <option value=\"\">Select revenue<\/option>\n                <option value=\"under5m\">Under $5M<\/option>\n                <option value=\"5-20m\">$5M\u2013$20M<\/option>\n                <option value=\"20-50m\">$20M\u2013$50M<\/option>\n                <option value=\"50-100m\">$50M\u2013$100M<\/option>\n                <option value=\"100-200m\">$100M\u2013$200M<\/option>\n                <option value=\"200-500m\">$200M\u2013$500M<\/option>\n                <option value=\"500m+\">$500M+<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"form-group\">\n              <label>Team Size<\/label>\n              <select id=\"sessionTeamSize\">\n                <option value=\"\">Select size<\/option>\n                <option value=\"2\">2<\/option>\n                <option value=\"3\">3<\/option>\n                <option value=\"4\">4<\/option>\n                <option value=\"5\">5<\/option>\n                <option value=\"6\">6<\/option>\n                <option value=\"8\">8<\/option>\n                <option value=\"10\">10<\/option>\n                <option value=\"12\">12<\/option>\n                <option value=\"15+\">15+<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"form-group\">\n              <label>Session Date<\/label>\n              <input type=\"date\" id=\"sessionDate\">\n            <\/div>\n            <button type=\"submit\" class=\"btn btn-primary form-group-full\">Generate Session Link<\/button>\n          <\/div>\n        <\/form>\n\n        <div id=\"sessionGenerated\" class=\"session-generated\">\n          <div style=\"margin-bottom: 12px;\">\n            <div style=\"font-size: 12px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px;\">Session Created<\/div>\n            <div style=\"color: #4caf50; font-weight: 600;\">\u2713 Link generated successfully<\/div>\n          <\/div>\n          <div style=\"font-size: 12px; color: var(--text-muted); margin-bottom: 12px;\">Share this link with your team:<\/div>\n          <div class=\"session-url\" id=\"generatedSessionUrl\"><\/div>\n          <div class=\"session-actions\">\n            <button class=\"btn btn-secondary action-btn\" onclick=\"copySessionLink()\">\ud83d\udccb Copy Link<\/button>\n            <button class=\"btn btn-secondary action-btn\" onclick=\"emailSessionLink()\">\ud83d\udce7 Email to Leader<\/button>\n          <\/div>\n        <\/div>\n      <\/div>\n\n      <div class=\"admin-section\">\n        <h2 class=\"admin-section-title\">Perception Gap &mdash; CEO vs Team<\/h2>\n        <p style=\"color:var(--text-muted);font-size:14px;line-height:1.7;margin:-8px 0 18px;\">\n          The only signal in this system that is not self-report. Companies are matched by company name.\n          A gap report needs one CEO diagnostic plus at least one team response.\n        <\/p>\n        <div class=\"table-container\" id=\"gapTableContainer\"><\/div>\n      <\/div>\n\n      <div class=\"admin-section\">\n        <h2 class=\"admin-section-title\">Active Sessions<\/h2>\n        <div class=\"table-container\" id=\"sessionsTableContainer\"><\/div>\n      <\/div>\n\n      <div class=\"admin-section\">\n        <h2 class=\"admin-section-title\">All Results<\/h2>\n        <div class=\"table-container\" id=\"resultsTableContainer\"><\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n\n<!-- GAP REPORT CONTAINER -->\n<div id=\"gapReportContainer\" style=\"display: none; flex-direction: column; min-height: 100vh;\">\n  <div class=\"screens-container\" style=\"padding-top: 60px; padding-bottom: 60px;\">\n    <div class=\"results-header\" id=\"gapReportHeader\"><\/div>\n    <div id=\"gapReportContent\"><\/div>\n  <\/div>\n<\/div>\n\n<!-- MODAL -->\n<div id=\"detailModal\" class=\"modal\">\n  <div class=\"modal-content\" id=\"modalContent\"><\/div>\n<\/div>\n\n<!-- TOAST CONTAINER -->\n<div class=\"toast-container\" id=\"toastContainer\"><\/div>\n\n<script>\n\/\/ ===== CONFIG =====\nconst CONFIG = {\n  appUrl: window.location.origin + window.location.pathname,\n  email: {\n    \/\/ \u2705 EmailJS credentials configured\n    serviceId: 'service_fazl3ab',\n    templateIdAlert: 'template_e2g7fot', \/\/ Admin alerts\n    templateIdResults: 'template_inpkl2c', \/\/ Respondent results\n    templateIdLeader: 'template_vceka0h', \/\/ Session links\n    publicKey: 'oobNeFhCL0yLB43bV',\n    adminEmail: 'phill@rismethod.com' \/\/ Change this to your email\n  },\n  sheetsWebhook: 'https:\/\/script.google.com\/macros\/s\/AKfycbxyW3PtpwlZA6uVMv_4IoE21v7_F1hnx5x9cKbp-qyC6G8jR9YpitTehnZT3nD1NQu4\/exec', \/\/ Google Sheets central results register\n  admin: {\n    \/\/ Credentials stored as SHA-256 hashes \u2014 plaintext no longer lives in this file.\n    \/\/ To change them: generate the SHA-256 hex of the new value and replace below.\n    userHash: '7d8030ceaa67ccb2141206dbcf9f179db3ff769b64ecccec8a60d59764391a40',\n    passHash: 'bbfe85c20bd1adc33024bc6a4bef576bd126024f3f2da7cadaa9d868e1e42752'\n  }\n};\n\n\/\/ Initialize EmailJS\n\/\/ Guarded: if the EmailJS CDN fails to load, the diagnostic must still run.\nvar EMAIL_READY = (typeof emailjs !== 'undefined');\nif (EMAIL_READY && CONFIG.email.publicKey && CONFIG.email.publicKey !== 'YOUR_EMAILJS_PUBLIC_KEY') {\n  try { emailjs.init(CONFIG.email.publicKey); } catch (e) { EMAIL_READY = false; }\n}\n\n\/\/ ===== STATE =====\nlet state = {\n  mode: null, \/\/ 'ceo' or 'team'\n  currentQuestion: 0,\n  answers: [],\n  respondent: {},\n  session: null,\n  isAdminLoggedIn: false\n};\n\n\/\/ ===== QUESTIONS DATA =====\n\/\/ v3 \u2014 rebuilt July 2026. Reverse-keyed items carry reverse:true (scoring inverts them).\n\/\/ CEO-voice set. Zones must keep 5 items each, in order, for zone scoring.\nconst CF_QUESTIONS = [\n  {\n    zone: 'Leadership Alignment',\n    reverse: true,\n    text: 'If I asked my top five leaders separately to write down our single most important priority for the next 90 days, I would get <strong>more than two materially different answers<\/strong>.'\n  },\n  {\n    zone: 'Leadership Alignment',\n    text: 'In our last three genuinely contested resource decisions, my team reached the <strong>enterprise-right answer without me refereeing it<\/strong>.'\n  },\n  {\n    zone: 'Leadership Alignment',\n    reverse: true,\n    text: 'When we add a new priority, it gets <strong>stacked on top of everything else<\/strong> \u2014 nothing is removed to make room for it.'\n  },\n  {\n    zone: 'Leadership Alignment',\n    text: \"A meaningful part of each senior leader's scorecard or compensation is tied to <strong>enterprise outcomes<\/strong>, not only their own function's numbers.\"\n  },\n  {\n    zone: 'Leadership Alignment',\n    text: 'When my senior team gets alignment right without me, my honest first reaction is <strong>pride<\/strong> \u2014 not a faint sense that I was not needed.'\n  },\n  {\n    zone: 'Decision & Execution Discipline',\n    reverse: true,\n    text: 'Most of the decisions that reached me last week <strong>could have been made two levels down<\/strong> without a materially worse outcome.'\n  },\n  {\n    zone: 'Decision & Execution Discipline',\n    text: 'The last time I was genuinely unreachable for five business days was <strong>within the last six months<\/strong>, and nothing material slipped.'\n  },\n  {\n    zone: 'Decision & Execution Discipline',\n    text: 'In the last quarter, a direct report told me <strong>in the room<\/strong> that I was wrong \u2014 and I changed my position as a result.'\n  },\n  {\n    zone: 'Decision & Execution Discipline',\n    reverse: true,\n    text: 'My team knows to <strong>check with me informally<\/strong> before finalising anything significant \u2014 and that is simply how we work.'\n  },\n  {\n    zone: 'Decision & Execution Discipline',\n    text: 'Once a decision is made, the organisation starts executing rather than quietly <strong>re-litigating it through delay<\/strong>.'\n  },\n  {\n    zone: 'Accountability Rigor',\n    text: 'In the last 12 months at least one senior leader has faced a <strong>real consequence<\/strong> \u2014 role change, comp change, or exit \u2014 for repeatedly missing committed outcomes.'\n  },\n  {\n    zone: 'Accountability Rigor',\n    reverse: true,\n    text: 'When a commitment slips here, the most common outcome is a <strong>renegotiated deadline<\/strong> rather than a consequence.'\n  },\n  {\n    zone: 'Accountability Rigor',\n    text: 'In the last 90 days, material problems reached me <strong>while there was still time to fix them cheaply<\/strong>.'\n  },\n  {\n    zone: 'Accountability Rigor',\n    reverse: true,\n    text: 'There is at least one person on my leadership team who is <strong>protected by loyalty, history, or revenue contribution<\/strong> in a way I would not defend in front of my board.'\n  },\n  {\n    zone: 'Accountability Rigor',\n    text: 'I can name a commitment <strong>I personally missed<\/strong> last quarter and the consequence I took for it.'\n  },\n  {\n    zone: 'Talent Density & Energy',\n    text: 'Every leader in a critical seat is someone I would <strong>confidently hire again today<\/strong> for that same seat, knowing what I now know.'\n  },\n  {\n    zone: 'Talent Density & Energy',\n    reverse: true,\n    text: 'At least one of my strongest performers is currently <strong>carrying a weaker colleague<\/strong> while we describe the team as fine.'\n  },\n  {\n    zone: 'Talent Density & Energy',\n    reverse: true,\n    text: 'There is a seat I already know is wrong that has <strong>been wrong for more than six months<\/strong>.'\n  },\n  {\n    zone: 'Talent Density & Energy',\n    text: 'Within the last 90 days I have asked my most valuable person <strong>directly what would make them leave<\/strong>.'\n  },\n  {\n    zone: 'Talent Density & Energy',\n    text: 'I can name, without hesitating, the person who could <strong>run this company better than me<\/strong> within 18 months \u2014 not merely keep it alive.'\n  },\n  {\n    zone: 'Leadership Courage & Cultural Integrity',\n    reverse: true,\n    text: 'There is something <strong>everyone in this company knows is broken<\/strong> that has never been named in a formal leadership meeting.'\n  },\n  {\n    zone: 'Leadership Courage & Cultural Integrity',\n    text: 'When a commercially valuable or politically influential leader underperforms, we <strong>confront it directly and promptly<\/strong>.'\n  },\n  {\n    zone: 'Leadership Courage & Cultural Integrity',\n    reverse: true,\n    text: 'Topics get discussed honestly <strong>in the corridor after the meeting<\/strong> that would not be said inside the meeting.'\n  },\n  {\n    zone: 'Leadership Courage & Cultural Integrity',\n    reverse: true,\n    text: 'If my top three people were asked anonymously to name the single biggest obstacle to this company\\u2019s growth, there is a <strong>real chance at least one would name me<\/strong>.'\n  },\n  {\n    zone: 'Leadership Courage & Cultural Integrity',\n    text: 'If I rebuilt this company from scratch at the same scale, I would deliberately recreate the <strong>courage standard<\/strong> of our leadership culture as it exists today.'\n  }\n];\n\n\/\/ Team-voice mirror set \u2014 same zones, same order, observed from the team's seat.\nconst TEAM_CF_QUESTIONS = [\n  {\n    zone: 'Leadership Alignment',\n    reverse: true,\n    text: 'If each member of the senior team privately wrote down the company\\u2019s single most important priority for the next 90 days, we would get <strong>more than two materially different answers<\/strong>.'\n  },\n  {\n    zone: 'Leadership Alignment',\n    text: 'In our last three genuinely contested resource decisions, the leadership team reached the <strong>company-right answer without the CEO refereeing it<\/strong>.'\n  },\n  {\n    zone: 'Leadership Alignment',\n    reverse: true,\n    text: 'When leadership adds a new priority, it gets <strong>stacked on top of everything else<\/strong> \u2014 nothing is removed to make room.'\n  },\n  {\n    zone: 'Leadership Alignment',\n    text: \"Leaders here are rewarded for <strong>company outcomes<\/strong>, not only their own department's numbers.\"\n  },\n  {\n    zone: 'Leadership Alignment',\n    reverse: true,\n    text: 'When the team gets something right without the CEO, the CEO seems <strong>less pleased than you would expect<\/strong>.'\n  },\n  {\n    zone: 'Decision & Execution Discipline',\n    reverse: true,\n    text: 'Most of what goes to the CEO for a decision <strong>could be decided two levels down<\/strong> without a worse outcome.'\n  },\n  {\n    zone: 'Decision & Execution Discipline',\n    text: 'The last time the CEO was genuinely unreachable for a week, the company <strong>kept moving without material drift<\/strong>.'\n  },\n  {\n    zone: 'Decision & Execution Discipline',\n    text: 'In the last quarter I have seen someone tell the CEO <strong>in the room<\/strong> that they were wrong \u2014 and watched the CEO change position.'\n  },\n  {\n    zone: 'Decision & Execution Discipline',\n    reverse: true,\n    text: 'Nothing significant here feels final until someone has <strong>checked with the CEO informally<\/strong>.'\n  },\n  {\n    zone: 'Decision & Execution Discipline',\n    text: 'Once a decision is made, we start executing rather than quietly <strong>re-litigating it through delay<\/strong>.'\n  },\n  {\n    zone: 'Accountability Rigor',\n    text: 'In the last 12 months at least one senior leader has faced a <strong>real consequence<\/strong> for repeatedly missing committed outcomes.'\n  },\n  {\n    zone: 'Accountability Rigor',\n    reverse: true,\n    text: 'When a commitment slips here, the usual outcome is a <strong>renegotiated deadline<\/strong> rather than a consequence.'\n  },\n  {\n    zone: 'Accountability Rigor',\n    text: 'Bad news reaches leadership <strong>while there is still time to fix it cheaply<\/strong>.'\n  },\n  {\n    zone: 'Accountability Rigor',\n    reverse: true,\n    text: 'At least one person here is <strong>protected by loyalty, history, or revenue contribution<\/strong> in a way the rest of us can see clearly.'\n  },\n  {\n    zone: 'Accountability Rigor',\n    text: 'When the CEO personally misses a commitment, it is <strong>named and owned<\/strong> the same way ours would be.'\n  },\n  {\n    zone: 'Talent Density & Energy',\n    text: 'Every leader in a critical seat is someone this company would <strong>confidently hire again today<\/strong> for that same seat.'\n  },\n  {\n    zone: 'Talent Density & Energy',\n    reverse: true,\n    text: 'At least one of our strongest performers is currently <strong>carrying a weaker colleague<\/strong> while we describe the team as fine.'\n  },\n  {\n    zone: 'Talent Density & Energy',\n    reverse: true,\n    text: 'There is a seat everyone knows is wrong that has <strong>been wrong for more than six months<\/strong>.'\n  },\n  {\n    zone: 'Talent Density & Energy',\n    text: 'In the last 90 days someone in leadership has asked me directly <strong>what would make me leave<\/strong>.'\n  },\n  {\n    zone: 'Talent Density & Energy',\n    text: 'I can name someone here who could <strong>run this company well<\/strong> if the CEO stepped away for a year.'\n  },\n  {\n    zone: 'Leadership Courage & Cultural Integrity',\n    reverse: true,\n    text: 'There is something <strong>everyone here knows is broken<\/strong> that has never been named in a formal leadership meeting.'\n  },\n  {\n    zone: 'Leadership Courage & Cultural Integrity',\n    text: 'When a commercially valuable or politically influential leader underperforms, it is <strong>confronted directly and promptly<\/strong>.'\n  },\n  {\n    zone: 'Leadership Courage & Cultural Integrity',\n    reverse: true,\n    text: 'The honest conversation happens <strong>in the corridor after the meeting<\/strong>, not inside it.'\n  },\n  {\n    zone: 'Leadership Courage & Cultural Integrity',\n    reverse: true,\n    text: 'If I were asked anonymously to name the single biggest obstacle to this company\\u2019s growth, <strong>the honest answer would be the CEO<\/strong>.'\n  },\n  {\n    zone: 'Leadership Courage & Cultural Integrity',\n    text: 'If this company were rebuilt from scratch, I would want it to <strong>keep the courage standard<\/strong> of the leadership culture exactly as it is today.'\n  }\n];\n\nconst DRAG_QUESTIONS = [\n  {\n    text: 'If you were <strong>completely unreachable for three weeks<\/strong> \u2014 no phone, no email \u2014 what would actually happen?',\n    options: [\n      { text: 'The company would run. Nothing material would break.', score: 0 },\n      { text: 'It would hold, but several things would slip.', score: 1 },\n      { text: 'Something important would break within days.', score: 2 }\n    ]\n  },\n  {\n    text: 'Of the decisions that reached you last week, what share <strong>genuinely required your specific judgment, relationships, or authority<\/strong> \u2014 not just your approval?',\n    options: [\n      { text: 'Most of them \u2014 I only see what truly needs me', score: 0 },\n      { text: 'About half \u2014 the rest is routing', score: 1 },\n      { text: 'A small minority \u2014 I am mostly approving', score: 2 }\n    ]\n  },\n  {\n    text: 'Can you name the person who could <strong>run this company better than you<\/strong> within 18 months? Better \u2014 not merely keep it alive.',\n    options: [\n      { text: 'Yes \u2014 I can name them without hesitating', score: 0 },\n      { text: 'I can name someone who could hold it together', score: 1 },\n      { text: 'No \u2014 there is no one', score: 2 }\n    ]\n  },\n  {\n    text: 'If your best operator became <strong>90% as good at your job<\/strong> as you are, what is your honest first reaction?',\n    options: [\n      { text: 'Relief \u2014 that is the entire goal', score: 0 },\n      { text: 'Mixed \u2014 pride, and something less comfortable', score: 1 },\n      { text: 'Threat \u2014 I would wonder what is left for me', score: 2 }\n    ]\n  },\n  {\n    text: 'When was your last <strong>full day with no email, no messages, no business calls<\/strong> \u2014 by choice, and without anxiety about it?',\n    options: [\n      { text: 'Within the last month', score: 0 },\n      { text: 'Within the last six months', score: 1 },\n      { text: \"I honestly can't remember\", score: 2 }\n    ]\n  },\n  {\n    text: 'If your top three people were asked anonymously to name the <strong>single biggest obstacle to this company\\u2019s growth<\/strong>, what are the odds at least one names you?',\n    options: [\n      { text: 'Low \u2014 under 10%', score: 0 },\n      { text: 'Real \u2014 somewhere around a third', score: 1 },\n      { text: 'High \u2014 more likely than not', score: 2 }\n    ]\n  },\n  {\n    text: 'Are you building this company so it <strong>eventually does not need you<\/strong> \u2014 or so that it can never fully replace what only you provide?',\n    options: [\n      { text: 'So it does not need me. That is the point.', score: 0 },\n      { text: 'I say the first, but I behave like the second.', score: 1 },\n      { text: 'Honestly \u2014 so that it always needs me.', score: 2 }\n    ]\n  },\n  {\n    text: 'A buyer offers a fair price tomorrow, on the condition you <strong>never work in this industry again<\/strong>. What would actually stop you saying yes?',\n    options: [\n      { text: 'Nothing but the number. This is an asset to me.', score: 0 },\n      { text: 'The number \u2014 and some of the identity.', score: 1 },\n      { text: 'Who I would be without it.', score: 2 }\n    ]\n  },\n  {\n    text: 'You are told today you must <strong>fully retire in 12 months<\/strong> \u2014 no advisory seat, no calls, no board role. What hits first?',\n    options: [\n      { text: 'Relief', score: 0 },\n      { text: 'Grief', score: 1 },\n      { text: 'Fear', score: 2 }\n    ]\n  },\n  {\n    text: 'Of your nine answers above, how many are the version you would want <strong>a board member to see<\/strong> \u2014 rather than the polished version you would give in a peer group?',\n    options: [\n      { text: 'All of them. I answered these straight.', score: 0 },\n      { text: 'Most \u2014 one or two were softened.', score: 1 },\n      { text: 'Several were the polished version.', score: 2 }\n    ]\n  }\n];\n\n\/\/ Team-voice drag set \u2014 the team observes the CEO. Same scoring.\nconst TEAM_DRAG_QUESTIONS = [\n  {\n    text: 'If your CEO were <strong>completely unreachable for three weeks<\/strong>, what would actually happen?',\n    options: [\n      { text: 'The company would run. Nothing material would break.', score: 0 },\n      { text: 'It would hold, but several things would slip.', score: 1 },\n      { text: 'Something important would break within days.', score: 2 }\n    ]\n  },\n  {\n    text: 'Of what goes to the CEO for a decision, what share <strong>genuinely needs them<\/strong> \u2014 rather than just their sign-off?',\n    options: [\n      { text: 'Most of it \u2014 they only see what truly needs them', score: 0 },\n      { text: 'About half \u2014 the rest is routing', score: 1 },\n      { text: 'A small minority \u2014 it is mostly approval', score: 2 }\n    ]\n  },\n  {\n    text: 'Is there someone here who could <strong>run this company well<\/strong> if the CEO stepped away for 18 months?',\n    options: [\n      { text: 'Yes \u2014 clearly, and more than one person', score: 0 },\n      { text: 'Someone could hold it together', score: 1 },\n      { text: 'No \u2014 there is no one', score: 2 }\n    ]\n  },\n  {\n    text: 'If a senior leader became <strong>nearly as capable as the CEO<\/strong> at the CEO\\u2019s own job, how would the CEO react?',\n    options: [\n      { text: 'Relief and support \u2014 they would promote them', score: 0 },\n      { text: 'Mixed \u2014 pride, but some discomfort', score: 1 },\n      { text: 'Threatened \u2014 that person would find the ceiling', score: 2 }\n    ]\n  },\n  {\n    text: 'Does the CEO ever <strong>genuinely disconnect<\/strong> \u2014 a full day with no messages, no calls?',\n    options: [\n      { text: 'Yes, regularly', score: 0 },\n      { text: 'Rarely, and never fully', score: 1 },\n      { text: 'Never \u2014 they are always reachable', score: 2 }\n    ]\n  },\n  {\n    text: 'If you were asked anonymously to name the <strong>single biggest obstacle to this company\\u2019s growth<\/strong>, how likely is it the honest answer is the CEO?',\n    options: [\n      { text: 'Unlikely \u2014 the constraint is elsewhere', score: 0 },\n      { text: 'Possible \u2014 they are one of two or three real constraints', score: 1 },\n      { text: 'Likely \u2014 the honest answer is the CEO', score: 2 }\n    ]\n  },\n  {\n    text: 'Is this company being built so it <strong>eventually does not need the CEO<\/strong> \u2014 or so that it always will?',\n    options: [\n      { text: 'So it does not need them. You can see it being built that way.', score: 0 },\n      { text: 'That is what is said, but not what is built.', score: 1 },\n      { text: 'It is being built so it always needs them.', score: 2 }\n    ]\n  },\n  {\n    text: 'If the CEO sold tomorrow and <strong>had to leave the industry entirely<\/strong>, would this company hold together?',\n    options: [\n      { text: 'Yes \u2014 the systems and people would carry it', score: 0 },\n      { text: 'Probably \u2014 with a difficult year', score: 1 },\n      { text: 'No \u2014 much of what holds this together would leave with them', score: 2 }\n    ]\n  },\n  {\n    text: 'If the CEO announced <strong>full retirement in 12 months<\/strong>, what would the leadership team feel first?',\n    options: [\n      { text: 'Confidence \u2014 we know how this would work', score: 0 },\n      { text: 'Uncertainty \u2014 we would have to work it out', score: 1 },\n      { text: 'Alarm \u2014 we have no idea what happens next', score: 2 }\n    ]\n  },\n  {\n    text: 'How many of your answers above are the version you would give <strong>if the CEO were reading them<\/strong>?',\n    options: [\n      { text: 'None \u2014 I answered these straight', score: 0 },\n      { text: 'One or two were softened', score: 1 },\n      { text: 'Several were the safe version', score: 2 }\n    ]\n  }\n];\n\nconst REVENUE_MIDPOINTS = { 'under5m': 3, '5-20m': 12, '20-50m': 35, '50-100m': 75, '100-200m': 150, '200-500m': 350, '500m+': 600 };\n\nconst ZONE_LABELS = { alignment: 'Leadership Alignment', decision: 'Decision & Execution', accountability: 'Accountability Rigor', talent: 'Talent Density', culture: 'Leadership Courage' };\n\nconst REC_BLOCKS = {\n  alignment: {\n    strength: 'Your leadership team is pulling in one direction \u2014 rare and valuable at your scale. Protect it: codify the priority stack in writing, revisit it quarterly, and make it the first filter for every new initiative. Alignment decays silently under growth; what preserves it is subtraction discipline \u2014 every added priority must displace one.',\n    friction: \"Your leaders agree in the meeting and diverge in the corridor. The cost is duplicated effort and functional turf wars that never surface as open conflict \u2014 they surface as missed quarters. 14-day move: have each senior leader write the company's top priority independently, then compare the answers in the room. The spread you see is your alignment tax, made visible.\",\n    critical: 'At this level your company is effectively running several competing strategies at once \u2014 each function optimising for itself while the enterprise pays. Expect execution to die at director level, because nobody below you can resolve conflicts you have not resolved at the top. 14-day move: one working session, one written priority stack, one explicit list of what you are STOPPING. Nothing else works until this exists.'\n  },\n  decision: {\n    strength: 'Decisions move at the speed of facts, not fear \u2014 a structural advantage most companies never build. Guard the two failure points that arrive with scale: new leaders importing escalation habits, and your own availability quietly re-centralising decisions. Write decision rights down before your next senior hire.',\n    friction: \"Decisions are being made, then informally re-approved, then quietly re-litigated. Every loop adds days and teaches your best people that the meeting is not where truth happens. 14-day move: pick the three most consequential recurring decision types and assign each a single named owner \u2014 not a committee. Announce that reversing a decision now requires a meeting, not a corridor.\",\n    critical: \"Decision-making has collapsed upward. Escalation is being used as insurance, and delay has become the organisation's way of saying no without saying it. This is the pattern that caps companies at their CEO's personal bandwidth. 14-day move: log every decision that reaches you for one week and mark which ones a named subordinate could have made. Then hand those decision rights back \u2014 in writing, in public.\"\n  },\n  accountability: {\n    strength: 'Commitments here mean something \u2014 missed outcomes trigger real conversations, and bad news travels fast enough to be cheap. Sustain it by keeping consequence visible: when a hard call is made, let the leadership team see that it was made, and why.',\n    friction: 'Deadlines are being politely reset, and problems are arriving after the cheap window to fix them has closed. Your real standard is drifting toward what you tolerate, not what you preach. 14-day move: revisit the last three missed commitments and hold the conversation that should have happened \u2014 not as punishment, but so the team relearns that commitments are contracts.',\n    critical: 'Accountability has become optional for the protected. Your strongest performers noticed \u2014 they always notice first \u2014 and they are quietly recalibrating their own effort against what leadership tolerates. This is how A-players leave and B-players settle in. 14-day move: identify the single most visible tolerated underperformance and act on it. One visible act of consequence resets more culture than a year of values talk.'\n  },\n  talent: {\n    strength: 'You would rehire your critical seats today \u2014 that puts you in a small minority of companies at your scale. Keep the bar where it is: hire from conviction, act early on drift, and re-ask the rehire question quarterly. Talent density is a standard, not an event.',\n    friction: \"At least one seat is below standard and everyone knows it \u2014 including the people carrying the extra weight. The cost is not just that seat's output; it is the message your tolerance sends to your best people. 14-day move: run the rehire test on every critical seat, in writing. Any 'no' gets a plan with a date: coach up, move, or move out.\",\n    critical: 'Your best people are subsidising your weakest, and leadership has been describing the team as fine. That subsidy always ends the same way \u2014 the strong leave, the weak stay, and the CEO wonders when the culture changed. 14-day move: the two hardest people decisions you have been deferring go on the table with dates attached. Deferred people decisions are the most expensive line item you do not track.'\n  },\n  culture: {\n    strength: \"Truth moves faster than politics in your company \u2014 the rarest cultural asset there is. It survives only as long as the CEO visibly rewards the bearer of bad news. Keep doing that publicly, and keep the 'no exemptions' rule absolute \u2014 one protected person is all it takes to retrain everyone.\",\n    friction: 'Truth is arriving edited. Hard conversations are happening in corridors instead of the room, and at least one topic has become quietly undiscussable. Every undiscussable charges you the compound interest of unspoken problems. 14-day move: name the undiscussable yourself, in the room, first. The CEO going first is the only known cure.',\n    critical: \"Your company has learned that honesty is unsafe and silence is free. You are now making decisions on filtered information \u2014 the most expensive kind there is. Expect surprises 'nobody saw coming' that everybody saw coming. 14-day move: bring in a forcing mechanism \u2014 an anonymous team read (this tool's Team Mode exists for exactly this) \u2014 then respond to what surfaces without punishing a single messenger.\"\n  }\n};\n\nconst DRAG_FLAGS = [\n  'Three weeks away and something important breaks. Whatever you believe you own, this means the company owns you \\u2014 and any acquirer, lender, or investor will price that dependency in.',\n  'Only a minority of what reaches you actually needs you. You are not operating as the CEO; you are operating as the chief approval officer. Decision rights, not effort, are your constraint.',\n  'You cannot name a successor who would run this better than you. That is not a talent market problem \\u2014 it is a bench you have not built, and it is the single largest discount a buyer will apply.',\n  'Your honest reaction to someone approaching your capability is closer to threat than relief. Every founder feels it; very few will say it. Naming it is the first move \\u2014 because that instinct, unexamined, quietly caps every person you hire.',\n  'If you cannot remember your last real day off, you do not have a vacation problem \\u2014 you have an architecture problem. Rest is a stress test your company is currently failing.',\n  'You put real odds on your own top three naming you as the obstacle. Believe your own estimate. It is the most accurate number in this report.',\n  'You said it plainly: this company is being built so that it always needs you. That is a choice, not a circumstance \\u2014 and it is the choice that decides whether you own an asset or a job.',\n  'What would stop you selling is not the number \\u2014 it is who you would be without it. That is worth taking seriously, because a business held for identity reasons gets managed for identity reasons.',\n  'Forced retirement lands as fear rather than relief. That answer says the company is currently carrying more of your identity than your balance sheet.',\n  'You have told us some of these answers were the polished version. That is honest, and it matters: your real scores are almost certainly worse than what this report shows. Read every number below as a floor, not a ceiling.'\n];\n\nfunction zoneSeverity(score) {\n  if (score <= 10) return 'strength';\n  if (score <= 17) return 'friction';\n  return 'critical';\n}\n\nfunction formatMoney(m) {\n  return m >= 1 ? '$' + m.toFixed(1).replace(\/\\.0$\/, '') + 'M' : '$' + Math.round(m * 1000) + 'K';\n}\n\nfunction frictionTax(scores) {\n  const mid = REVENUE_MIDPOINTS[state.respondent.revenue];\n  if (!mid) return null;\n  const cfPct = Math.max(0, (scores.cf.total - 25) \/ 100);\n  const dragPct = scores.drag.total \/ 20;\n  const combined = cfPct * 0.6 + dragPct * 0.4;\n  if (combined < 0.05) return null;\n  const low = mid * combined * 0.02;\n  const high = mid * combined * 0.05;\n  return {\n    low: low,\n    high: high,\n    text: formatMoney(low) + '\\u2013' + formatMoney(high) + ' per year',\n    method: 'How this is derived: your friction index (60% culture score, 40% CEO drag score) applied to a 2\\u20135% band of revenue at your stated revenue band. The 2\\u20135% band is RISMETHOD\\u2019s own working assumption from field engagements, not a published academic figure \\u2014 it is deliberately conservative and stated as a range for that reason. This is a directional estimate built entirely from your own answers. It is not an audit, and it should be treated as a floor for discussion, not a finding.'\n  };\n}\n\nfunction buildRecommendations(scores) {\n  const sorted = Object.entries(scores.cf.zoneScores).sort((a, b) => b[1] - a[1]); \/\/ worst first\n  const worst = sorted.slice(0, 2);\n  const best = sorted.slice(-2).reverse();\n  const tax = state.mode === 'ceo' ? frictionTax(scores) : null;\n\n  let html = '<div class=\"score-card\" style=\"text-align:left;\">';\n  html += '<h3 style=\"margin-bottom:16px;\">Your Tailored Read \u2014 And What To Do About It<\/h3>';\n  let text = '';\n\n  if (tax) {\n    html += '<div style=\"background:var(--bg-primary);border:1px solid var(--border-light);border-radius:12px;padding:16px;margin-bottom:20px;\"><strong style=\"color:var(--accent-gold);\">Estimated Friction Tax: ' + tax.text + '<\/strong><div style=\"font-size:12px;color:var(--text-muted);margin-top:8px;line-height:1.6;\">' + tax.method + '<\/div><\/div>';\n    text += 'ESTIMATED FRICTION TAX: ' + tax.text + '\\n' + tax.method + '\\n\\n';\n  }\n\n  html += '<h4 style=\"margin-bottom:12px;\">Your two priority zones<\/h4>';\n  text += 'YOUR TWO PRIORITY ZONES\\n';\n  worst.forEach(function (entry) {\n    const key = entry[0], score = entry[1];\n    const sev = zoneSeverity(score);\n    const block = REC_BLOCKS[key][sev];\n    const sevLabel = sev === 'critical' ? 'CRITICAL' : sev === 'friction' ? 'FRICTION' : 'STRENGTH';\n    html += '<div style=\"margin-bottom:16px;\"><strong>' + ZONE_LABELS[key] + ' \u2014 ' + score + '\/25 (' + sevLabel + ')<\/strong><p style=\"color:var(--text-muted);font-size:14px;line-height:1.7;margin-top:6px;\">' + block + '<\/p><\/div>';\n    text += '\\n' + ZONE_LABELS[key] + ' \u2014 ' + score + '\/25 (' + sevLabel + ')\\n' + block + '\\n';\n  });\n\n  html += '<h4 style=\"margin:20px 0 12px;\">Where you are strongest<\/h4>';\n  text += '\\nWHERE YOU ARE STRONGEST\\n';\n  best.forEach(function (entry) {\n    const key = entry[0], score = entry[1];\n    if (zoneSeverity(score) === 'strength') {\n      html += '<div style=\"margin-bottom:12px;\"><strong>' + ZONE_LABELS[key] + ' \u2014 ' + score + '\/25<\/strong><p style=\"color:var(--text-muted);font-size:14px;line-height:1.7;margin-top:6px;\">' + REC_BLOCKS[key].strength + '<\/p><\/div>';\n      text += '\\n' + ZONE_LABELS[key] + ' \u2014 ' + score + '\/25\\n' + REC_BLOCKS[key].strength + '\\n';\n    } else {\n      html += '<div style=\"margin-bottom:12px;\"><strong>' + ZONE_LABELS[key] + ' \u2014 ' + score + '\/25<\/strong><p style=\"color:var(--text-muted);font-size:14px;line-height:1.7;margin-top:6px;\">Your relative strongest zone \u2014 but at ' + score + '\/25 it still carries friction. Stabilise the priority zones above first.<\/p><\/div>';\n      text += '\\n' + ZONE_LABELS[key] + ' \u2014 ' + score + '\/25 (relative strength, still carrying friction)\\n';\n    }\n  });\n\n  if (state.mode === 'ceo') {\n    const flags = [];\n    (scores.dragAnswers || []).forEach(function (ansIdx, i) {\n      if (ansIdx !== null && ansIdx !== undefined && DRAG_QUESTIONS[i].options[ansIdx].score === 2) flags.push(DRAG_FLAGS[i]);\n    });\n    if (flags.length) {\n      html += '<h4 style=\"margin:20px 0 12px;\">Red flags from your own answers<\/h4>';\n      text += '\\nRED FLAGS FROM YOUR OWN ANSWERS\\n';\n      flags.forEach(function (f) {\n        html += '<p style=\"color:var(--text-muted);font-size:14px;line-height:1.7;margin-bottom:10px;\">\u2022 ' + f + '<\/p>';\n        text += '\\n\u2022 ' + f + '\\n';\n      });\n    }\n  }\n\n  html += '<div style=\"margin-top:24px;padding-top:16px;border-top:1px solid var(--border-light);font-size:14px;color:var(--text-muted);\">This read is generated from your specific answers \u2014 different answers produce a different read. To pressure-test it against reality, the next step is a confidential <strong>Leadership Risk Audit<\/strong>: <a href=\"mailto:phill@rismethod.com\" style=\"color:var(--accent-gold);\">phill@rismethod.com<\/a><\/div>';\n  html += '<\/div>';\n\n  return { html: html, text: text, taxText: tax ? tax.text : '' };\n}\n\nfunction simpleSig(str) {\n  let h = 5381;\n  for (let i = 0; i < str.length; i++) { h = ((h << 5) + h + str.charCodeAt(i)) | 0; }\n  return (h >>> 0).toString(36);\n}\n\nfunction runQA(profile) {\n  state.mode = 'ceo';\n  state.qaMode = true;\n  state.respondent = { name: 'QA ' + String(profile).toUpperCase(), email: '', role: 'QA', company: 'QA Test Co', revenue: '20-50m', industry: 'technology', size: '101-300' };\n  if (profile === 'low') {\n    state.answers = Array(25).fill(1).concat(Array(10).fill(0));\n  } else if (profile === 'high') {\n    state.answers = Array(25).fill(5).concat(Array(10).fill(2));\n  } else {\n    const cf = []; for (let i = 0; i < 25; i++) cf.push(i % 2 ? 5 : 1);\n    const dr = []; for (let i = 0; i < 10; i++) dr.push(i % 3);\n    state.answers = cf.concat(dr);\n  }\n  showResults();\n}\n\n\/\/ ===== UTILITIES =====\n\/\/ ===== UTILITIES =====\nfunction getStore() {\n  try {\n    const data = localStorage.getItem('ris_v2_data');\n    return data ? JSON.parse(data) : { results: [], sessions: [] };\n  } catch (e) {\n    return { results: [], sessions: [] };\n  }\n}\n\nfunction saveStore(data) {\n  try {\n    localStorage.setItem('ris_v2_data', JSON.stringify(data));\n  } catch (e) {\n    console.error('Storage error', e);\n  }\n}\n\nfunction generateSessionId() {\n  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';\n  let id = 'RIS-';\n  for (let i = 0; i < 12; i++) {\n    id += chars.charAt(Math.floor(Math.random() * chars.length));\n  }\n  return id;\n}\n\nfunction showToast(message, type = 'success') {\n  const container = document.getElementById('toastContainer');\n  const icon = type === 'success' ? '\u2713' : '\u26a0';\n  const toast = document.createElement('div');\n  toast.className = `toast ${type}`;\n  toast.innerHTML = `<span class=\"toast-icon\">${icon}<\/span><span>${message}<\/span>`;\n  container.appendChild(toast);\n  setTimeout(() => {\n    toast.style.animation = 'slideInRight 0.3s ease-out reverse';\n    setTimeout(() => toast.remove(), 300);\n  }, 3500);\n}\n\nfunction closeModal() {\n  document.getElementById('detailModal').classList.remove('active');\n}\n\n\/\/ ===== ROUTING & TAB MANAGEMENT =====\nfunction switchTab(tabName) {\n  document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));\n  document.querySelector(`[data-tab=\"${tabName}\"]`).classList.add('active');\n  document.querySelectorAll('#app .screen').forEach(s => s.classList.remove('active'));\n\n  if (tabName === 'ceo') {\n    document.getElementById('ceoScreen').classList.add('active');\n  } else if (tabName === 'team') {\n    document.getElementById('teamScreen').classList.add('active');\n    checkTeamSession();\n  } else if (tabName === 'admin') {\n    if (state.isAdminLoggedIn) {\n      renderAdminDashboard();\n    } else {\n      showAdminLogin();\n    }\n  }\n}\n\nfunction showLanding() {\n  document.getElementById('landingScreen').style.display = 'flex';\n  document.getElementById('app').classList.remove('active');\n  document.getElementById('surveyContainer').style.display = 'none';\n  document.getElementById('resultsContainer').style.display = 'none';\n  document.getElementById('adminLoginContainer').style.display = 'none';\n  document.getElementById('adminDashboardContainer').style.display = 'none';\n}\n\nfunction showApp() {\n  document.getElementById('landingScreen').style.display = 'none';\n  document.getElementById('app').classList.add('active');\n  document.getElementById('surveyContainer').style.display = 'none';\n  document.getElementById('resultsContainer').style.display = 'none';\n  document.getElementById('adminLoginContainer').style.display = 'none';\n  document.getElementById('adminDashboardContainer').style.display = 'none';\n}\n\nfunction showSurvey() {\n  document.getElementById('landingScreen').style.display = 'none';\n  document.getElementById('app').classList.remove('active');\n  document.getElementById('surveyContainer').style.display = 'flex';\n  document.getElementById('resultsContainer').style.display = 'none';\n  document.getElementById('adminLoginContainer').style.display = 'none';\n  document.getElementById('adminDashboardContainer').style.display = 'none';\n  renderQuestion();\n}\n\nfunction showResults() {\n  document.getElementById('landingScreen').style.display = 'none';\n  document.getElementById('app').classList.remove('active');\n  document.getElementById('surveyContainer').style.display = 'none';\n  document.getElementById('resultsContainer').style.display = 'flex';\n  document.getElementById('adminLoginContainer').style.display = 'none';\n  document.getElementById('adminDashboardContainer').style.display = 'none';\n  renderResults();\n}\n\nfunction showAdminLogin() {\n  document.getElementById('landingScreen').style.display = 'none';\n  document.getElementById('app').classList.remove('active');\n  document.getElementById('surveyContainer').style.display = 'none';\n  document.getElementById('resultsContainer').style.display = 'none';\n  document.getElementById('adminLoginContainer').style.display = 'flex';\n  document.getElementById('adminDashboardContainer').style.display = 'none';\n}\n\nfunction showGapReport(key) {\n  document.getElementById('landingScreen').style.display = 'none';\n  document.getElementById('app').classList.remove('active');\n  document.getElementById('surveyContainer').style.display = 'none';\n  document.getElementById('resultsContainer').style.display = 'none';\n  document.getElementById('adminLoginContainer').style.display = 'none';\n  document.getElementById('adminDashboardContainer').style.display = 'none';\n  document.getElementById('gapReportContainer').style.display = 'flex';\n  renderGapReport(key);\n  window.scrollTo(0, 0);\n}\n\nfunction backToAdmin() {\n  document.getElementById('gapReportContainer').style.display = 'none';\n  showAdminDashboard();\n  renderAdminDashboard();\n}\n\nfunction showAdminDashboard() {\n  document.getElementById('gapReportContainer').style.display = 'none';\n  document.getElementById('landingScreen').style.display = 'none';\n  document.getElementById('app').classList.remove('active');\n  document.getElementById('surveyContainer').style.display = 'none';\n  document.getElementById('resultsContainer').style.display = 'none';\n  document.getElementById('adminLoginContainer').style.display = 'none';\n  document.getElementById('adminDashboardContainer').style.display = 'flex';\n}\n\n\/\/ ===== CEO DIAGNOSTIC FLOW =====\nfunction startCEODiagnostic() {\n  const form = document.getElementById('ceoIntakeForm');\n  if (!form.checkValidity()) {\n    form.reportValidity();\n    return;\n  }\n\n  state.mode = 'ceo';\n  state.respondent = {\n    name: document.getElementById('ceoName').value,\n    email: document.getElementById('ceoEmail').value,\n    role: document.getElementById('ceoRole').value,\n    company: document.getElementById('ceoCompany').value,\n    revenue: document.getElementById('ceoRevenue').value,\n    industry: document.getElementById('ceoIndustry').value,\n    size: document.getElementById('ceoEmployees').value\n  };\n  state.currentQuestion = 0;\n  state.answers = new Array(35).fill(null);\n  showSurvey();\n}\n\n\/\/ ===== TEAM SURVEY FLOW =====\nfunction checkTeamSession() {\n  const params = new URLSearchParams(window.location.search);\n  const sessionId = params.get('session');\n  const company = params.get('company');\n  const leader = params.get('leader');\n  const exp = params.get('exp');\n  const sig = params.get('sig');\n\n  if (!sessionId || !company) return;\n\n  let valid = false;\n  if (exp && sig) {\n    \/\/ Signed portable link \u2014 works on any device, no local storage required.\n    const expected = simpleSig(sessionId + '|' + exp + '|' + SIG_SALT);\n    valid = (sig === expected) && (Date.now() < parseInt(exp, 10));\n  } else {\n    \/\/ Legacy links: fall back to local session store (same-device only).\n    const store = getStore();\n    const session = store.sessions.find(s => s.id === sessionId);\n    valid = !!(session && new Date(session.expiresAt) > new Date());\n  }\n\n  const statusEl = document.getElementById('sessionStatus');\n  if (valid) {\n    statusEl.style.display = 'block';\n    document.getElementById('teamCompany').value = decodeURIComponent(company);\n    document.getElementById('startTeamBtn').disabled = false;\n    state.session = { id: sessionId, company: decodeURIComponent(company), leaderName: leader ? decodeURIComponent(leader) : '' };\n  } else {\n    statusEl.style.display = 'block';\n    statusEl.innerHTML = '<div style=\"color: #dc4a39; font-weight: 600;\">\u23f0 This session link has expired or is invalid. Ask your leader for a fresh link.<\/div>';\n    document.getElementById('startTeamBtn').disabled = true;\n  }\n}\n\nfunction startTeamDiagnostic() {\n  const role = document.getElementById('teamRole').value.trim();\n  if (!role) {\n    showToast('Please enter your role', 'error');\n    return;\n  }\n\n  const teamEmail = document.getElementById('teamEmail').value.trim();\n  if (!teamEmail || !teamEmail.includes('@')) {\n    showToast('Please enter a valid email', 'error');\n    return;\n  }\n\n  state.mode = 'team';\n  state.respondent = {\n    name: 'Team Member',\n    email: teamEmail,\n    role: role,\n    company: document.getElementById('teamCompany').value\n  };\n  state.currentQuestion = 0;\n  state.answers = new Array(35).fill(null);\n  showSurvey();\n}\n\n\/\/ ===== SURVEY RENDERING & LOGIC =====\nfunction getAllQuestions() {\n  if (state.mode === 'team') return [...TEAM_CF_QUESTIONS, ...TEAM_DRAG_QUESTIONS];\n  return [...CF_QUESTIONS, ...DRAG_QUESTIONS];\n}\n\nfunction isPartOne(questionIndex) {\n  return questionIndex < 25;\n}\n\nfunction renderQuestion() {\n  const allQuestions = getAllQuestions();\n  const q = allQuestions[state.currentQuestion];\n  const isScale = isPartOne(state.currentQuestion);\n\n  const part = isScale ? 'Part 1 \u00b7 Cultural Friction' : 'Part 2 \u00b7 CEO Drag';\n  const qNum = isScale ? (state.currentQuestion + 1) : (state.currentQuestion - 24);\n  const qTotal = isScale ? 25 : 10;\n\n  document.getElementById('progressLabel').innerHTML = `${part} \u2014 Question ${qNum} of ${qTotal}`;\n  document.getElementById('zonePill').textContent = q.zone || 'CEO Drag';\n  document.getElementById('zonePill').className = isScale ? 'zone-pill cf' : 'zone-pill drag';\n  document.getElementById('questionCounter').textContent = `Question ${state.currentQuestion + 1} of 35`;\n  document.getElementById('questionText').innerHTML = q.text;\n\n  const progress = ((state.currentQuestion + 1) \/ 35) * 100;\n  document.getElementById('progressFill').style.width = progress + '%';\n\n  const answerGrid = document.getElementById('answerGrid');\n  answerGrid.innerHTML = '';\n\n  if (isScale) {\n    const scaleButtons = document.createElement('div');\n    scaleButtons.className = 'scale-buttons';\n    for (let i = 1; i <= 5; i++) {\n      const btn = document.createElement('button');\n      btn.type = 'button';\n      btn.className = `btn btn-circle ${state.answers[state.currentQuestion] === i ? 'btn-primary' : 'btn-secondary'}`;\n      btn.textContent = i;\n      btn.onclick = () => selectScale(i);\n      scaleButtons.appendChild(btn);\n    }\n    answerGrid.appendChild(scaleButtons);\n\n    const labels = document.createElement('div');\n    labels.style.display = 'flex';\n    labels.style.justifyContent = 'space-between';\n    labels.style.marginTop = '12px';\n    labels.innerHTML = `\n      <span class=\"scale-label left\">1 = Strongly Agree \u2014 true of us<\/span>\n      <span class=\"scale-label center\">3 = Neutral<\/span>\n      <span class=\"scale-label right\">5 = Strongly Disagree \u2014 not true of us<\/span>\n    `;\n    answerGrid.appendChild(labels);\n  } else {\n    const optionBtns = document.createElement('div');\n    optionBtns.className = 'option-buttons';\n    q.options.forEach((opt, idx) => {\n      const btn = document.createElement('button');\n      btn.type = 'button';\n      btn.className = `option-btn ${state.answers[state.currentQuestion] === idx ? 'selected' : ''}`;\n      btn.innerHTML = `<span class=\"option-radio\"><\/span><span>${opt.text}<\/span>`;\n      btn.onclick = () => selectOption(idx);\n      optionBtns.appendChild(btn);\n    });\n    answerGrid.appendChild(optionBtns);\n  }\n\n  document.getElementById('backBtn').style.display = state.currentQuestion === 0 ? 'none' : 'block';\n  const nextBtn = document.getElementById('nextBtn');\n  nextBtn.textContent = state.currentQuestion === 34 ? 'Generate My Report \u2192' : 'Next \u2192';\n  nextBtn.disabled = state.answers[state.currentQuestion] === null;\n}\n\nfunction selectScale(value) {\n  state.answers[state.currentQuestion] = value;\n  document.getElementById('nextBtn').disabled = false;\n\n  setTimeout(() => {\n    nextQuestion();\n  }, 320);\n}\n\nfunction selectOption(index) {\n  state.answers[state.currentQuestion] = index;\n  document.getElementById('nextBtn').disabled = false;\n  renderQuestion();\n}\n\nfunction nextQuestion() {\n  if (state.currentQuestion < 34) {\n    state.currentQuestion++;\n    renderQuestion();\n  } else {\n    showResults();\n  }\n}\n\nfunction previousQuestion() {\n  if (state.currentQuestion > 0) {\n    state.currentQuestion--;\n    renderQuestion();\n  }\n}\n\n\/\/ ===== SCORING =====\nfunction calculateScores() {\n  const qSet = state.mode === 'team' ? TEAM_CF_QUESTIONS : CF_QUESTIONS;\n  const dSet = state.mode === 'team' ? TEAM_DRAG_QUESTIONS : DRAG_QUESTIONS;\n\n  const cfRaw = state.answers.slice(0, 25);\n  \/\/ Reverse-keyed items: agreement means friction, so the scale inverts (6 - answer).\n  const cfAnswers = cfRaw.map((a, i) => (a === null || a === undefined) ? 3 : (qSet[i].reverse ? 6 - a : a));\n  const cfTotal = cfAnswers.reduce((sum, a) => sum + a, 0);\n\n  const zones = [\n    { name: 'Alignment', indices: [0, 1, 2, 3, 4] },\n    { name: 'Decision', indices: [5, 6, 7, 8, 9] },\n    { name: 'Accountability', indices: [10, 11, 12, 13, 14] },\n    { name: 'Talent', indices: [15, 16, 17, 18, 19] },\n    { name: 'Culture', indices: [20, 21, 22, 23, 24] }\n  ];\n\n  const zoneScores = {};\n  zones.forEach(z => {\n    zoneScores[z.name.toLowerCase()] = z.indices.reduce((sum, i) => sum + (cfAnswers[i] || 0), 0);\n  });\n\n  const dragAnswers = state.answers.slice(25, 35);\n  let dragTotal = 0;\n  for (let i = 0; i < dragAnswers.length; i++) {\n    if (dragAnswers[i] !== null && dragAnswers[i] !== undefined) {\n      dragTotal += dSet[i].options[dragAnswers[i]].score;\n    }\n  }\n\n  return {\n    cf: { total: cfTotal, zoneScores: zoneScores },\n    drag: { total: dragTotal },\n    dragAnswers: dragAnswers\n  };\n}\n\nfunction getCFLevel(total) {\n  if (total <= 50) return { name: 'Friction-Free', color: 'green', summary: 'Your leadership culture is operating with exceptional alignment and courage. A rare result \u2014 protect and codify it.' };\n  if (total <= 75) return { name: 'Low Friction', color: 'green', summary: 'Strong alignment with manageable friction. Targeted improvements in your highest-scoring zones will compound over time.' };\n  if (total <= 95) return { name: 'Friction Zone', color: 'gold', summary: 'Noticeable cultural friction is quietly taxing execution. Leadership gaps in key zones need deliberate attention now.' };\n  if (total <= 110) return { name: 'Friction Tax', color: 'orange', summary: 'Cultural friction is actively draining growth capacity. The patterns are systemic \u2014 intervention required, not incremental improvement.' };\n  return { name: 'High Friction', color: 'red', summary: 'Critical leadership friction across multiple zones. Execution is compromised. This requires immediate, structured intervention.' };\n}\n\nfunction getDragLevel(total) {\n  if (total <= 4) return { name: 'Clear Leader', color: 'green', summary: 'You are operating with strong delegation and low personal drag. The company can run and grow without you as the bottleneck.' };\n  if (total <= 9) return { name: 'Friction Zone', color: 'gold', summary: 'Some personal operational drag is taxing your leadership capacity. Identifiable areas where you are still the constraint.' };\n  if (total <= 14) return { name: 'Bottleneck Risk', color: 'orange', summary: 'You are a meaningful constraint on company growth. Decision dependency, operational involvement, or both are limiting execution.' };\n  return { name: 'Full Drag', color: 'red', summary: 'The company is running you. Structural CEO dependency is actively capping scale. This requires decisive, immediate delegation work.' };\n}\n\nfunction getCombinedRead(cfLevel, dragLevel) {\n  \/\/ Severity ranks \\u2014 explicit, exhaustive matrix. No silent fallthrough.\n  var CF_RANK   = { 'Friction-Free': 0, 'Low Friction': 1, 'Friction Zone': 2, 'Friction Tax': 3, 'High Friction': 4 };\n  var DRAG_RANK = { 'Clear Leader': 0, 'Friction Zone': 1, 'Bottleneck Risk': 2, 'Full Drag': 3 };\n\n  var c = CF_RANK[cfLevel.name];\n  var d = DRAG_RANK[dragLevel.name];\n  if (c === undefined) c = 2;\n  if (d === undefined) d = 1;\n\n  var cHigh = c >= 3, cMid = c === 2, cLow = c <= 1;\n  var dHigh = d >= 2, dMid = d === 1, dLow = d === 0;\n\n  if (cHigh && dHigh) {\n    return 'Both readings are in the danger band. The culture is taxing execution and the CEO is a structural constraint at the same time \\u2014 which means neither can be fixed in isolation. Delegating into a culture this frictional simply moves the bottleneck; fixing the culture while decisions still route through one person will not hold. This needs sequenced structural work, starting with decision rights.';\n  }\n  if (cHigh && dMid) {\n    return 'The culture is carrying significant friction and you are still a partial constraint on it. The friction is now systemic rather than personal \\u2014 but your own operating habits are close enough to the problem that they will either accelerate the fix or quietly block it. Start with the two priority zones below, and watch how much of the work still routes back through you.';\n  }\n  if (cHigh && dLow) {\n    return 'You personally delegate well, but the organisation around you does not. That gap is informative: the discipline exists in you and has not been installed in the system. The opportunity is to codify what you already do instinctively \\u2014 decision rights, consequence standards, escalation rules \\u2014 so it survives without your presence enforcing it.';\n  }\n  if (cMid && dHigh) {\n    return 'The culture is workable; you are the tighter constraint. Your organisation has more capacity than it is being allowed to use, and the pattern points at concentration of decisions rather than a broken team. Freeing capable people from dependency is the single highest-leverage move available to you this quarter.';\n  }\n  if (cMid && dMid) {\n    return 'This is the most common and most under-treated pattern at your scale: real friction in specific zones, and a CEO who is a partial bottleneck. Nothing here is in crisis, which is exactly why it persists \\u2014 the cost is paid in speed and retention rather than in visible failure. Two disciplined 90-day moves would change the trajectory materially.';\n  }\n  if (cMid && dLow) {\n    return 'You are running clean personally, and the friction is concentrated in specific zones rather than across the whole system. That is a targeted problem, not a structural one. Treat the two priority zones below as a focused 90-day project rather than a transformation.';\n  }\n  if (cLow && dHigh) {\n    return 'The culture is relatively healthy \\u2014 and you are the constraint. That is a good problem, because it is the one most fully within your control. The organisation has the talent and the standards; what it does not have is permission. Freeing it from dependency on you is the highest-leverage move on this page.';\n  }\n  if (cLow && dMid) {\n    return 'A strong cultural foundation with some personal drag still present. You are close to the position most CEOs at your scale are trying to reach. The remaining work is narrow: identify the two or three categories of decision still routing through you unnecessarily and hand them over with explicit authority.';\n  }\n  return 'Both readings sit in the healthy band: the culture is functioning as an asset and you are not the bottleneck. That is a genuinely rare result and worth treating as fragile \\u2014 alignment and accountability decay silently under growth. Codify what is working now, while you still have the slack to do it.';\n}\n\n\n\/\/ ================================================================\n\/\/  PERCEPTION GAP ENGINE\n\/\/  The CEO's self-score vs the aggregated team score. This is the\n\/\/  only number in the system that is not self-report, so it is the\n\/\/  only one that cannot be talked around.\n\/\/  Higher score = more friction. delta = team - ceo.\n\/\/  Positive delta => the team sees MORE friction than the CEO does.\n\/\/ ================================================================\n\nvar GAP_ZONES = [\n  ['alignment',      [0, 1, 2, 3, 4]],\n  ['decision',       [5, 6, 7, 8, 9]],\n  ['accountability', [10, 11, 12, 13, 14]],\n  ['talent',         [15, 16, 17, 18, 19]],\n  ['culture',        [20, 21, 22, 23, 24]]\n];\n\nfunction normKey(s) {\n  return (s || '').toString().trim().toLowerCase().replace(\/\\s+\/g, ' ');\n}\n\nfunction gapAvg(arr) {\n  var v = arr.filter(function (x) { return x !== null && x !== undefined && !isNaN(x); });\n  return v.length ? v.reduce(function (a, b) { return a + b; }, 0) \/ v.length : null;\n}\n\nfunction gapRound(n, dp) {\n  if (n === null || n === undefined || isNaN(n)) return null;\n  var f = Math.pow(10, dp || 0);\n  return Math.round(n * f) \/ f;\n}\n\n\/\/ Re-score a stored result into per-item friction values, using the\n\/\/ question set that respondent actually saw (CEO voice or team voice).\nfunction itemScores(result) {\n  var isTeam = result.mode === 'team';\n  var qSet = isTeam ? TEAM_CF_QUESTIONS : CF_QUESTIONS;\n  var dSet = isTeam ? TEAM_DRAG_QUESTIONS : DRAG_QUESTIONS;\n  var ans = result.answers || [];\n  var cf = [], drag = [];\n  for (var i = 0; i < 25; i++) {\n    var a = ans[i];\n    if (a === null || a === undefined) a = 3;\n    cf.push(qSet[i] && qSet[i].reverse ? (6 - a) : a);\n  }\n  for (var j = 0; j < 10; j++) {\n    var idx = ans[25 + j];\n    if (idx === null || idx === undefined || !dSet[j] || !dSet[j].options[idx]) drag.push(null);\n    else drag.push(dSet[j].options[idx].score);\n  }\n  return { cf: cf, drag: drag };\n}\n\n\/\/ Group every stored result by company. Most recent CEO run wins.\nfunction gapGroups() {\n  var store = getStore();\n  var groups = {};\n  (store.results || []).forEach(function (r) {\n    if (!r || !r.respondent) return;\n    var key = normKey(r.respondent.company);\n    if (!key) return;\n    if (!groups[key]) groups[key] = { key: key, company: r.respondent.company, ceo: null, team: [] };\n    if (r.mode === 'ceo') {\n      if (!groups[key].ceo || new Date(r.timestamp) > new Date(groups[key].ceo.timestamp)) groups[key].ceo = r;\n    } else {\n      groups[key].team.push(r);\n    }\n  });\n  return groups;\n}\n\nfunction gapBand(delta, scale) {\n  \/\/ scale: 'zone' (\/25), 'cf' (\/125), 'drag' (\/20)\n  var t = scale === 'cf' ? [8, 20] : scale === 'drag' ? [2, 5] : [2, 5];\n  var a = Math.abs(delta);\n  if (a < t[0]) return { label: 'Shared View', tone: 'ok' };\n  if (delta > 0) return a < t[1] ? { label: 'Divergence', tone: 'warn' } : { label: 'Blind Spot', tone: 'bad' };\n  return a < t[1] ? { label: 'Divergence', tone: 'warn' } : { label: 'Over-Critical', tone: 'warn' };\n}\n\nfunction computeGap(group) {\n  if (!group || !group.ceo || !group.team.length) return null;\n  var c = itemScores(group.ceo);\n  var tItems = group.team.map(itemScores);\n  var n = group.team.length;\n\n  var cfItems = [];\n  for (var i = 0; i < 25; i++) {\n    (function (i) {\n      var t = gapAvg(tItems.map(function (x) { return x.cf[i]; }));\n      cfItems.push({\n        i: i, zone: CF_QUESTIONS[i].zone, ceo: c.cf[i], team: t,\n        delta: (t === null ? null : t - c.cf[i]),\n        ceoText: CF_QUESTIONS[i].text, teamText: TEAM_CF_QUESTIONS[i].text\n      });\n    })(i);\n  }\n\n  var dragItems = [];\n  for (var j = 0; j < 10; j++) {\n    (function (j) {\n      var t = gapAvg(tItems.map(function (x) { return x.drag[j]; }));\n      var ceoV = c.drag[j];\n      dragItems.push({\n        i: j, ceo: ceoV, team: t,\n        delta: (t === null || ceoV === null) ? null : t - ceoV,\n        ceoText: DRAG_QUESTIONS[j].text, teamText: TEAM_DRAG_QUESTIONS[j].text\n      });\n    })(j);\n  }\n\n  var zones = GAP_ZONES.map(function (z) {\n    var key = z[0], idx = z[1];\n    var ceoZ = idx.reduce(function (s, i) { return s + c.cf[i]; }, 0);\n    var teamZ = gapAvg(tItems.map(function (x) {\n      return idx.reduce(function (s, i) { return s + x.cf[i]; }, 0);\n    }));\n    return { key: key, label: ZONE_LABELS[key], ceo: ceoZ, team: teamZ, delta: (teamZ === null ? null : teamZ - ceoZ) };\n  });\n\n  var cfCeo = c.cf.reduce(function (a, b) { return a + b; }, 0);\n  var cfTeam = gapAvg(tItems.map(function (x) { return x.cf.reduce(function (a, b) { return a + b; }, 0); }));\n  var dgCeo = c.drag.reduce(function (a, b) { return a + (b || 0); }, 0);\n  var dgTeam = gapAvg(tItems.map(function (x) { return x.drag.reduce(function (a, b) { return a + (b || 0); }, 0); }));\n\n  var ranked = zones.slice().filter(function (z) { return z.delta !== null; })\n                    .sort(function (a, b) { return b.delta - a.delta; });\n  var itemRanked = cfItems.slice().filter(function (x) { return x.delta !== null; })\n                          .sort(function (a, b) { return b.delta - a.delta; });\n  var dragRanked = dragItems.slice().filter(function (x) { return x.delta !== null; })\n                            .sort(function (a, b) { return b.delta - a.delta; });\n\n  return {\n    company: group.company, n: n, key: group.key,\n    ceoResult: group.ceo,\n    cf: { ceo: cfCeo, team: cfTeam, delta: (cfTeam === null ? null : cfTeam - cfCeo) },\n    drag: { ceo: dgCeo, team: dgTeam, delta: (dgTeam === null ? null : dgTeam - dgCeo) },\n    zones: zones, zonesRanked: ranked,\n    cfItems: cfItems, itemsRanked: itemRanked,\n    dragItems: dragItems, dragRanked: dragRanked\n  };\n}\n\nfunction gapHeadline(g) {\n  var d = g.cf.delta, dd = g.drag.delta;\n  var cfBand = gapBand(d, 'cf'), dgBand = gapBand(dd, 'drag');\n  if (cfBand.tone === 'bad' || dgBand.tone === 'bad') {\n    return {\n      title: 'Perception Gap: Blind Spot Confirmed',\n      body: 'Your senior team is reporting materially more friction than you are. This is the finding that matters most in the whole suite, because it is the one you cannot argue with from the inside. The people closest to the work are describing a different company than the one you described &mdash; and they are describing it without knowing what you said. Where the two reads diverge is not a disagreement to be settled. It is a list of the things nobody has been telling you.'\n    };\n  }\n  if (cfBand.tone === 'warn' || dgBand.tone === 'warn') {\n    if (d < 0 || dd < 0) {\n      return {\n        title: 'Perception Gap: You Are Harder On Yourself Than They Are',\n        body: 'Your team rates this company more favourably than you rate it yourself. That is rarer than the reverse and worth reading carefully. It can mean genuine standards held higher at the top &mdash; or it can mean a team that is not yet safe enough to say the harder thing, even anonymously. The zone table below will tell you which: real confidence shows up as consistent agreement across zones, while caution shows up as everything clustering near the middle.'\n      };\n    }\n    return {\n      title: 'Perception Gap: Divergence in Specific Zones',\n      body: 'The headline reads are broadly consistent, but specific zones diverge enough to matter. This is the most actionable pattern in the set: you are not systematically blind, you have two or three particular places where what you believe is happening and what your team experiences are not the same thing. Those are targeted, fixable conversations &mdash; and the zone table names them.'\n    };\n  }\n  return {\n    title: 'Perception Gap: Aligned Read',\n    body: 'Your read and your team\u2019s read are materially the same. That is a genuinely good result and rarer than most CEOs assume &mdash; it means the information reaching you is largely intact, which is the precondition for every other kind of improvement. Treat it as perishable. Alignment of perception decays fastest exactly when a business is growing quickly.'\n  };\n}\n\nfunction gapTone(tone) {\n  return tone === 'bad' ? '#dc4a39' : tone === 'warn' ? 'var(--accent-gold)' : '#4caf50';\n}\n\nfunction gapArrow(delta) {\n  if (delta === null) return '&mdash;';\n  var s = (delta > 0 ? '+' : '') + gapRound(delta, 1);\n  return s;\n}\n\n\/\/ ---- Admin table -------------------------------------------------\nfunction renderGapTable() {\n  var el = document.getElementById('gapTableContainer');\n  if (!el) return;\n  var groups = gapGroups();\n  var keys = Object.keys(groups);\n  if (!keys.length) {\n    el.innerHTML = '<p style=\"color: var(--text-muted); text-align: center; padding: 40px 20px;\">No results yet.<\/p>';\n    return;\n  }\n  var rows = '';\n  keys.forEach(function (k) {\n    var grp = groups[k];\n    var ready = grp.ceo && grp.team.length;\n    var g = ready ? computeGap(grp) : null;\n    var status, action, cfCell, dgCell;\n    if (!grp.ceo) {\n      status = '<span class=\"badge badge-expired\">Awaiting CEO<\/span>';\n      action = '<span style=\"color:var(--text-muted);font-size:12px;\">' + grp.team.length + ' team response(s)<\/span>';\n      cfCell = '&mdash;'; dgCell = '&mdash;';\n    } else if (!grp.team.length) {\n      status = '<span class=\"badge badge-expired\">Awaiting Team<\/span>';\n      action = '<span style=\"color:var(--text-muted);font-size:12px;\">Send the team link<\/span>';\n      cfCell = grp.ceo.cf.total + ' <span style=\"color:var(--text-muted);\">(CEO)<\/span>'; dgCell = grp.ceo.drag.total;\n    } else {\n      var b = gapBand(g.cf.delta, 'cf');\n      status = '<span class=\"badge\" style=\"color:' + gapTone(b.tone) + ';border-color:' + gapTone(b.tone) + ';\">' + b.label + '<\/span>';\n      action = '<button class=\"btn btn-secondary action-btn\" onclick=\"showGapReport(\\'' + k.replace(\/'\/g, \"\\\\'\") + '\\')\">View Gap Report<\/button>';\n      cfCell = g.cf.ceo + ' &rarr; ' + gapRound(g.cf.team, 1) + ' <strong style=\"color:' + gapTone(b.tone) + ';\">(' + gapArrow(g.cf.delta) + ')<\/strong>';\n      var bd = gapBand(g.drag.delta, 'drag');\n      dgCell = g.drag.ceo + ' &rarr; ' + gapRound(g.drag.team, 1) + ' <strong style=\"color:' + gapTone(bd.tone) + ';\">(' + gapArrow(g.drag.delta) + ')<\/strong>';\n    }\n    rows += '<tr><td>' + grp.company + '<\/td><td>' + (grp.team.length || 0) + '<\/td><td>' + cfCell + '<\/td><td>' + dgCell + '<\/td><td>' + status + '<\/td><td>' + action + '<\/td><\/tr>';\n  });\n  el.innerHTML = '<table><thead><tr><th>Company<\/th><th>Team n<\/th><th>Culture: CEO &rarr; Team<\/th><th>Drag: CEO &rarr; Team<\/th><th>Read<\/th><th>Actions<\/th><\/tr><\/thead><tbody>' + rows + '<\/tbody><\/table>';\n}\n\n\/\/ ---- Full gap report ---------------------------------------------\nfunction renderGapReport(key) {\n  var groups = gapGroups();\n  var grp = groups[key];\n  var head = document.getElementById('gapReportHeader');\n  var content = document.getElementById('gapReportContent');\n  content.innerHTML = '';\n\n  var g = computeGap(grp);\n  if (!g) {\n    head.innerHTML = '<h1 class=\"results-title\">Perception Gap Report<\/h1>';\n    content.innerHTML = '<div class=\"results-section\"><div class=\"score-card\"><p>Not enough data. A gap report needs one CEO diagnostic and at least one team response for this company.<\/p><button class=\"btn btn-secondary\" onclick=\"backToAdmin()\">&larr; Back to Admin<\/button><\/div><\/div>';\n    return;\n  }\n\n  var hl = gapHeadline(g);\n  var cfB = gapBand(g.cf.delta, 'cf');\n  var dgB = gapBand(g.drag.delta, 'drag');\n\n  head.innerHTML =\n    '<h1 class=\"results-title\">Leadership Perception Gap<\/h1>' +\n    '<div class=\"results-subtitle\">' + g.company + '<\/div>' +\n    '<div class=\"results-meta\"><span>' + new Date().toLocaleDateString() + '<\/span><span>CEO self-report vs ' + g.n + ' team response' + (g.n === 1 ? '' : 's') + '<\/span><\/div>';\n\n  \/\/ 1. Executive summary\n  var s1 = document.createElement('div');\n  s1.className = 'results-section';\n  s1.innerHTML =\n    '<div class=\"score-card\" style=\"text-align:left;\">' +\n      '<div style=\"font-size:11px;letter-spacing:2px;text-transform:uppercase;color:var(--text-muted);margin-bottom:10px;\">Executive Summary<\/div>' +\n      '<h3 style=\"margin-bottom:18px;line-height:1.35;\">' + hl.title + '<\/h3>' +\n      '<div style=\"display:flex;gap:14px;flex-wrap:wrap;margin-bottom:22px;\">' +\n        '<div style=\"flex:1;min-width:190px;background:var(--bg-primary);border:1px solid var(--border-light);border-radius:12px;padding:14px 16px;\">' +\n          '<div style=\"font-size:11px;letter-spacing:1.5px;text-transform:uppercase;color:var(--text-muted);\">Cultural Friction \/125<\/div>' +\n          '<div style=\"font-size:24px;font-weight:700;line-height:1.25;margin-top:6px;color:var(--text-primary);\">' + g.cf.ceo + ' <span style=\"color:var(--text-muted);font-size:16px;\">CEO<\/span> &rarr; ' + gapRound(g.cf.team, 1) + ' <span style=\"color:var(--text-muted);font-size:16px;\">team<\/span><\/div>' +\n          '<div style=\"font-size:15px;font-weight:700;margin-top:4px;color:' + gapTone(cfB.tone) + ';\">' + gapArrow(g.cf.delta) + ' &middot; ' + cfB.label + '<\/div>' +\n        '<\/div>' +\n        '<div style=\"flex:1;min-width:190px;background:var(--bg-primary);border:1px solid var(--border-light);border-radius:12px;padding:14px 16px;\">' +\n          '<div style=\"font-size:11px;letter-spacing:1.5px;text-transform:uppercase;color:var(--text-muted);\">CEO Drag \/20<\/div>' +\n          '<div style=\"font-size:24px;font-weight:700;line-height:1.25;margin-top:6px;color:var(--text-primary);\">' + g.drag.ceo + ' <span style=\"color:var(--text-muted);font-size:16px;\">CEO<\/span> &rarr; ' + gapRound(g.drag.team, 1) + ' <span style=\"color:var(--text-muted);font-size:16px;\">team<\/span><\/div>' +\n          '<div style=\"font-size:15px;font-weight:700;margin-top:4px;color:' + gapTone(dgB.tone) + ';\">' + gapArrow(g.drag.delta) + ' &middot; ' + dgB.label + '<\/div>' +\n        '<\/div>' +\n      '<\/div>' +\n      '<p style=\"line-height:1.85;color:var(--text-muted);margin:0;\">' + hl.body + '<\/p>' +\n      (g.n < 3 ? '<div style=\"margin-top:18px;background:rgba(201,168,76,0.08);border:1px solid rgba(201,168,76,0.35);border-radius:12px;padding:14px 16px;\"><div style=\"font-size:11px;letter-spacing:2px;text-transform:uppercase;color:var(--accent-gold);margin-bottom:6px;\">Sample Caution<\/div><p style=\"margin:0;line-height:1.8;font-size:14px;color:var(--text-primary);\">This gap is built on ' + g.n + ' team response' + (g.n === 1 ? '' : 's') + '. Treat it as a signal to investigate, not a measurement. Three to five responses is the point at which this stops being one person\u2019s view and starts being the team\u2019s.<\/p><\/div>' : '') +\n    '<\/div>';\n  content.appendChild(s1);\n\n  \/\/ 2. Zone table\n  var zoneRows = '';\n  g.zones.forEach(function (z) {\n    var b = gapBand(z.delta === null ? 0 : z.delta, 'zone');\n    zoneRows +=\n      '<tr>' +\n        '<td><strong>' + z.label + '<\/strong><\/td>' +\n        '<td>' + z.ceo + '\/25<\/td>' +\n        '<td>' + (z.team === null ? '&mdash;' : gapRound(z.team, 1) + '\/25') + '<\/td>' +\n        '<td style=\"color:' + gapTone(b.tone) + ';font-weight:700;\">' + gapArrow(z.delta) + '<\/td>' +\n        '<td><span class=\"badge\" style=\"color:' + gapTone(b.tone) + ';border-color:' + gapTone(b.tone) + ';\">' + b.label + '<\/span><\/td>' +\n      '<\/tr>';\n  });\n  var s2 = document.createElement('div');\n  s2.className = 'results-section';\n  s2.innerHTML =\n    '<div class=\"score-card\" style=\"text-align:left;\">' +\n      '<h3 style=\"margin-bottom:8px;\">Zone by Zone<\/h3>' +\n      '<p style=\"color:var(--text-muted);font-size:14px;line-height:1.7;margin-bottom:18px;\">Higher is more friction. A positive gap means your team reports more friction in that zone than you do &mdash; that is the direction that matters.<\/p>' +\n      '<div class=\"table-container\"><table><thead><tr><th>Zone<\/th><th>CEO<\/th><th>Team avg<\/th><th>Gap<\/th><th>Read<\/th><\/tr><\/thead><tbody>' + zoneRows + '<\/tbody><\/table><\/div>' +\n    '<\/div>';\n  content.appendChild(s2);\n\n  \/\/ 3. Widest gaps, question level\n  \/\/ Spread the top divergences across zones so one zone cannot fill the list.\n  var seenZone = {}, top = [];\n  g.itemsRanked.forEach(function (x) {\n    if (x.delta <= 0.4 || top.length >= 4) return;\n    var c = seenZone[x.zone] || 0;\n    if (c >= 2) return;\n    seenZone[x.zone] = c + 1;\n    top.push(x);\n  });\n  var topDrag = g.dragRanked.slice(0, 3).filter(function (x) { return x.delta > 0.25; });\n  var body = '';\n  if (top.length) {\n    body += '<h4 style=\"margin:0 0 12px;\">Culture &mdash; where you and your team disagree most<\/h4>';\n    top.forEach(function (x) {\n      body +=\n        '<div style=\"margin-bottom:16px;padding-left:16px;border-left:3px solid ' + gapTone(gapBand(x.delta, 'zone').tone) + ';\">' +\n          '<div style=\"font-size:11px;letter-spacing:1.5px;text-transform:uppercase;color:var(--text-muted);margin-bottom:4px;\">' + x.zone + ' &middot; gap ' + gapArrow(x.delta) + '<\/div>' +\n          '<p style=\"margin:0 0 4px;line-height:1.7;color:var(--text-primary);font-size:14px;\">' + x.ceoText + '<\/p>' +\n          '<p style=\"margin:0;line-height:1.7;color:var(--text-muted);font-size:13px;\">You scored ' + x.ceo + '\/5 friction here. Your team averaged ' + gapRound(x.team, 1) + '\/5.<\/p>' +\n        '<\/div>';\n    });\n  }\n  if (topDrag.length) {\n    body += '<h4 style=\"margin:22px 0 12px;\">Dependency &mdash; where their view of you differs from your own<\/h4>';\n    topDrag.forEach(function (x) {\n      body +=\n        '<div style=\"margin-bottom:16px;padding-left:16px;border-left:3px solid ' + gapTone(gapBand(x.delta * 2.5, 'zone').tone) + ';\">' +\n          '<div style=\"font-size:11px;letter-spacing:1.5px;text-transform:uppercase;color:var(--text-muted);margin-bottom:4px;\">CEO Drag &middot; gap ' + gapArrow(x.delta) + '<\/div>' +\n          '<p style=\"margin:0 0 4px;line-height:1.7;color:var(--text-primary);font-size:14px;\">' + x.ceoText + '<\/p>' +\n          '<p style=\"margin:0;line-height:1.7;color:var(--text-muted);font-size:13px;\">You scored ' + x.ceo + '\/2. Your team averaged ' + gapRound(x.team, 1) + '\/2.<\/p>' +\n        '<\/div>';\n    });\n  }\n  if (!body) {\n    body = '<p style=\"color:var(--text-muted);line-height:1.8;margin:0;\">No individual item shows a material gap. Your team\u2019s read of specific behaviours tracks your own closely &mdash; which is the strongest single indicator in this report that information is reaching you intact.<\/p>';\n  }\n  var s3 = document.createElement('div');\n  s3.className = 'results-section';\n  s3.innerHTML = '<div class=\"score-card\" style=\"text-align:left;\"><h3 style=\"margin-bottom:18px;\">The Sharpest Divergences<\/h3>' + body + '<\/div>';\n  content.appendChild(s3);\n\n  \/\/ 4. What to do\n  var worst = g.zonesRanked[0];\n  var s4 = document.createElement('div');\n  s4.className = 'results-section';\n  s4.innerHTML =\n    '<div class=\"score-card\" style=\"text-align:left;\">' +\n      '<h3 style=\"margin-bottom:16px;\">How To Use This In The Room<\/h3>' +\n      '<p style=\"line-height:1.85;color:var(--text-muted);margin-bottom:14px;\">Do not present this as a verdict. Present it as two honest readings that do not match, and make the mismatch the agenda. The wrong move is to defend the gap; the right move is to get curious about it in front of the people who produced it.<\/p>' +\n      (worst && worst.delta > 1 ?\n        '<div style=\"border-left:3px solid var(--accent-gold);padding-left:16px;margin-bottom:14px;\"><div style=\"font-size:11px;letter-spacing:2px;text-transform:uppercase;color:var(--text-muted);margin-bottom:6px;\">Start here<\/div><p style=\"margin:0;line-height:1.8;color:var(--text-primary);\"><strong>' + worst.label + '<\/strong> carries the widest gap (' + gapArrow(worst.delta) + '). Open the conversation there. One question, asked once, and then silence long enough to be uncomfortable: <em>&ldquo;The data says you all experience this differently than I do. I want to understand that, not defend it. What am I not seeing?&rdquo;<\/em><\/p><\/div>' : '') +\n      '<p style=\"line-height:1.85;color:var(--text-muted);margin:0;\">Then commit to one visible change inside fourteen days and name it publicly as coming from this exercise. A gap surfaced and not acted on is worse than a gap never measured &mdash; it teaches the team that candour is collected and ignored, and you will not get an honest answer from them a second time.<\/p>' +\n    '<\/div>';\n  content.appendChild(s4);\n\n  \/\/ 5. Method \/ confidentiality\n  var s5 = document.createElement('div');\n  s5.className = 'results-section';\n  s5.innerHTML =\n    '<div class=\"score-card\" style=\"text-align:left;\">' +\n      '<div style=\"font-size:11px;letter-spacing:2px;text-transform:uppercase;color:var(--text-muted);margin-bottom:10px;\">Method &amp; Confidentiality<\/div>' +\n      '<p style=\"line-height:1.85;color:var(--text-muted);font-size:14px;margin-bottom:12px;\">Team responses are aggregated and reported as averages only. No individual response, name, role, or email appears in this report, and none should ever be shared &mdash; the value of this instrument depends entirely on the team believing that.<\/p>' +\n      '<p style=\"line-height:1.85;color:var(--text-muted);font-size:14px;margin-bottom:12px;\">CEO and team answer parallel versions of the same 35 items, worded from their own seat, scored in the same direction. Reverse-keyed items are inverted before comparison, so both sides are measured on one friction scale. Gap = team average minus CEO score.<\/p>' +\n      '<p style=\"line-height:1.85;color:var(--text-muted);font-size:14px;margin:0;\">Thresholds: culture totals &mdash; under 8 shared view, 8 to 19 divergence, 20 or more a blind spot. Zones &mdash; under 2, 2 to 4, 5 or more. Drag &mdash; under 2, 2 to 4, 5 or more. These are RISMETHOD working thresholds calibrated to the scale of the instrument, not published norms.<\/p>' +\n      '<div style=\"margin-top:20px;display:flex;gap:10px;flex-wrap:wrap;\">' +\n        '<button class=\"btn btn-secondary\" onclick=\"window.print()\">Print \/ Save as PDF<\/button>' +\n        '<button class=\"btn btn-secondary\" onclick=\"backToAdmin()\">&larr; Back to Admin<\/button>' +\n      '<\/div>' +\n    '<\/div>';\n  content.appendChild(s5);\n}\n\n\/\/ ===== RESULTS RENDERING =====\nfunction renderResults() {\n  const scores = calculateScores();\n  const cfLevel = getCFLevel(scores.cf.total);\n  const dragLevel = getDragLevel(scores.drag.total);\n  const combinedRead = getCombinedRead(cfLevel, dragLevel);\n\n  const header = document.getElementById('resultsHeader');\n  header.innerHTML = `\n    <h1 class=\"results-title\">${state.respondent.name}'s Leadership Report<\/h1>\n    <div class=\"results-subtitle\">${state.respondent.company} \u00b7 ${state.respondent.role}<\/div>\n    <div class=\"results-meta\">\n      <span>${new Date().toLocaleDateString()}<\/span>\n      <span>${state.mode === 'ceo' ? 'CEO Diagnostic' : 'Team Survey'}<\/span>\n    <\/div>\n  `;\n\n  const content = document.getElementById('resultsContent');\n  content.innerHTML = '';\n\n  \/\/ ===== BOARD READOUT (executive summary) =====\n  const tax = state.mode === 'ceo' ? frictionTax(scores) : null;\n  const sortedZones = Object.entries(scores.cf.zoneScores).sort((a, b) => b[1] - a[1]);\n  const worstKey = sortedZones[0][0], worstVal = sortedZones[0][1];\n  const secondKey = sortedZones[1][0], secondVal = sortedZones[1][1];\n  const polishIdx = scores.dragAnswers && scores.dragAnswers[9];\n  const softened = (polishIdx === 1 || polishIdx === 2);\n\n  const verdict = (function () {\n    const c = scores.cf.total, d = scores.drag.total;\n    if (c > 95 && d > 9) return 'Board Readout: Structural Intervention Required';\n    if (c > 95) return 'Board Readout: The Business Is Paying a Friction Tax';\n    if (d > 9) return 'Board Readout: The CEO Is the Binding Constraint';\n    if (c > 75 || d > 4) return 'Board Readout: Measurable Drag, Not Yet Structural';\n    return 'Board Readout: Culture and Leadership Are Supporting Performance';\n  })();\n\n  const board = document.createElement('div');\n  board.className = 'results-section';\n  board.innerHTML = `\n    <div class=\"score-card\" style=\"text-align:left;\">\n      <div style=\"font-size:11px;letter-spacing:2px;text-transform:uppercase;color:var(--text-muted);margin-bottom:10px;\">Executive Summary<\/div>\n      <h3 style=\"margin-bottom:18px;line-height:1.35;\">${verdict}<\/h3>\n\n      <div style=\"display:flex;gap:14px;flex-wrap:wrap;margin-bottom:22px;\">\n        <div style=\"flex:1;min-width:150px;background:var(--bg-primary);border:1px solid var(--border-light);border-radius:12px;padding:14px 16px;\">\n          <div style=\"font-size:11px;letter-spacing:1.5px;text-transform:uppercase;color:var(--text-muted);\">Cultural Friction<\/div>\n          <div style=\"font-size:28px;font-weight:700;color:var(--accent-gold);line-height:1.2;margin-top:4px;\">${scores.cf.total}<span style=\"font-size:14px;color:var(--text-muted);font-weight:400;\">\/125<\/span><\/div>\n          <div style=\"font-size:13px;color:var(--text-primary);margin-top:2px;\">${cfLevel.name}<\/div>\n        <\/div>\n        <div style=\"flex:1;min-width:150px;background:var(--bg-primary);border:1px solid var(--border-light);border-radius:12px;padding:14px 16px;\">\n          <div style=\"font-size:11px;letter-spacing:1.5px;text-transform:uppercase;color:var(--text-muted);\">CEO Drag<\/div>\n          <div style=\"font-size:28px;font-weight:700;color:#dc4a39;line-height:1.2;margin-top:4px;\">${scores.drag.total}<span style=\"font-size:14px;color:var(--text-muted);font-weight:400;\">\/20<\/span><\/div>\n          <div style=\"font-size:13px;color:var(--text-primary);margin-top:2px;\">${dragLevel.name}<\/div>\n        <\/div>\n        ${tax ? `<div style=\"flex:1;min-width:150px;background:var(--bg-primary);border:1px solid var(--border-light);border-radius:12px;padding:14px 16px;\">\n          <div style=\"font-size:11px;letter-spacing:1.5px;text-transform:uppercase;color:var(--text-muted);\">Estimated Friction Tax<\/div>\n          <div style=\"font-size:22px;font-weight:700;color:var(--accent-gold);line-height:1.3;margin-top:6px;\">${tax.text}<\/div>\n          <div style=\"font-size:12px;color:var(--text-muted);margin-top:2px;\">Directional. Derivation below.<\/div>\n        <\/div>` : ''}\n      <\/div>\n\n      <p style=\"line-height:1.85;color:var(--text-muted);margin-bottom:18px;\">${combinedRead}<\/p>\n\n      <div style=\"border-left:3px solid var(--accent-gold);padding-left:16px;margin-bottom:6px;\">\n        <div style=\"font-size:11px;letter-spacing:2px;text-transform:uppercase;color:var(--text-muted);margin-bottom:6px;\">Where the pressure is concentrated<\/div>\n        <p style=\"line-height:1.8;color:var(--text-primary);margin:0;\">\n          This is not a diffuse morale issue. The score pattern puts the concentrated pressure in\n          <strong>${ZONE_LABELS[worstKey]}<\/strong> (${worstVal}\/25) and\n          <strong>${ZONE_LABELS[secondKey]}<\/strong> (${secondVal}\/25).\n          Left untreated, the business keeps paying through slower execution, weaker leadership trust,\n          higher retention risk, and more CEO load than a company at this stage should still be carrying.\n        <\/p>\n      <\/div>\n\n      ${softened ? `<div style=\"margin-top:20px;background:rgba(220,74,57,0.08);border:1px solid rgba(220,74,57,0.35);border-radius:12px;padding:14px 16px;\">\n        <div style=\"font-size:11px;letter-spacing:2px;text-transform:uppercase;color:#dc4a39;margin-bottom:6px;\">Confidence Adjustment<\/div>\n        <p style=\"margin:0;line-height:1.8;color:var(--text-primary);font-size:14px;\">\n          You indicated that some of your answers were the polished version rather than the one you would show a board member.\n          That is a credit to your honesty, and it changes how this report should be read: <strong>treat every score below as a\n          floor, not a ceiling.<\/strong> The real numbers are very likely worse. This is exactly the gap the team survey is\n          designed to measure &mdash; run it.\n        <\/p>\n      <\/div>` : ''}\n    <\/div>\n  `;\n  content.appendChild(board);\n\n  \/\/ ===== LIVE PERCEPTION GAP (only when team data already exists) =====\n  if (state.mode === 'ceo') {\n    try {\n      var _groups = gapGroups();\n      var _grp = _groups[normKey(state.respondent.company)];\n      if (_grp && _grp.team.length) {\n        var _g = computeGap({ company: _grp.company, key: _grp.key, team: _grp.team,\n                              ceo: { mode: 'ceo', answers: state.answers, timestamp: new Date().toISOString() } });\n        if (_g) {\n          var _hl = gapHeadline(_g);\n          var _b = gapBand(_g.cf.delta, 'cf');\n          var _w = _g.zonesRanked[0];\n          var _gapEl = document.createElement('div');\n          _gapEl.className = 'results-section';\n          _gapEl.innerHTML =\n            '<div class=\"score-card\" style=\"text-align:left;border:1px solid ' + gapTone(_b.tone) + ';\">' +\n              '<div style=\"font-size:11px;letter-spacing:2px;text-transform:uppercase;color:' + gapTone(_b.tone) + ';margin-bottom:10px;\">Perception Gap &middot; ' + _g.n + ' team response' + (_g.n === 1 ? '' : 's') + '<\/div>' +\n              '<h3 style=\"margin-bottom:16px;line-height:1.35;\">' + _hl.title + '<\/h3>' +\n              '<p style=\"line-height:1.85;color:var(--text-muted);margin-bottom:16px;\">' + _hl.body + '<\/p>' +\n              '<div style=\"display:flex;gap:14px;flex-wrap:wrap;\">' +\n                '<div style=\"flex:1;min-width:180px;background:var(--bg-primary);border:1px solid var(--border-light);border-radius:12px;padding:14px 16px;\">' +\n                  '<div style=\"font-size:11px;letter-spacing:1.5px;text-transform:uppercase;color:var(--text-muted);\">Culture \/125<\/div>' +\n                  '<div style=\"font-size:20px;font-weight:700;margin-top:6px;\">You ' + _g.cf.ceo + ' &rarr; Team ' + gapRound(_g.cf.team, 1) + '<\/div>' +\n                  '<div style=\"font-size:14px;font-weight:700;color:' + gapTone(_b.tone) + ';\">' + gapArrow(_g.cf.delta) + '<\/div>' +\n                '<\/div>' +\n                '<div style=\"flex:1;min-width:180px;background:var(--bg-primary);border:1px solid var(--border-light);border-radius:12px;padding:14px 16px;\">' +\n                  '<div style=\"font-size:11px;letter-spacing:1.5px;text-transform:uppercase;color:var(--text-muted);\">CEO Drag \/20<\/div>' +\n                  '<div style=\"font-size:20px;font-weight:700;margin-top:6px;\">You ' + _g.drag.ceo + ' &rarr; Team ' + gapRound(_g.drag.team, 1) + '<\/div>' +\n                  '<div style=\"font-size:14px;font-weight:700;color:' + gapTone(gapBand(_g.drag.delta, 'drag').tone) + ';\">' + gapArrow(_g.drag.delta) + '<\/div>' +\n                '<\/div>' +\n              '<\/div>' +\n              (_w && _w.delta > 1 ? '<p style=\"margin:16px 0 0;line-height:1.8;color:var(--text-primary);\"><strong>Widest gap: ' + _w.label + '<\/strong> (' + gapArrow(_w.delta) + '). That is where to start the conversation.<\/p>' : '') +\n            '<\/div>';\n          content.appendChild(_gapEl);\n        }\n      }\n    } catch (e) { console.error('inline gap', e); }\n  }\n\n  \/\/ CF Score\n  const cfSection = document.createElement('div');\n  cfSection.className = 'results-section';\n  cfSection.innerHTML = `\n    <div class=\"score-card\">\n      <div class=\"score-visualization\">\n        <svg viewBox=\"0 0 200 200\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n          <circle cx=\"100\" cy=\"100\" r=\"90\" fill=\"none\" stroke=\"var(--bg-primary)\" stroke-width=\"8\"\/>\n          <circle cx=\"100\" cy=\"100\" r=\"90\" fill=\"none\" stroke=\"url(#goldGrad)\" stroke-width=\"8\" stroke-dasharray=\"${(scores.cf.total \/ 125) * 565} 565\" stroke-linecap=\"round\" transform=\"rotate(-90 100 100)\"\/>\n          <defs>\n            <linearGradient id=\"goldGrad\" x1=\"0%\" y1=\"0%\" x2=\"100%\" y2=\"100%\">\n              <stop offset=\"0%\" style=\"stop-color:var(--accent-gold);stop-opacity:1\" \/>\n              <stop offset=\"100%\" style=\"stop-color:var(--accent-gold-light);stop-opacity:1\" \/>\n            <\/linearGradient>\n          <\/defs>\n          <text x=\"100\" y=\"95\" text-anchor=\"middle\" font-size=\"32\" fill=\"var(--accent-gold)\" font-weight=\"bold\">${scores.cf.total}<\/text>\n          <text x=\"100\" y=\"115\" text-anchor=\"middle\" font-size=\"12\" fill=\"var(--text-muted)\">\/125<\/text>\n        <\/svg>\n      <\/div>\n      <div class=\"score-level-badge level-${cfLevel.color}\">${cfLevel.name}<\/div>\n      <h3 style=\"margin-bottom: 12px;\">${cfLevel.name}<\/h3>\n      <div class=\"score-summary\">${cfLevel.summary}<\/div>\n\n      <h4 style=\"margin-top: 32px; margin-bottom: 16px; font-size: 16px;\">Zone Breakdown<\/h4>\n      <div class=\"zone-breakdown\">\n        <div class=\"zone-card\">\n          <div class=\"zone-name\">Leadership Alignment<\/div>\n          <div class=\"zone-score\">\n            <span>${scores.cf.zoneScores.alignment}<\/span>\n            <span style=\"color: var(--text-muted);\">\/25<\/span>\n          <\/div>\n          <div class=\"zone-bar\">\n            <div class=\"zone-bar-fill\" style=\"width: ${(scores.cf.zoneScores.alignment \/ 25) * 100}%\"><\/div>\n          <\/div>\n        <\/div>\n        <div class=\"zone-card\">\n          <div class=\"zone-name\">Decision & Execution<\/div>\n          <div class=\"zone-score\">\n            <span>${scores.cf.zoneScores.decision}<\/span>\n            <span style=\"color: var(--text-muted);\">\/25<\/span>\n          <\/div>\n          <div class=\"zone-bar\">\n            <div class=\"zone-bar-fill\" style=\"width: ${(scores.cf.zoneScores.decision \/ 25) * 100}%\"><\/div>\n          <\/div>\n        <\/div>\n        <div class=\"zone-card\">\n          <div class=\"zone-name\">Accountability Rigor<\/div>\n          <div class=\"zone-score\">\n            <span>${scores.cf.zoneScores.accountability}<\/span>\n            <span style=\"color: var(--text-muted);\">\/25<\/span>\n          <\/div>\n          <div class=\"zone-bar\">\n            <div class=\"zone-bar-fill\" style=\"width: ${(scores.cf.zoneScores.accountability \/ 25) * 100}%\"><\/div>\n          <\/div>\n        <\/div>\n        <div class=\"zone-card\">\n          <div class=\"zone-name\">Talent Density<\/div>\n          <div class=\"zone-score\">\n            <span>${scores.cf.zoneScores.talent}<\/span>\n            <span style=\"color: var(--text-muted);\">\/25<\/span>\n          <\/div>\n          <div class=\"zone-bar\">\n            <div class=\"zone-bar-fill\" style=\"width: ${(scores.cf.zoneScores.talent \/ 25) * 100}%\"><\/div>\n          <\/div>\n        <\/div>\n        <div class=\"zone-card\">\n          <div class=\"zone-name\">Leadership Courage<\/div>\n          <div class=\"zone-score\">\n            <span>${scores.cf.zoneScores.culture}<\/span>\n            <span style=\"color: var(--text-muted);\">\/25<\/span>\n          <\/div>\n          <div class=\"zone-bar\">\n            <div class=\"zone-bar-fill\" style=\"width: ${(scores.cf.zoneScores.culture \/ 25) * 100}%\"><\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  `;\n  content.appendChild(cfSection);\n\n  \/\/ Drag Score\n  const dragSection = document.createElement('div');\n  dragSection.className = 'results-section';\n  dragSection.innerHTML = `\n    <div class=\"score-card\">\n      <div class=\"score-visualization\">\n        <svg viewBox=\"0 0 200 200\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n          <circle cx=\"100\" cy=\"100\" r=\"90\" fill=\"none\" stroke=\"var(--bg-primary)\" stroke-width=\"8\"\/>\n          <circle cx=\"100\" cy=\"100\" r=\"90\" fill=\"none\" stroke=\"#dc4a39\" stroke-width=\"8\" stroke-dasharray=\"${(scores.drag.total \/ 20) * 565} 565\" stroke-linecap=\"round\" transform=\"rotate(-90 100 100)\"\/>\n          <text x=\"100\" y=\"95\" text-anchor=\"middle\" font-size=\"32\" fill=\"#dc4a39\" font-weight=\"bold\">${scores.drag.total}<\/text>\n          <text x=\"100\" y=\"115\" text-anchor=\"middle\" font-size=\"12\" fill=\"var(--text-muted)\">\/20<\/text>\n        <\/svg>\n      <\/div>\n      <div class=\"score-level-badge level-${dragLevel.color}\">${dragLevel.name}<\/div>\n      <h3 style=\"margin-bottom: 12px;\">${dragLevel.name}<\/h3>\n      <div class=\"score-summary\">${dragLevel.summary}<\/div>\n    <\/div>\n  `;\n  content.appendChild(dragSection);\n\n  \/\/ Combined Read\n  const combined = document.createElement('div');\n  combined.className = 'results-section';\n  combined.innerHTML = `\n    <div class=\"combined-read\">\n      <div class=\"combined-read-title\">Your Read<\/div>\n      <p>${combinedRead}<\/p>\n    <\/div>\n  `;\n  content.appendChild(combined);\n\n  \/\/ Tailored recommendations (generated from this respondent's specific answers)\n  const rec = buildRecommendations(scores);\n  const recSection = document.createElement('div');\n  recSection.className = 'results-section';\n  recSection.innerHTML = rec.html;\n  content.appendChild(recSection);\n\n  \/\/ Email confirmation\n  const email = document.createElement('div');\n  email.className = 'email-confirmation';\n  email.innerHTML = state.mode === 'ceo' && state.respondent.email\n    ? `\ud83d\udce7 Your full report has been sent to <strong>${state.respondent.email}<\/strong>`\n    : `\u2705 Your submission has been recorded. Thank you for your honesty.`;\n  content.appendChild(email);\n\n  \/\/ Another diagnostic button\n  const another = document.createElement('div');\n  another.style.textAlign = 'center';\n  another.innerHTML = '<button class=\"btn btn-primary\" onclick=\"showLanding()\">Take Another Diagnostic<\/button>';\n  content.appendChild(another);\n\n  \/\/ Save result\n  if (!state.qaMode) saveResult(scores, cfLevel, dragLevel);\n\n  \/\/ ===== METHODOLOGY & LIMITS =====\n  const meth = document.createElement('div');\n  meth.className = 'results-section';\n  meth.innerHTML = `\n    <div class=\"score-card\" style=\"text-align:left;\">\n      <div style=\"font-size:11px;letter-spacing:2px;text-transform:uppercase;color:var(--text-muted);margin-bottom:10px;\">Method &amp; Limits<\/div>\n      <p style=\"line-height:1.85;color:var(--text-muted);font-size:14px;margin-bottom:12px;\">\n        <strong style=\"color:var(--text-primary);\">What this is.<\/strong> 25 statements across five leadership zones on a five-point scale\n        (11 of them reverse-keyed, so agreement is not always the flattering answer), plus 10 forced-choice questions on CEO dependency.\n        Cultural Friction scores 25&ndash;125. CEO Drag scores 0&ndash;20. Zone scores are 5 items each, scored 5&ndash;25.\n      <\/p>\n      <p style=\"line-height:1.85;color:var(--text-muted);font-size:14px;margin-bottom:12px;\">\n        <strong style=\"color:var(--text-primary);\">What this is not.<\/strong> This is a self-report instrument. It measures what you are\n        willing to say about your own company today &mdash; which is useful, and is not the same thing as measurement. It is not an audit,\n        not a benchmark against a normed population, and not a valuation input. Any dollar figure shown is derived from your own answers\n        and is deliberately expressed as a range.\n      <\/p>\n      <p style=\"line-height:1.85;color:var(--text-muted);font-size:14px;margin:0;\">\n        <strong style=\"color:var(--text-primary);\">The number that matters most is not on this page.<\/strong> The single most defensible\n        signal in this system is the <em>gap<\/em> between how a CEO scores their company and how their own senior team scores it. That gap\n        cannot be talked around. Run the team survey with your top three to five people and compare the two reads &mdash; that comparison,\n        not this score, is where the real conversation starts.\n      <\/p>\n    <\/div>\n  `;\n  content.appendChild(meth);\n\n  \/\/ Send emails\n  if (!state.qaMode) sendResultEmails(scores, cfLevel, dragLevel, combinedRead, rec);\n}\n\nfunction saveResult(scores, cfLevel, dragLevel) {\n  const store = getStore();\n  const result = {\n    id: generateSessionId(),\n    timestamp: new Date().toISOString(),\n    mode: state.mode,\n    respondent: state.respondent,\n    session: state.session,\n    answers: state.answers,\n    cf: {\n      total: scores.cf.total,\n      level: cfLevel.name,\n      color: cfLevel.color,\n      summary: cfLevel.summary,\n      zoneScores: scores.cf.zoneScores\n    },\n    drag: {\n      total: scores.drag.total,\n      level: dragLevel.name,\n      color: dragLevel.color,\n      summary: dragLevel.summary\n    }\n  };\n\n  store.results.push(result);\n  if (state.session) {\n    const session = store.sessions.find(s => s.id === state.session.id);\n    if (session) session.completions = (session.completions || 0) + 1;\n  }\n  saveStore(store);\n}\n\n\/\/ ===== EMAIL SENDING =====\nfunction sendResultEmails(scores, cfLevel, dragLevel, combinedRead, rec) {\n  const zoneList = Object.entries(scores.cf.zoneScores).map(([k, v]) => `${k}: ${v}\/25`).join('\\n');\n  const dragSet = state.mode === 'team' ? TEAM_DRAG_QUESTIONS : DRAG_QUESTIONS;\n  const dragResponses = state.answers.slice(25, 35).map((ansIdx, qIdx) => {\n    if (ansIdx !== null) return dragSet[qIdx].options[ansIdx].text;\n    return '';\n  }).join('\\n');\n\n  const params = {\n    name: state.respondent.name,\n    cf_answers: state.answers.slice(0, 25).join(','),\n    recommendations: rec ? rec.text : '',\n    friction_tax: rec && rec.taxText ? rec.taxText : '',\n    respondent_name: state.respondent.name,\n    respondent_role: state.respondent.role,\n    respondent_email: state.respondent.email,\n    company: state.respondent.company,\n    revenue: state.respondent.revenue || '',\n    industry: state.respondent.industry || '',\n    size: state.respondent.size || '',\n    session_id: state.session?.id || 'Direct',\n    timestamp: new Date().toLocaleString(),\n    cf_total: scores.cf.total,\n    cf_level: cfLevel.name,\n    cf_summary: cfLevel.summary,\n    zone_breakdown: zoneList,\n    drag_total: scores.drag.total,\n    drag_level: dragLevel.name,\n    drag_summary: dragLevel.summary,\n    drag_responses: dragResponses,\n    combined_read: combinedRead,\n    mode: state.mode\n  };\n\n  \/\/ Alert email to admin\n  if (EMAIL_READY && CONFIG.email.serviceId !== 'YOUR_EMAILJS_SERVICE_ID') {\n    emailjs.send(CONFIG.email.serviceId, CONFIG.email.templateIdAlert, {\n      ...params,\n      to_email: CONFIG.email.adminEmail\n    }).catch(e => console.log('Alert email failed:', e));\n  }\n\n  \/\/ Results email to respondent\n  if (state.mode === 'ceo' && state.respondent.email && EMAIL_READY && CONFIG.email.serviceId !== 'YOUR_EMAILJS_SERVICE_ID') {\n    emailjs.send(CONFIG.email.serviceId, CONFIG.email.templateIdResults, {\n      ...params,\n      to_email: state.respondent.email\n    }).catch(e => console.log('Results email failed:', e));\n  }\n\n  \/\/ Sync to Google Sheets\n  if (CONFIG.sheetsWebhook) {\n    fetch(CONFIG.sheetsWebhook, {\n      method: 'POST',\n      mode: 'no-cors',\n      body: JSON.stringify(params)\n    }).catch(e => console.log('Sheet sync failed:', e));\n  }\n}\n\n\/\/ ===== ADMIN FUNCTIONS =====\nfunction showAdminLogin() {\n  document.getElementById('adminLoginContainer').style.display = 'flex';\n}\n\nasync function sha256Hex(str) {\n  const buf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(str));\n  return Array.from(new Uint8Array(buf)).map(b => b.toString(16).padStart(2, '0')).join('');\n}\n\nasync function adminLogin(e) {\n  e.preventDefault();\n  const username = document.getElementById('adminUsername').value;\n  const password = document.getElementById('adminPassword').value;\n  const hashes = await Promise.all([sha256Hex(username), sha256Hex(password)]);\n\n  if (hashes[0] === CONFIG.admin.userHash && hashes[1] === CONFIG.admin.passHash) {\n    state.isAdminLoggedIn = true;\n    sessionStorage.setItem('adminLogged', 'true');\n    showAdminDashboard();\n    renderAdminDashboard();\n  } else {\n    const errorEl = document.getElementById('adminError');\n    errorEl.textContent = 'Invalid credentials. Try again.';\n    errorEl.classList.add('show');\n  }\n}\n\nfunction adminLogout() {\n  state.isAdminLoggedIn = false;\n  sessionStorage.removeItem('adminLogged');\n  showLanding();\n}\n\nfunction renderAdminDashboard() {\n  const store = getStore();\n  try { renderGapTable(); } catch (e) { console.error('gap table', e); }\n\n  \/\/ Stats\n  const now = new Date();\n  const activeCount = store.sessions.filter(s => new Date(s.expiresAt) > now).length;\n  const avgCF = store.results.length > 0 ? Math.round(store.results.reduce((sum, r) => sum + r.cf.total, 0) \/ store.results.length) : 0;\n  const todayCount = store.results.filter(r => new Date(r.timestamp).toDateString() === now.toDateString()).length;\n\n  const statsGrid = document.getElementById('statsGrid');\n  statsGrid.innerHTML = `\n    <div class=\"stat-card\">\n      <div class=\"stat-label\">Total Completions<\/div>\n      <div class=\"stat-value\">${store.results.length}<\/div>\n    <\/div>\n    <div class=\"stat-card\">\n      <div class=\"stat-label\">Active Sessions<\/div>\n      <div class=\"stat-value\">${activeCount}<\/div>\n    <\/div>\n    <div class=\"stat-card\">\n      <div class=\"stat-label\">Avg CF Score<\/div>\n      <div class=\"stat-value\">${avgCF}<\/div>\n    <\/div>\n    <div class=\"stat-card\">\n      <div class=\"stat-label\">Submitted Today<\/div>\n      <div class=\"stat-value\">${todayCount}<\/div>\n    <\/div>\n  `;\n\n  \/\/ Sessions table\n  const sessionsTable = document.getElementById('sessionsTableContainer');\n  if (store.sessions.length === 0) {\n    sessionsTable.innerHTML = '<p style=\"color: var(--text-muted); text-align: center; padding: 40px 20px;\">No active sessions yet.<\/p>';\n  } else {\n    let html = `<table>\n      <thead>\n        <tr>\n          <th>Company<\/th>\n          <th>Leader<\/th>\n          <th>Created<\/th>\n          <th>Expires<\/th>\n          <th>Progress<\/th>\n          <th>Status<\/th>\n          <th>Actions<\/th>\n        <\/tr>\n      <\/thead>\n      <tbody>`;\n\n    store.sessions.forEach(s => {\n      const isActive = new Date(s.expiresAt) > now;\n      const status = isActive ? '<span class=\"badge badge-active\">Active<\/span>' : '<span class=\"badge badge-expired\">Expired<\/span>';\n      const completions = s.completions || 0;\n      const progress = s.teamSize ? Math.round((completions \/ s.teamSize) * 100) : 0;\n\n      html += `<tr>\n        <td>${s.company}<\/td>\n        <td>\n          <div>${s.leaderName}<\/div>\n          <div style=\"font-size: 12px; color: var(--text-muted);\">${s.leaderEmail}<\/div>\n        <\/td>\n        <td>${new Date(s.createdAt).toLocaleDateString()}<\/td>\n        <td>${new Date(s.expiresAt).toLocaleDateString()}<\/td>\n        <td>\n          <div style=\"font-size: 12px; color: var(--text-muted);\">${completions}\/${s.teamSize || '?'}<\/div>\n          <div class=\"progress-mini\">\n            <div class=\"progress-mini-fill\" style=\"width: ${progress}%\"><\/div>\n          <\/div>\n        <\/td>\n        <td>${status}<\/td>\n        <td>\n          <div class=\"table-actions\">\n            <button class=\"btn btn-secondary action-btn\" onclick=\"copySessLink('${s.id}')\">Copy<\/button>\n            <button class=\"btn btn-secondary action-btn\" onclick=\"deleteSession('${s.id}')\">Delete<\/button>\n          <\/div>\n        <\/td>\n      <\/tr>`;\n    });\n\n    html += '<\/tbody><\/table>';\n    sessionsTable.innerHTML = html;\n  }\n\n  \/\/ Results table\n  const resultsTable = document.getElementById('resultsTableContainer');\n  if (store.results.length === 0) {\n    resultsTable.innerHTML = '<p style=\"color: var(--text-muted); text-align: center; padding: 40px 20px;\">No results yet.<\/p>';\n  } else {\n    let html = `<table>\n      <thead>\n        <tr>\n          <th>Name \/ Role<\/th>\n          <th>Company<\/th>\n          <th>Date<\/th>\n          <th>CF Score<\/th>\n          <th>Drag Score<\/th>\n          <th>Level<\/th>\n          <th>Actions<\/th>\n        <\/tr>\n      <\/thead>\n      <tbody>`;\n\n    store.results.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp)).forEach(r => {\n      html += `<tr>\n        <td>\n          <div>${r.respondent.name}<\/div>\n          <div style=\"font-size: 12px; color: var(--text-muted);\">${r.respondent.role}<\/div>\n        <\/td>\n        <td>${r.respondent.company}<\/td>\n        <td>${new Date(r.timestamp).toLocaleDateString()}<\/td>\n        <td>${r.cf.total}<\/td>\n        <td>${r.drag.total}<\/td>\n        <td><span class=\"badge level-${r.cf.color}\">${r.cf.level}<\/span><\/td>\n        <td><button class=\"btn btn-secondary action-btn\" onclick=\"showResultDetail('${r.id}')\">View<\/button><\/td>\n      <\/tr>`;\n    });\n\n    html += '<\/tbody><\/table>';\n    resultsTable.innerHTML = html;\n  }\n}\n\nfunction generateSessionLink(e) {\n  e.preventDefault();\n\n  const company = document.getElementById('sessionCompany').value;\n  const leader = document.getElementById('sessionLeader').value;\n  const email = document.getElementById('sessionLeaderEmail').value;\n  const phone = document.getElementById('sessionPhone').value;\n  const industry = document.getElementById('sessionIndustry').value;\n  const revenue = document.getElementById('sessionRevenue').value;\n  const teamSize = document.getElementById('sessionTeamSize').value;\n  const date = document.getElementById('sessionDate').value;\n\n  const sessionId = generateSessionId();\n  const now = new Date();\n  const expires = new Date(now.getTime() + 72 * 60 * 60 * 1000);\n\n  const store = getStore();\n  store.sessions.push({\n    id: sessionId,\n    company,\n    leaderName: leader,\n    leaderEmail: email,\n    phone,\n    industry,\n    revenue,\n    teamSize: parseInt(teamSize) || null,\n    sessionDate: date,\n    createdAt: now.toISOString(),\n    expiresAt: expires.toISOString(),\n    completions: 0\n  });\n  saveStore(store);\n\n  const linkExp = expires.getTime();\n  const url = `${CONFIG.appUrl}?session=${sessionId}&company=${encodeURIComponent(company)}&leader=${encodeURIComponent(leader)}&exp=${linkExp}&sig=${simpleSig(sessionId + '|' + linkExp + '|' + SIG_SALT)}`;\n  document.getElementById('generatedSessionUrl').textContent = url;\n  document.getElementById('sessionGenerated').classList.add('show');\n\n  \/\/ Save current session for later email use\n  state.currentSessionUrl = url;\n  state.currentSessionEmail = email;\n\n  showToast('Session link generated successfully');\n  renderAdminDashboard();\n}\n\nfunction copySessionLink() {\n  const url = document.getElementById('generatedSessionUrl').textContent;\n  navigator.clipboard.writeText(url).then(() => showToast('Link copied'));\n}\n\nfunction emailSessionLink() {\n  const url = document.getElementById('generatedSessionUrl').textContent;\n  const email = state.currentSessionEmail;\n\n  if (EMAIL_READY && CONFIG.email.serviceId !== 'YOUR_EMAILJS_SERVICE_ID') {\n    emailjs.send(CONFIG.email.serviceId, CONFIG.email.templateIdLeader, {\n      to_email: email,\n      session_url: url,\n      company: document.getElementById('sessionCompany').value\n    }).then(() => {\n      showToast('Email sent successfully');\n    }).catch(() => {\n      showToast('Failed to send email', 'error');\n    });\n  }\n}\n\nfunction copySessLink(sessionId) {\n  const store = getStore();\n  const session = store.sessions.find(s => s.id === sessionId);\n  if (session) {\n    const linkExp = new Date(session.expiresAt).getTime();\n    const url = `${CONFIG.appUrl}?session=${sessionId}&company=${encodeURIComponent(session.company)}&leader=${encodeURIComponent(session.leaderName)}&exp=${linkExp}&sig=${simpleSig(sessionId + '|' + linkExp + '|' + SIG_SALT)}`;\n    navigator.clipboard.writeText(url).then(() => showToast('Link copied'));\n  }\n}\n\nfunction deleteSession(sessionId) {\n  if (confirm('Delete this session?')) {\n    const store = getStore();\n    store.sessions = store.sessions.filter(s => s.id !== sessionId);\n    saveStore(store);\n    renderAdminDashboard();\n    showToast('Session deleted');\n  }\n}\n\nfunction showResultDetail(resultId) {\n  const store = getStore();\n  const result = store.results.find(r => r.id === resultId);\n  if (!result) return;\n\n  const cfLevel = getCFLevel(result.cf.total);\n  const dragLevel = getDragLevel(result.drag.total);\n\n  const html = `\n    <div class=\"modal-header\">\n      <h2 class=\"modal-title\">${result.respondent.name}<\/h2>\n      <button class=\"modal-close\" onclick=\"closeModal()\">\u00d7<\/button>\n    <\/div>\n\n    <div style=\"margin-bottom: 24px;\">\n      <div style=\"font-size: 12px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px;\">Details<\/div>\n      <div style=\"font-size: 14px;\">${result.respondent.role} at ${result.respondent.company}<\/div>\n      <div style=\"font-size: 12px; color: var(--text-muted);\">${new Date(result.timestamp).toLocaleString()}<\/div>\n    <\/div>\n\n    <div style=\"margin-bottom: 32px;\">\n      <h3 style=\"margin-bottom: 16px;\">Cultural Friction<\/h3>\n      <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 16px;\">\n        <div style=\"background: var(--bg-primary); border: 1px solid var(--border-light); border-radius: 12px; padding: 16px; text-align: center;\">\n          <div style=\"font-size: 28px; color: var(--accent-gold); font-weight: 600;\">${result.cf.total}<\/div>\n          <div style=\"font-size: 12px; color: var(--text-muted);\">\/125<\/div>\n        <\/div>\n        <div style=\"background: var(--bg-primary); border: 1px solid var(--border-light); border-radius: 12px; padding: 16px; text-align: center;\">\n          <div class=\"score-level-badge level-${result.cf.color}\" style=\"display: inline-block;\">${result.cf.level}<\/div>\n        <\/div>\n      <\/div>\n      <div style=\"background: var(--bg-primary); border: 1px solid var(--border-light); border-radius: 12px; padding: 16px; font-size: 14px; line-height: 1.6; color: var(--text-muted);\">${result.cf.summary}<\/div>\n    <\/div>\n\n    <div style=\"margin-bottom: 32px;\">\n      <h3 style=\"margin-bottom: 16px;\">Zone Breakdown<\/h3>\n      <table style=\"width: 100%; font-size: 14px;\">\n        <tr>\n          <td style=\"border-bottom: 1px solid var(--border-light); padding: 12px 0;\">Leadership Alignment<\/td>\n          <td style=\"border-bottom: 1px solid var(--border-light); padding: 12px 0; text-align: right; color: var(--accent-gold);\">${result.cf.zoneScores.alignment}\/25<\/td>\n        <\/tr>\n        <tr>\n          <td style=\"border-bottom: 1px solid var(--border-light); padding: 12px 0;\">Decision & Execution<\/td>\n          <td style=\"border-bottom: 1px solid var(--border-light); padding: 12px 0; text-align: right; color: var(--accent-gold);\">${result.cf.zoneScores.decision}\/25<\/td>\n        <\/tr>\n        <tr>\n          <td style=\"border-bottom: 1px solid var(--border-light); padding: 12px 0;\">Accountability Rigor<\/td>\n          <td style=\"border-bottom: 1px solid var(--border-light); padding: 12px 0; text-align: right; color: var(--accent-gold);\">${result.cf.zoneScores.accountability}\/25<\/td>\n        <\/tr>\n        <tr>\n          <td style=\"border-bottom: 1px solid var(--border-light); padding: 12px 0;\">Talent Density<\/td>\n          <td style=\"border-bottom: 1px solid var(--border-light); padding: 12px 0; text-align: right; color: var(--accent-gold);\">${result.cf.zoneScores.talent}\/25<\/td>\n        <\/tr>\n        <tr>\n          <td style=\"padding: 12px 0;\">Leadership Courage<\/td>\n          <td style=\"padding: 12px 0; text-align: right; color: var(--accent-gold);\">${result.cf.zoneScores.culture}\/25<\/td>\n        <\/tr>\n      <\/table>\n    <\/div>\n\n    <div>\n      <h3 style=\"margin-bottom: 16px;\">CEO Drag<\/h3>\n      <div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 16px;\">\n        <div style=\"background: var(--bg-primary); border: 1px solid var(--border-light); border-radius: 12px; padding: 16px; text-align: center;\">\n          <div style=\"font-size: 28px; color: #dc4a39; font-weight: 600;\">${result.drag.total}<\/div>\n          <div style=\"font-size: 12px; color: var(--text-muted);\">\/20<\/div>\n        <\/div>\n        <div style=\"background: var(--bg-primary); border: 1px solid var(--border-light); border-radius: 12px; padding: 16px; text-align: center;\">\n          <div class=\"score-level-badge level-${result.drag.color}\" style=\"display: inline-block;\">${result.drag.level}<\/div>\n        <\/div>\n      <\/div>\n      <div style=\"background: var(--bg-primary); border: 1px solid var(--border-light); border-radius: 12px; padding: 16px; font-size: 14px; line-height: 1.6; color: var(--text-muted);\">${result.drag.summary}<\/div>\n    <\/div>\n  `;\n\n  document.getElementById('modalContent').innerHTML = html;\n  document.getElementById('detailModal').classList.add('active');\n}\n\nfunction exportCSV() {\n  const store = getStore();\n  const headers = ['Date', 'Name', 'Role', 'Email', 'Company', 'Revenue', 'Industry', 'Employees', 'Mode', 'Session ID', 'CF Total', 'CF Level', 'Zone Alignment', 'Zone Decision', 'Zone Accountability', 'Zone Talent', 'Zone Culture', 'Drag Total', 'Drag Level'];\n\n  let csv = headers.join(',') + '\\n';\n  store.results.forEach(r => {\n    const row = [\n      new Date(r.timestamp).toLocaleDateString(),\n      `\"${r.respondent.name}\"`,\n      `\"${r.respondent.role}\"`,\n      r.respondent.email,\n      `\"${r.respondent.company}\"`,\n      r.respondent.revenue || '',\n      r.respondent.industry || '',\n      r.respondent.size || '',\n      r.mode,\n      r.session?.id || 'Direct',\n      r.cf.total,\n      r.cf.level,\n      r.cf.zoneScores.alignment,\n      r.cf.zoneScores.decision,\n      r.cf.zoneScores.accountability,\n      r.cf.zoneScores.talent,\n      r.cf.zoneScores.culture,\n      r.drag.total,\n      r.drag.level\n    ];\n    csv += row.join(',') + '\\n';\n  });\n\n  const blob = new Blob([csv], { type: 'text\/csv' });\n  const url = window.URL.createObjectURL(blob);\n  const a = document.createElement('a');\n  a.href = url;\n  a.download = `ris-friction-results-${new Date().toISOString().split('T')[0]}.csv`;\n  a.click();\n}\n\n\/\/ ===== INITIALIZATION =====\ndocument.addEventListener('DOMContentLoaded', () => {\n  \/\/ Tab switching\n  document.querySelectorAll('.tab-btn').forEach(btn => {\n    btn.addEventListener('click', () => switchTab(btn.dataset.tab));\n  });\n\n  \/\/ Check if admin logged in\n  if (sessionStorage.getItem('adminLogged')) {\n    state.isAdminLoggedIn = true;\n  }\n\n  \/\/ Check URL params\n  const params = new URLSearchParams(window.location.search);\n  if (params.has('qa')) {\n    runQA(params.get('qa'));\n    return;\n  }\n  if (params.has('session')) {\n    showApp();\n    document.querySelector('[data-tab=\"team\"]').click();\n  } else if (params.get('mode') === 'admin') {\n    if (state.isAdminLoggedIn) {\n      showAdminDashboard();\n      renderAdminDashboard();\n    } else {\n      showAdminLogin();\n    }\n  } else {\n    showLanding();\n  }\n});\n\ndocument.addEventListener('keypress', (e) => {\n  if (e.key === 'Enter' && document.getElementById('adminLoginForm') && document.activeElement.closest('#adminLoginForm')) {\n    adminLogin(e);\n  }\n});\n<\/script>\n\n<!--\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nSETUP INSTRUCTIONS\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n1. EMAILJS SETUP\n\n- Create a free EmailJS account at emailjs.com\n- Create 3 email templates:\n\n  TEMPLATE 1 (Alert Email to Admin)\n  Template Name: (anything, e.g., \"alert_template\")\n  Variables used: {{name}}, {{respondent_name}}, {{respondent_role}}, {{respondent_email}}, {{company}}, {{cf_total}}, {{cf_level}}, {{drag_total}}, {{drag_level}}, {{timestamp}}, {{recommendations}}, {{friction_tax}}, {{zone_breakdown}}, {{combined_read}}\n\n  TEMPLATE 2 (Results to Respondent - CEO Mode)\n  Template Name: (anything, e.g., \"results_template\")\n  Variables used: {{respondent_name}}, {{company}}, {{cf_total}}, {{cf_level}}, {{cf_summary}}, {{drag_total}}, {{drag_level}}, {{drag_summary}}, {{combined_read}}, {{recommendations}}, {{friction_tax}}, {{zone_breakdown}}\n\n  TEMPLATE 3 (Session Link to Leader)\n  Template Name: (anything, e.g., \"leader_template\")\n  Variables used: {{session_url}}, {{company}}\n\n- Copy your:\n  - Service ID (Account > Services)\n  - Public Key (Account > API Keys)\n  - Template IDs from each template\n\n- Update CONFIG object at top of this file:\n  CONFIG.email.serviceId = 'YOUR_SERVICE_ID'\n  CONFIG.email.templateIdAlert = 'ALERT_TEMPLATE_ID'\n  CONFIG.email.templateIdResults = 'RESULTS_TEMPLATE_ID'\n  CONFIG.email.templateIdLeader = 'LEADER_TEMPLATE_ID'\n  CONFIG.email.publicKey = 'YOUR_PUBLIC_KEY'\n\n2. ADMIN CREDENTIALS\n\n- Stored as SHA-256 hashes in CONFIG.admin (userHash \/ passHash) \u2014 no plaintext in this file.\n- To change: open the browser console on the app page and run:  await sha256Hex('newvalue')\n  then paste the resulting hex into userHash \/ passHash.\n\n3. GOOGLE SHEETS SYNC (Optional)\n\n- Create a new Google Apps Script project\n- Paste the code from the commented section at the end of this file into the editor\n- Deploy as web app (Execute as: your account, Who has access: Anyone)\n- Copy the deployment URL\n- Paste into CONFIG.sheetsWebhook = 'YOUR_WEBHOOK_URL'\n- Each submission will append a row to your sheet\n\n4. WORDPRESS EMBEDDING\n\n- Use the HTML\/Custom HTML widget\n- Paste this entire file content into the widget, OR\n- Use an iframe: <iframe src=\"path\/to\/ris-friction-suite.html\" width=\"100%\" height=\"800px\"><\/iframe>\n\n5. CUSTOMIZATION\n\n- Logo URL: Change the img src in the landing screen to your logo\n- App URL: CONFIG.appUrl auto-detects, but can be hardcoded to your domain\n- Accent color: Change --accent-gold in CSS (default #C9A84C)\n- Admin email for alerts: CONFIG.email.adminEmail\n\n6. TESTING\n\n- Open the file in a browser\n- Test CEO flow: Fill intake \u2192 answer questions \u2192 see results\n- Test team flow: Generate session link in admin \u2192 use URL param\n- Admin login: Click Admin tab, use credentials\n- Check localStorage in dev tools: Application > Local Storage > ris_v2_data\n\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nGOOGLE APPS SCRIPT CODE (Copy into Apps Script editor)\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nfunction doPost(e) {\n  const data = JSON.parse(e.postData.contents);\n  const sheet = SpreadsheetApp.getActiveSheet();\n\n  const row = [\n    data.timestamp,\n    data.respondent_name,\n    data.respondent_role,\n    data.respondent_email,\n    data.company,\n    data.revenue,\n    data.industry,\n    data.size,\n    data.mode,\n    data.session_id,\n    data.cf_total,\n    data.cf_level,\n    data.zone_breakdown,\n    data.drag_total,\n    data.drag_level,\n    data.drag_responses,\n    data.combined_read\n  ];\n\n  sheet.appendRow(row);\n\n  return ContentService.createTextOutput('OK');\n}\n\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n-->\n<\/body>\n<\/html>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>RIS METHOD\u2122 \u00b7 Leadership Friction Suite\u2122<\/p>","protected":false},"author":1,"featured_media":1371,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"footnotes":""},"class_list":["post-1343","page","type-page","status-publish","has-post-thumbnail","hentry"],"blocksy_meta":[],"_hostinger_reach_plugin_has_subscription_block":false,"_hostinger_reach_plugin_is_elementor":false,"_links":{"self":[{"href":"https:\/\/rismethod.com\/fr\/wp-json\/wp\/v2\/pages\/1343","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rismethod.com\/fr\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/rismethod.com\/fr\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/rismethod.com\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rismethod.com\/fr\/wp-json\/wp\/v2\/comments?post=1343"}],"version-history":[{"count":41,"href":"https:\/\/rismethod.com\/fr\/wp-json\/wp\/v2\/pages\/1343\/revisions"}],"predecessor-version":[{"id":1554,"href":"https:\/\/rismethod.com\/fr\/wp-json\/wp\/v2\/pages\/1343\/revisions\/1554"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rismethod.com\/fr\/wp-json\/wp\/v2\/media\/1371"}],"wp:attachment":[{"href":"https:\/\/rismethod.com\/fr\/wp-json\/wp\/v2\/media?parent=1343"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}