{"id":44102,"date":"2026-04-27T11:14:18","date_gmt":"2026-04-27T17:14:18","guid":{"rendered":"https:\/\/twkumc.org\/?page_id=44102"},"modified":"2026-04-29T11:00:17","modified_gmt":"2026-04-29T17:00:17","slug":"ministry-team-bubble-map","status":"publish","type":"page","link":"https:\/\/twkumc.org\/ko\/ministry-team-bubble-map\/","title":{"rendered":"\uc0ac\uc5ed \ud300 \ubc84\ube14 \ub9f5"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"44102\" class=\"elementor elementor-44102\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-e46cda7 e-con-full e-flex e-con e-parent\" data-id=\"e46cda7\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-5b519dd elementor-widget elementor-widget-html\" data-id=\"5b519dd\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\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>TWK Conference Team Structure<\/title>\n\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Poppins:wght@300;400;500;600;700&display=swap\" rel=\"stylesheet\">\n\n<script src=\"https:\/\/d3js.org\/d3.v7.min.js\"><\/script>\n\n<style>\n  :root {\n    --twk-blue: #299BD7;\n    --twk-blue-dark: #103E56;\n    --twk-blue-light: #BFDFF0;\n    --twk-text-on-bubble: #FFFFFF;\n    --twk-panel-bg: #FFFFFF;\n    --twk-panel-shadow: rgba(16, 62, 86, 0.22);\n    --twk-stage-bg-top: #F5FAFD;\n    --twk-stage-bg-bot: #EAF4FB;\n  }\n\n  .twk-bubble-map-wrapper {\n    font-family: 'Poppins', system-ui, sans-serif;\n    position: relative;\n    width: 100%;\n    max-width: 1400px;\n    margin: 0 auto;\n    padding: 16px;\n    box-sizing: border-box;\n  }\n\n  .twk-bubble-map-wrapper * {\n    box-sizing: border-box;\n  }\n\n  .twk-bubble-map-wrapper .twk-header {\n    text-align: center;\n    margin-bottom: 10px;\n  }\n\n  .twk-bubble-map-wrapper .twk-header h2 {\n    font-family: 'Poppins', sans-serif;\n    font-weight: 600;\n    color: var(--twk-blue-dark);\n    margin: 0 0 4px;\n    font-size: clamp(18px, 2.2vw, 26px);\n  }\n\n  .twk-bubble-map-wrapper .twk-header p {\n    font-family: 'Poppins', sans-serif;\n    font-weight: 400;\n    color: #6a7d87;\n    margin: 0;\n    font-size: clamp(12px, 1.3vw, 14px);\n  }\n\n  \/* ------------------------------------------------------------------ *\/\n  \/* STAGE                                                               *\/\n  \/* ------------------------------------------------------------------ *\/\n  .twk-bubble-map-stage {\n    position: relative;\n    width: 100%;\n    background: linear-gradient(180deg, var(--twk-stage-bg-top) 0%, var(--twk-stage-bg-bot) 100%);\n    border-radius: 16px;\n    overflow: hidden;\n    \/* Responsive height: wide on desktop, taller on mobile *\/\n    aspect-ratio: 16 \/ 9;\n    min-height: 400px;\n  }\n\n  .twk-bubble-map-stage svg {\n    width: 100%;\n    height: 100%;\n    display: block;\n  }\n\n  \/* ------------------------------------------------------------------ *\/\n  \/* BUBBLES                                                             *\/\n  \/* ------------------------------------------------------------------ *\/\n  .twk-bubble {\n    cursor: pointer;\n  }\n\n  .twk-bubble .twk-circle {\n    stroke: #FFFFFF;\n    stroke-width: 2.5;\n    transition: filter 260ms ease;\n    transform-box: fill-box;\n    transform-origin: center;\n  }\n\n  .twk-bubble:hover .twk-circle {\n    filter: drop-shadow(0 4px 12px rgba(16, 62, 86, 0.35)) brightness(1.08);\n  }\n\n  .twk-bubble.is-active .twk-circle {\n    filter: drop-shadow(0 6px 16px rgba(16, 62, 86, 0.4));\n  }\n\n  .twk-label {\n    fill: var(--twk-text-on-bubble);\n    font-family: 'Poppins', sans-serif;\n    font-weight: 500;\n    text-anchor: middle;\n    pointer-events: none;\n    user-select: none;\n  }\n\n  .twk-link-line {\n    fill: none;\n    stroke-width: 1.6px;\n    stroke-opacity: 0.7;\n  }\n\n  \/* ------------------------------------------------------------------ *\/\n  \/* INFO PANEL                                                          *\/\n  \/* ------------------------------------------------------------------ *\/\n  .twk-info-panel {\n    position: absolute;\n    top: 16px;\n    right: 16px;\n    width: 320px;\n    max-width: calc(100% - 32px);\n    background: var(--twk-panel-bg);\n    border-radius: 14px;\n    padding: 20px 22px 22px;\n    box-shadow: 0 10px 28px var(--twk-panel-shadow);\n    opacity: 0;\n    transform: translateY(-8px);\n    pointer-events: none;\n    transition: opacity 220ms ease, transform 220ms ease;\n    z-index: 10;\n    border-top: 4px solid var(--twk-accent, var(--twk-blue));\n  }\n\n  .twk-info-panel.is-visible {\n    opacity: 1;\n    transform: translateY(0);\n    pointer-events: auto;\n  }\n\n  .twk-info-panel .twk-panel-tier {\n    font-size: 10px;\n    font-weight: 600;\n    letter-spacing: 0.14em;\n    text-transform: uppercase;\n    color: var(--twk-accent, var(--twk-blue));\n    margin: 0 0 5px;\n  }\n\n  .twk-info-panel h3 {\n    font-family: 'Poppins', sans-serif;\n    font-weight: 600;\n    color: var(--twk-blue-dark);\n    margin: 0 0 8px;\n    font-size: 17px;\n    padding-right: 28px;\n    line-height: 1.25;\n  }\n\n  .twk-info-panel p {\n    font-family: 'Poppins', sans-serif;\n    font-weight: 400;\n    color: #374853;\n    margin: 0 0 6px;\n    font-size: 13px;\n    line-height: 1.55;\n  }\n\n  .twk-info-panel .twk-panel-parent {\n    font-size: 11px;\n    color: #6a7d87;\n    margin-top: 8px;\n    padding-top: 8px;\n    border-top: 1px solid #E5EEF4;\n  }\n\n  .twk-info-panel .twk-panel-parent span {\n    color: var(--twk-blue-dark);\n    font-weight: 600;\n  }\n\n  .twk-info-panel .twk-close {\n    position: absolute;\n    top: 8px;\n    right: 10px;\n    width: 28px;\n    height: 28px;\n    border: none;\n    background: transparent;\n    color: #9aa7ae;\n    font-size: 20px;\n    line-height: 1;\n    cursor: pointer;\n    border-radius: 50%;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    transition: background 160ms ease, color 160ms ease;\n  }\n\n  .twk-info-panel .twk-close:hover {\n    background: #EAF4FB;\n    color: var(--twk-blue-dark);\n  }\n\n  \/* ------------------------------------------------------------------ *\/\n  \/* CONTROLS                                                            *\/\n  \/* ------------------------------------------------------------------ *\/\n  .twk-controls {\n    position: absolute;\n    bottom: 12px;\n    left: 14px;\n    display: flex;\n    gap: 8px;\n    z-index: 5;\n  }\n\n  .twk-controls button {\n    background: rgba(255, 255, 255, 0.92);\n    border: 1px solid #D6E7F1;\n    color: var(--twk-blue-dark);\n    font-family: 'Poppins', sans-serif;\n    font-weight: 500;\n    font-size: 12px;\n    padding: 5px 12px;\n    border-radius: 8px;\n    cursor: pointer;\n    transition: background 160ms ease, color 160ms ease, border-color 160ms ease;\n  }\n\n  .twk-controls button:hover {\n    background: var(--twk-blue);\n    color: #FFFFFF;\n    border-color: var(--twk-blue);\n  }\n\n  .twk-hint {\n    position: absolute;\n    bottom: 12px;\n    right: 16px;\n    font-family: 'Poppins', sans-serif;\n    font-size: 11px;\n    color: #6a7d87;\n    background: rgba(255, 255, 255, 0.85);\n    padding: 4px 10px;\n    border-radius: 6px;\n    pointer-events: none;\n    z-index: 5;\n    transition: opacity 300ms ease;\n  }\n\n  \/* ------------------------------------------------------------------ *\/\n  \/* BREADCRUMB                                                          *\/\n  \/* ------------------------------------------------------------------ *\/\n  .twk-breadcrumb {\n    position: absolute;\n    top: 12px;\n    left: 14px;\n    font-family: 'Poppins', sans-serif;\n    font-size: 12px;\n    font-weight: 500;\n    color: var(--twk-blue-dark);\n    background: rgba(255, 255, 255, 0.92);\n    padding: 6px 14px;\n    border-radius: 8px;\n    border: 1px solid #D6E7F1;\n    z-index: 5;\n    cursor: pointer;\n    opacity: 0;\n    pointer-events: none;\n    transition: opacity 250ms ease, background 160ms ease;\n  }\n\n  .twk-breadcrumb.is-visible {\n    opacity: 1;\n    pointer-events: auto;\n  }\n\n  .twk-breadcrumb:hover {\n    background: var(--twk-blue);\n    color: #FFFFFF;\n    border-color: var(--twk-blue);\n  }\n\n  .twk-breadcrumb::before {\n    content: '\u2190 ';\n  }\n\n  \/* ------------------------------------------------------------------ *\/\n  \/* RESPONSIVE                                                          *\/\n  \/* ------------------------------------------------------------------ *\/\n  @media (max-width: 1024px) {\n    .twk-bubble-map-stage {\n      aspect-ratio: 4 \/ 3;\n    }\n  }\n\n  @media (max-width: 640px) {\n    .twk-bubble-map-stage {\n      aspect-ratio: 3 \/ 4;\n      min-height: 480px;\n    }\n    .twk-info-panel {\n      top: auto;\n      bottom: 60px;\n      right: 10px;\n      left: 10px;\n      width: auto;\n    }\n    .twk-hint { display: none; }\n  }\n<\/style>\n<\/head>\n<body>\n\n<div class=\"twk-bubble-map-wrapper\" id=\"twk-bubble-map\">\n\n  <div class=\"twk-header\">\n    <h2>Our Conference Team Structure<\/h2>\n    <p>Click a team to explore its structure. Click the background or \"Back\" to return.<\/p>\n  <\/div>\n\n  <div class=\"twk-bubble-map-stage\" id=\"twk-stage\">\n    <svg id=\"twk-svg\" role=\"img\" aria-label=\"TWK Conference team structure interactive bubble map\"><\/svg>\n\n    <div class=\"twk-breadcrumb\" id=\"twk-breadcrumb\" role=\"button\" tabindex=\"0\">Back to Overview<\/div>\n\n    <div class=\"twk-info-panel\" id=\"twk-info-panel\" role=\"dialog\" aria-live=\"polite\" aria-hidden=\"true\">\n      <button class=\"twk-close\" id=\"twk-close\" aria-label=\"Close details\">\u00d7<\/button>\n      <p class=\"twk-panel-tier\" id=\"twk-panel-tier\"><\/p>\n      <h3 id=\"twk-panel-title\"><\/h3>\n      <p id=\"twk-panel-desc\"><\/p>\n      <p class=\"twk-panel-parent\" id=\"twk-panel-parent\"><\/p>\n    <\/div>\n\n    <div class=\"twk-controls\">\n      <button id=\"twk-reset\">Reset Zoom<\/button>\n    <\/div>\n    <div class=\"twk-hint\" id=\"twk-hint\">Click a team to explore<\/div>\n  <\/div>\n\n<\/div>\n\n<!-- ====================================================================\n  DATA: ACF fallback\n  =====================================================================\n  When running in WordPress, the wp_head hook injects:\n    <script>window.twkTeamData = { ... from ACF ... };<\/script>\n  before this file loads. The fallback below is only used for local preview.\n  ==================================================================== -->\n<script>\nif (!window.twkTeamData) {\n  window.twkTeamData = {\n    name: \"Connectional Table\",\n    description: \"The central coordinating body of the TWK Conference, connecting the work of all strategy teams and ministry areas.\",\n    children: [\n      {\n        name: \"Administrative Strategy Team\",\n        description: \"Oversees the operational, financial, and stewardship ministries of the conference.\",\n        children: [\n          { name: \"Trustees\", description: \"Holds in trust the property and assets of the conference.\" },\n          { name: \"Council on Finance & Administration\", description: \"Develops and administers the conference budget.\" },\n          { name: \"Human Resources Committee\", description: \"Guides personnel policies and staffing.\" },\n          { name: \"Equitable Compensation\", description: \"Ensures fair compensation for pastors.\" },\n          { name: \"Board of Pensions & Health Benefits\", description: \"Administers retirement and health benefits.\" },\n          { name: \"Foundation\", description: \"Manages endowments and charitable funds.\" },\n          { name: \"Archives and History\", description: \"Preserves the historical records of the conference.\" }\n        ]\n      },\n      {\n        name: \"Cabinet Strategy Team\",\n        description: \"Supports the Bishop and District Superintendents in their oversight of conference ministry.\",\n        children: [\n          { name: \"District Trustees\", description: \"Manages district-level property and assets.\" },\n          { name: \"District Lay Leader\", description: \"Represents lay voice at the district level.\" },\n          { name: \"Higher Education\", description: \"Connects with United Methodist higher education institutions.\" },\n          { name: \"Chair of Superintendents Committee\", description: \"Coordinates the work of district superintendents.\" },\n          { name: \"District Board of Location and Building\", description: \"Oversees church building and location decisions.\" },\n          {\n            name: \"District Operational Team\",\n            description: \"Manages day-to-day district operations.\",\n            children: [\n              { name: \"District Committee on Ministry\", description: \"Oversees candidacy and licensing in the district.\" }\n            ]\n          }\n        ]\n      },\n      {\n        name: \"Justice & Mercy Strategy Team\",\n        description: \"Leads the conference in acts of justice, mercy, and compassion.\",\n        children: [\n          { name: \"Anti-Racism Coalition\", description: \"Works to dismantle racism and build Beloved Community.\" },\n          { name: \"Commission on Religion & Race\", description: \"Advocates for racial inclusion and equity.\" },\n          { name: \"Commission on Status & Role of Women\", description: \"Advocates for the full participation of women.\" },\n          { name: \"Church and Society\", description: \"Engages the public witness of the church.\" },\n          { name: \"Creation Care\", description: \"Encourages stewardship of God's creation.\" },\n          { name: \"Disaster Response\", description: \"Coordinates relief and recovery efforts.\" },\n          { name: \"Ethnic and Local Church Concerns\", description: \"Strengthens ethnic local church ministry.\" },\n          { name: \"Hispanic\/Latino\/Indigenous Ministries\", description: \"Supports Hispanic, Latino, and Indigenous ministries.\" },\n          { name: \"LGBTQ+ Inclusion\", description: \"Works toward full inclusion of LGBTQ+ people.\" },\n          { name: \"Caucus Groups\", description: \"Supports various caucus group ministries.\" },\n          { name: \"Covenant Entities\", description: \"Partners with covenant organizations.\" },\n          { name: \"CONAM\", description: \"Committee on Native American Ministries.\" }\n        ]\n      },\n      {\n        name: \"Faith & Innovation Guide Team\",\n        description: \"Cultivates new and innovative expressions of ministry.\",\n        children: [\n          { name: \"Thriving Congregations\", description: \"Supports congregational renewal and revitalization.\" },\n          { name: \"Mission Spark\", description: \"Launches new faith communities and church plants.\" },\n          { name: \"Developing Innovators\", description: \"Nurtures innovative ministry leaders.\" }\n        ]\n      },\n      {\n        name: \"Communications Strategy Team\",\n        description: \"Shares the conference story and equips churches with communications resources.\",\n        children: [\n          { name: \"Connect\", description: \"Conference communications and connection ministries.\" },\n          { name: \"Research & Evaluation\", description: \"Gathers data to guide strategic decisions.\" },\n          {\n            name: \"Annual Conference Planning\",\n            description: \"Plans the annual conference session.\",\n            children: [\n              { name: \"Resolutions\", description: \"Reviews resolutions submitted to annual conference.\" },\n              { name: \"Standing Rules\", description: \"Maintains the standing rules of conference proceedings.\" }\n            ]\n          }\n        ]\n      },\n      {\n        name: \"Equip Strategy Team\",\n        description: \"Equips lay and clergy leaders for effective ministry.\",\n        children: [\n          { name: \"Board of Ordained Ministry\", description: \"Oversees clergy candidacy, credentialing, and care.\" },\n          { name: \"Board of Laity\", description: \"Equips and advocates for lay leadership.\" },\n          { name: \"Higher Education & Campus Ministry\", description: \"Supports campus ministries and UM colleges.\" },\n          {\n            name: \"Camp and Retreat\",\n            description: \"Provides transformative camp and retreat experiences.\",\n            children: [\n              { name: \"Lakeshore\", description: \"Lakeshore camp and retreat center.\" },\n              { name: \"Cedar Crest Camp\", description: \"Cedar Crest camp facility.\" },\n              { name: \"Beersheba Springs Assembly\", description: \"Beersheba Springs assembly grounds.\" }\n            ]\n          },\n          {\n            name: \"Safe Spaces\",\n            description: \"Protects children, youth, and vulnerable adults.\",\n            children: [\n              { name: \"Safe Sanctuaries\", description: \"Safe Sanctuaries policy and training.\" }\n            ]\n          },\n          { name: \"Youth Ministry\", description: \"Conference-wide youth ministry support.\" },\n          { name: \"Children's Ministry\", description: \"Resources for children's ministry.\" },\n          { name: \"United Methodist Men\", description: \"Supports the ministry of United Methodist Men.\" },\n          { name: \"United Women of Faith\", description: \"Supports the ministry of United Women in Faith.\" },\n          {\n            name: \"Conference Relations Committee\",\n            description: \"Handles conference relations matters.\"\n          }\n        ]\n      },\n      {\n        name: \"Mental Health & Well-Being Guide Team\",\n        description: \"Supports mental health awareness and well-being across the conference.\",\n        children: []\n      }\n    ]\n  };\n}\n<\/script>\n\n<!-- ====================================================================\n  RENDER SCRIPT\n  ==================================================================== -->\n<script>\n(function renderTwkBubbleMap() {\n  \/* ----------------------------------------------------------------\n   * GUARD: wait for data\n   * -------------------------------------------------------------- *\/\n  if (!window.twkTeamData) {\n    document.addEventListener('DOMContentLoaded', renderTwkBubbleMap);\n    return;\n  }\n\n  const data = window.twkTeamData;\n\n  \/* ----------------------------------------------------------------\n   * CONSTANTS\n   * -------------------------------------------------------------- *\/\n  const VIEW_W = 1200;\n  const VIEW_H = 675;\n  const CX = VIEW_W \/ 2;\n  const CY = VIEW_H \/ 2;\n\n  const ANIM_DUR = 500; \/\/ ms for transitions\n\n  \/* ----------------------------------------------------------------\n   * COLOR PALETTE\n   * Guide team colors are looked up by name. If a name doesn't match,\n   * it inherits its parent's color. Edit the keys below to match\n   * your ACF Guide Team names exactly.\n   * -------------------------------------------------------------- *\/\n  const ROOT_COLOR = '#299BD7';\n\n  const GUIDE_PALETTE = {\n    'Administrative Guide Team':              '#0F766E',\n    'Connection Guide Team':                  '#5B21B6',\n    'Leadership Development Guide Team':      '#B45309',\n    'Faith & Innovation Guide Team':          '#166534',\n    'Justice & Mercy Guide Team':             '#9F1239',\n    'Mental Health & Well-Being Guide Team':  '#0E7490',\n    'Cabinet':                                '#2563EB',\n};\n\n  \/* ----------------------------------------------------------------\n   * HELPERS: color math\n   * -------------------------------------------------------------- *\/\n  function hexToRgb(hex) {\n    const h = hex.replace('#', '');\n    return [parseInt(h.slice(0,2),16), parseInt(h.slice(2,4),16), parseInt(h.slice(4,6),16)];\n  }\n  function rgbToHex(r,g,b) {\n    const x = n => Math.max(0, Math.min(255, Math.round(n))).toString(16).padStart(2,'0');\n    return `#${x(r)}${x(g)}${x(b)}`;\n  }\n  function rgbToHsl([r,g,b]) {\n    r\/=255; g\/=255; b\/=255;\n    const mx=Math.max(r,g,b), mn=Math.min(r,g,b);\n    let h=0, s=0, l=(mx+mn)\/2;\n    if(mx!==mn){\n      const d=mx-mn;\n      s=l>0.5?d\/(2-mx-mn):d\/(mx+mn);\n      if(mx===r) h=(g-b)\/d+(g<b?6:0);\n      else if(mx===g) h=(b-r)\/d+2;\n      else h=(r-g)\/d+4;\n      h\/=6;\n    }\n    return [h,s,l];\n  }\n  function hslToRgb(h,s,l){\n    let r,g,b;\n    if(s===0){r=g=b=l;}\n    else{\n      const q=l<0.5?l*(1+s):l+s-l*s, p=2*l-q;\n      const hue2rgb=(p,q,t)=>{if(t<0)t+=1;if(t>1)t-=1;if(t<1\/6)return p+(q-p)*6*t;if(t<1\/2)return q;if(t<2\/3)return p+(q-p)*(2\/3-t)*6;return p;};\n      r=hue2rgb(p,q,h+1\/3);g=hue2rgb(p,q,h);b=hue2rgb(p,q,h-1\/3);\n    }\n    return [r*255,g*255,b*255];\n  }\n  function shift(hex,dL){\n    const [h,s,l]=rgbToHsl(hexToRgb(hex));\n    const [r,g,b]=hslToRgb(h,s,Math.max(0,Math.min(1,l+dL)));\n    return rgbToHex(r,g,b);\n  }\n  const lighten=(hex,a)=>shift(hex,a);\n  const darken=(hex,a)=>shift(hex,-a);\n\n  \/* ----------------------------------------------------------------\n   * BUILD HIERARCHY & ASSIGN COLORS\n   * -------------------------------------------------------------- *\/\n  const root = d3.hierarchy(data);\n\n  root.each(d => {\n    if (d.depth === 0) {\n      d.color = ROOT_COLOR;\n    } else {\n      let guide = d;\n      while (guide.depth > 1) guide = guide.parent;\n      const base = GUIDE_PALETTE[guide.data.name] || ROOT_COLOR;\n      if (d.depth === 1) d.color = base;\n      else if (d.depth === 2) d.color = lighten(base, 0.08);\n      else d.color = lighten(base, 0.16);\n    }\n    d.hoverColor = darken(d.color, 0.10);\n  });\n\n  \/* ----------------------------------------------------------------\n   * SVG SETUP\n   * -------------------------------------------------------------- *\/\n  const svg = d3.select('#twk-svg')\n    .attr('viewBox', `0 0 ${VIEW_W} ${VIEW_H}`)\n    .attr('preserveAspectRatio', 'xMidYMid meet');\n\n  const defs = svg.append('defs');\n\n  \/\/ Subtle radial gradient for background\n  const bgGrad = defs.append('radialGradient')\n    .attr('id', 'twk-bg-grad')\n    .attr('cx', '50%').attr('cy', '50%').attr('r', '60%');\n  bgGrad.append('stop').attr('offset', '0%').attr('stop-color', '#EAF4FB').attr('stop-opacity', 0.5);\n  bgGrad.append('stop').attr('offset', '100%').attr('stop-color', 'transparent');\n\n  svg.append('rect')\n    .attr('width', VIEW_W).attr('height', VIEW_H)\n    .attr('fill', 'url(#twk-bg-grad)');\n\n  const mainGroup = svg.append('g').attr('class', 'twk-main');\n  const linkGroup = mainGroup.append('g').attr('class', 'twk-links');\n  const nodeGroup = mainGroup.append('g').attr('class', 'twk-nodes');\n\n  \/* ----------------------------------------------------------------\n   * PANEL ELEMENTS\n   * -------------------------------------------------------------- *\/\n  const panel    = document.getElementById('twk-info-panel');\n  const titleEl  = document.getElementById('twk-panel-title');\n  const descEl   = document.getElementById('twk-panel-desc');\n  const tierEl   = document.getElementById('twk-panel-tier');\n  const parentEl = document.getElementById('twk-panel-parent');\n  const closeBtn = document.getElementById('twk-close');\n  const breadcrumb = document.getElementById('twk-breadcrumb');\n  const hintEl   = document.getElementById('twk-hint');\n\n  const TIER_LABELS = {\n    0: 'Conference',\n    1: 'Strategy Team',\n    2: 'Team \/ Board \/ Committee',\n    3: 'Sub-Team',\n    4: 'Sub-Committee'\n  };\n\n  function escapeHtml(s) {\n    return String(s).replace(\/[&<>\"']\/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;',\"'\":'&#39;'}[c]));\n  }\n\n  function showPanel(d) {\n    tierEl.textContent  = TIER_LABELS[d.depth] || 'Team';\n    titleEl.textContent = d.data.name;\n    descEl.textContent  = d.data.description || '';\n    if (d.parent) {\n      parentEl.innerHTML = `Part of <span>${escapeHtml(d.parent.data.name)}<\/span>`;\n      parentEl.style.display = '';\n    } else {\n      parentEl.style.display = 'none';\n    }\n    panel.style.setProperty('--twk-accent', d.color);\n    panel.classList.add('is-visible');\n    panel.setAttribute('aria-hidden', 'false');\n  }\n\n  function hidePanel() {\n    panel.classList.remove('is-visible');\n    panel.setAttribute('aria-hidden', 'true');\n  }\n\n  closeBtn.addEventListener('click', (e) => { e.stopPropagation(); hidePanel(); });\n  document.addEventListener('keydown', (e) => { if (e.key === 'Escape') hidePanel(); });\n\n  \/* ----------------------------------------------------------------\n   * LAYOUT HELPERS\n   * -------------------------------------------------------------- *\/\n\n  \/\/ Place children in a circle around a center point\n  function circleLayout(children, cx, cy, radius, startAngle, endAngle) {\n    const n = children.length;\n    if (n === 0) return;\n    const span = endAngle - startAngle;\n    children.forEach((child, i) => {\n      const angle = n === 1\n        ? startAngle + span \/ 2\n        : startAngle + (i \/ n) * span;\n      child._x = cx + Math.cos(angle) * radius;\n      child._y = cy + Math.sin(angle) * radius;\n    });\n  }\n\n  \/\/ Wrap text into lines\n  function wrapLabel(textSel, text, maxWidth, fontSize) {\n    const words = text.split(\/\\s+\/);\n    textSel.text(null);\n    const lineH = 1.15;\n    let line = [];\n    let tspan = textSel.append('tspan').attr('x', 0).attr('dy', '0em');\n    words.forEach(word => {\n      line.push(word);\n      tspan.text(line.join(' '));\n      if (tspan.node().getComputedTextLength() > maxWidth && line.length > 1) {\n        line.pop();\n        tspan.text(line.join(' '));\n        line = [word];\n        tspan = textSel.append('tspan').attr('x', 0).attr('dy', `${lineH}em`).text(word);\n      }\n    });\n    const tspans = textSel.selectAll('tspan');\n    const total = tspans.size();\n    const offset = -((total - 1) \/ 2) * lineH + 0.33;\n    tspans.each(function(_, i) {\n      d3.select(this).attr('dy', i === 0 ? `${offset}em` : `${lineH}em`);\n    });\n  }\n\n  \/* ----------------------------------------------------------------\n   * STATE\n   * -------------------------------------------------------------- *\/\n  let currentView = 'overview'; \/\/ 'overview' or 'drilldown'\n  let focusedTeam = null;\n\n  \/* ----------------------------------------------------------------\n   * OVERVIEW VIEW: root center + guide teams around it\n   * -------------------------------------------------------------- *\/\n  function renderOverview(animate) {\n    currentView = 'overview';\n    focusedTeam = null;\n    hidePanel();\n    breadcrumb.classList.remove('is-visible');\n    hintEl.textContent = 'Click a team to explore';\n    hintEl.style.opacity = '1';\n\n    const guideTeams = root.children || [];\n    const rootR = Math.min(VIEW_W, VIEW_H) * 0.15;\n    const guideR = Math.min(VIEW_W, VIEW_H) * 0.11;\n    const orbitR = Math.min(VIEW_W, VIEW_H) * 0.36;\n\n    \/\/ Position root\n    root._x = CX;\n    root._y = CY;\n    root._r = rootR;\n    root._fontSize = 18;\n\n    \/\/ Position guide teams in circle\n    circleLayout(guideTeams, CX, CY, orbitR, -Math.PI \/ 2, -Math.PI \/ 2 + 2 * Math.PI);\n    guideTeams.forEach(g => {\n      g._r = guideR;\n      g._fontSize = 12;\n    });\n\n    \/\/ All visible nodes in overview\n    const nodes = [root, ...guideTeams];\n\n    \/\/ Links from root to each guide team\n    const links = guideTeams.map(g => ({ source: root, target: g }));\n\n    drawScene(nodes, links, animate);\n  }\n\n  \/* ----------------------------------------------------------------\n   * DRILLDOWN VIEW: focused team center + its children around it\n   * -------------------------------------------------------------- *\/\n  function renderDrilldown(guideNode, animate) {\n    currentView = 'drilldown';\n    focusedTeam = guideNode;\n    hidePanel();\n    breadcrumb.textContent = `\u2190 Back to Overview`;\n    breadcrumb.classList.add('is-visible');\n    hintEl.textContent = 'Click a bubble to learn more';\n\n    const children = guideNode.children || [];\n    const focusR = Math.min(VIEW_W, VIEW_H) * 0.11;\n    const childR = Math.min(VIEW_W, VIEW_H) * 0.085;\n    const grandchildR = Math.min(VIEW_W, VIEW_H) * 0.055;\n\n    \/\/ Count total items to determine orbit radius\n    let totalGrandchildren = 0;\n    children.forEach(c => {\n      if (c.children) totalGrandchildren += c.children.length;\n    });\n\n    const orbitR = Math.min(VIEW_W * 0.30, VIEW_H * 0.30);\n    const gcOrbitR = childR + grandchildR + 60;\n\n    \/\/ Position focused team at center\n    guideNode._x = CX;\n    guideNode._y = CY;\n    guideNode._r = focusR;\n    guideNode._fontSize = 13;\n\n    \/\/ Position children\n    const startAngle = -Math.PI \/ 2;\n    const endAngle = startAngle + 2 * Math.PI;\n    circleLayout(children, CX, CY, orbitR, startAngle, endAngle - (2 * Math.PI \/ Math.max(children.length, 1)));\n    children.forEach(c => {\n      c._r = childR;\n      c._fontSize = 11;\n    });\n\n    \/\/ Collect all visible nodes and links\n    const nodes = [guideNode];\n    const links = [];\n\n    children.forEach(child => {\n      nodes.push(child);\n      links.push({ source: guideNode, target: child });\n\n      \/\/ Grandchildren (4th tier)\n      if (child.children && child.children.length > 0) {\n        const gcs = child.children;\n        \/\/ Fan grandchildren outward from the child\n        const childAngle = Math.atan2(child._y - CY, child._x - CX);\n        const gcSpread = Math.min(Math.PI * 1.0, gcs.length * 0.45);\n        const gcStart = childAngle - gcSpread \/ 2;\n        const gcEnd = childAngle + gcSpread \/ 2;\n\n        circleLayout(gcs, child._x, child._y, gcOrbitR, gcStart, gcEnd);\n        gcs.forEach(gc => {\n          gc._r = grandchildR;\n          gc._fontSize = 9;\n          nodes.push(gc);\n          links.push({ source: child, target: gc });\n        });\n      }\n    });\n\n    drawScene(nodes, links, animate);\n  }\n\n  \/* ----------------------------------------------------------------\n   * DRAW SCENE: render nodes + links with optional animation\n   * -------------------------------------------------------------- *\/\n  function drawScene(nodes, links, animate) {\n    const dur = animate ? ANIM_DUR : 0;\n\n    \/\/ --- LINKS ---\n    const linkSel = linkGroup.selectAll('path.twk-link-line')\n      .data(links, d => d.source.data.name + '\u2192' + d.target.data.name);\n\n    linkSel.exit()\n      .transition().duration(dur).attr('stroke-opacity', 0).remove();\n\n    const linkEnter = linkSel.enter()\n      .append('path')\n      .attr('class', 'twk-link-line')\n      .attr('stroke-opacity', 0);\n\n    linkSel.merge(linkEnter)\n      .attr('stroke', d => lighten(d.target.color, 0.25))\n      .transition().duration(dur)\n      .attr('d', d => {\n        const sx = d.source._x, sy = d.source._y;\n        const tx = d.target._x, ty = d.target._y;\n        const mx = (sx + tx) \/ 2, my = (sy + ty) \/ 2;\n        const px = (CX - mx) * 0.08, py = (CY - my) * 0.08;\n        return `M ${sx},${sy} Q ${mx + px},${my + py} ${tx},${ty}`;\n      })\n      .attr('stroke-opacity', 0.7);\n\n    \/\/ --- NODES ---\n    const nodeSel = nodeGroup.selectAll('g.twk-bubble')\n      .data(nodes, d => d.data.name + '-' + d.depth);\n\n    \/\/ EXIT\n    nodeSel.exit()\n      .transition().duration(dur)\n      .attr('opacity', 0)\n      .attr('transform', d => `translate(${d._x || CX},${d._y || CY}) scale(0.3)`)\n      .remove();\n\n    \/\/ ENTER\n    const nodeEnter = nodeSel.enter()\n      .append('g')\n      .attr('class', 'twk-bubble')\n      .attr('opacity', 0)\n      .attr('transform', d => `translate(${d._x},${d._y}) scale(0.3)`)\n      .attr('tabindex', 0)\n      .attr('role', 'button')\n      .attr('aria-label', d => d.data.name)\n      .style('cursor', 'pointer');\n\n    nodeEnter.append('circle')\n      .attr('class', 'twk-circle')\n      .attr('r', d => d._r);\n\n    nodeEnter.append('text')\n      .attr('class', 'twk-label');\n\n    \/\/ MERGE (enter + update)\n    const nodeMerge = nodeSel.merge(nodeEnter);\n\n    nodeMerge\n      .transition().duration(dur)\n      .attr('opacity', 1)\n      .attr('transform', d => `translate(${d._x},${d._y}) scale(1)`);\n\n    nodeMerge.select('circle')\n      .transition().duration(dur)\n      .attr('r', d => d._r)\n      .attr('fill', d => d.color);\n\n    nodeMerge.select('text')\n      .attr('font-size', d => d._fontSize)\n      .each(function(d) {\n        wrapLabel(d3.select(this), d.data.name, d._r * 1.7, d._fontSize);\n      });\n\n    \/\/ EVENT HANDLERS \u2014 re-bindto merged selection\n    nodeMerge\n      .on('click', null)\n      .on('keydown', null)\n      .on('click', (event, d) => {\n        event.stopPropagation();\n\n        if (currentView === 'overview' && d.depth === 0) {\n          \/\/ Click on root in overview: show info\n          showPanel(d);\n        } else if (currentView === 'overview' && d.depth === 1) {\n          \/\/ Click on guide team: drill down\n          renderDrilldown(d, true);\n        } else {\n          \/\/ In drilldown, click on any bubble: show info\n          showPanel(d);\n        }\n      })\n      .on('keydown', (event, d) => {\n        if (event.key === 'Enter' || event.key === ' ') {\n          event.preventDefault();\n          if (currentView === 'overview' && d.depth === 1) {\n            renderDrilldown(d, true);\n          } else {\n            showPanel(d);\n          }\n        }\n      });\n  }\n\n  \/* ----------------------------------------------------------------\n   * BACKGROUND CLICK: go back\n   * -------------------------------------------------------------- *\/\n  svg.on('click', () => {\n    if (currentView === 'drilldown') {\n      renderOverview(true);\n    } else {\n      hidePanel();\n    }\n  });\n\n  \/* ----------------------------------------------------------------\n   * BREADCRUMB: go back\n   * -------------------------------------------------------------- *\/\n  breadcrumb.addEventListener('click', (e) => {\n    e.stopPropagation();\n    renderOverview(true);\n  });\n  breadcrumb.addEventListener('keydown', (e) => {\n    if (e.key === 'Enter' || e.key === ' ') {\n      e.preventDefault();\n      renderOverview(true);\n    }\n  });\n\n  \/* ----------------------------------------------------------------\n   * ZOOM + PAN\n   * -------------------------------------------------------------- *\/\n  const zoom = d3.zoom()\n    .scaleExtent([0.5, 3])\n    .on('zoom', (event) => {\n      mainGroup.attr('transform', event.transform);\n    });\n\n  svg.call(zoom);\n\n  document.getElementById('twk-reset').addEventListener('click', (e) => {\n    e.stopPropagation();\n    svg.transition().duration(400).call(zoom.transform, d3.zoomIdentity);\n  });\n\n  \/* ----------------------------------------------------------------\n   * INITIAL RENDER\n   * -------------------------------------------------------------- *\/\n  renderOverview(false);\n\n})();\n<\/script>\n\n<\/body>\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>TWK Conference Team Structure Our Conference Team Structure Click a team to explore its structure. Click the background or &#8220;Back&#8221; to return. Back to Overview \u00d7 Reset Zoom Click a [&hellip;]<\/p>\n","protected":false},"author":6,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"footnotes":""},"tags":[],"class_list":["post-44102","page","type-page","status-publish","hentry"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Ministry Team Bubble Map - TWKUMC<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/twkumc.org\/ko\/ministry-team-bubble-map\/\" \/>\n<meta property=\"og:locale\" content=\"ko_KR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Ministry Team Bubble Map - TWKUMC\" \/>\n<meta property=\"og:description\" content=\"TWK Conference Team Structure Our Conference Team Structure Click a team to explore its structure. Click the background or &#8220;Back&#8221; to return. Back to Overview \u00d7 Reset Zoom Click a [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/twkumc.org\/ko\/ministry-team-bubble-map\/\" \/>\n<meta property=\"og:site_name\" content=\"TWKUMC\" \/>\n<meta property=\"article:modified_time\" content=\"2026-04-29T17:00:17+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\uc608\uc0c1 \ub418\ub294 \ud310\ub3c5 \uc2dc\uac04\" \/>\n\t<meta name=\"twitter:data1\" content=\"1\ubd84\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/twkumc.org\/ministry-team-bubble-map\/\",\"url\":\"https:\/\/twkumc.org\/ministry-team-bubble-map\/\",\"name\":\"Ministry Team Bubble Map - TWKUMC\",\"isPartOf\":{\"@id\":\"https:\/\/twkumc.org\/#website\"},\"datePublished\":\"2026-04-27T17:14:18+00:00\",\"dateModified\":\"2026-04-29T17:00:17+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/twkumc.org\/ministry-team-bubble-map\/#breadcrumb\"},\"inLanguage\":\"ko-KR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/twkumc.org\/ministry-team-bubble-map\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/twkumc.org\/ministry-team-bubble-map\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/twkumc.org\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Ministry Team Bubble Map\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/twkumc.org\/#website\",\"url\":\"https:\/\/twkumc.org\/\",\"name\":\"TWKUMC\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/twkumc.org\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/twkumc.org\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"ko-KR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/twkumc.org\/#organization\",\"name\":\"TWKUMC\",\"url\":\"https:\/\/twkumc.org\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\/\/twkumc.org\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/twkumc.org\/wp-content\/uploads\/2025\/02\/TWK-Full_ColorBlack.webp\",\"contentUrl\":\"https:\/\/twkumc.org\/wp-content\/uploads\/2025\/02\/TWK-Full_ColorBlack.webp\",\"width\":2340,\"height\":478,\"caption\":\"TWKUMC\"},\"image\":{\"@id\":\"https:\/\/twkumc.org\/#\/schema\/logo\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Ministry Team Bubble Map - TWKUMC","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/twkumc.org\/ko\/ministry-team-bubble-map\/","og_locale":"ko_KR","og_type":"article","og_title":"Ministry Team Bubble Map - TWKUMC","og_description":"TWK Conference Team Structure Our Conference Team Structure Click a team to explore its structure. Click the background or &#8220;Back&#8221; to return. Back to Overview \u00d7 Reset Zoom Click a [&hellip;]","og_url":"https:\/\/twkumc.org\/ko\/ministry-team-bubble-map\/","og_site_name":"TWKUMC","article_modified_time":"2026-04-29T17:00:17+00:00","twitter_card":"summary_large_image","twitter_misc":{"\uc608\uc0c1 \ub418\ub294 \ud310\ub3c5 \uc2dc\uac04":"1\ubd84"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/twkumc.org\/ministry-team-bubble-map\/","url":"https:\/\/twkumc.org\/ministry-team-bubble-map\/","name":"Ministry Team Bubble Map - TWKUMC","isPartOf":{"@id":"https:\/\/twkumc.org\/#website"},"datePublished":"2026-04-27T17:14:18+00:00","dateModified":"2026-04-29T17:00:17+00:00","breadcrumb":{"@id":"https:\/\/twkumc.org\/ministry-team-bubble-map\/#breadcrumb"},"inLanguage":"ko-KR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/twkumc.org\/ministry-team-bubble-map\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/twkumc.org\/ministry-team-bubble-map\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/twkumc.org\/"},{"@type":"ListItem","position":2,"name":"Ministry Team Bubble Map"}]},{"@type":"WebSite","@id":"https:\/\/twkumc.org\/#website","url":"https:\/\/twkumc.org\/","name":"TWKUMC","description":"","publisher":{"@id":"https:\/\/twkumc.org\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/twkumc.org\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"ko-KR"},{"@type":"Organization","@id":"https:\/\/twkumc.org\/#organization","name":"TWKUMC","url":"https:\/\/twkumc.org\/","logo":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/twkumc.org\/#\/schema\/logo\/image\/","url":"https:\/\/twkumc.org\/wp-content\/uploads\/2025\/02\/TWK-Full_ColorBlack.webp","contentUrl":"https:\/\/twkumc.org\/wp-content\/uploads\/2025\/02\/TWK-Full_ColorBlack.webp","width":2340,"height":478,"caption":"TWKUMC"},"image":{"@id":"https:\/\/twkumc.org\/#\/schema\/logo\/image\/"}}]}},"publishpress_future_action":{"enabled":false,"date":"2026-05-07 09:20:41","action":"change-status","newStatus":"draft","terms":[],"taxonomy":"post_tag","extraData":[]},"publishpress_future_workflow_manual_trigger":{"enabledWorkflows":[]},"_links":{"self":[{"href":"https:\/\/twkumc.org\/ko\/wp-json\/wp\/v2\/pages\/44102","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/twkumc.org\/ko\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/twkumc.org\/ko\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/twkumc.org\/ko\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/twkumc.org\/ko\/wp-json\/wp\/v2\/comments?post=44102"}],"version-history":[{"count":31,"href":"https:\/\/twkumc.org\/ko\/wp-json\/wp\/v2\/pages\/44102\/revisions"}],"predecessor-version":[{"id":44350,"href":"https:\/\/twkumc.org\/ko\/wp-json\/wp\/v2\/pages\/44102\/revisions\/44350"}],"wp:attachment":[{"href":"https:\/\/twkumc.org\/ko\/wp-json\/wp\/v2\/media?parent=44102"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/twkumc.org\/ko\/wp-json\/wp\/v2\/tags?post=44102"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}