// volunteering.jsx — Globally Volunteering
// Loaded after globly.jsx, before app.jsx. Uses React.* directly (like globly.jsx).
// Architecturally isolated: all components/state live here; integration into the
// main app is a single render swap + a hash-prefix match in globly.jsx.
//
// Exposes globals: VolunteeringApp (rendered by globly.jsx) and
// VolunteeringMegaMenu (used by the header). Data comes from window.VOL.

// ─── tiny inline icons (avoid coupling to lucide load order) ──────────────────
function VIco(props) {
  var n = props.name, s = props.size || 16, sw = props.stroke || 1.9;
  var p = { width: s, height: s, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor",
    strokeWidth: sw, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true" };
  var paths = {
    arrow:    <React.Fragment><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></React.Fragment>,
    back:     <React.Fragment><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></React.Fragment>,
    search:   <React.Fragment><circle cx="11" cy="11" r="7"/><line x1="16.5" y1="16.5" x2="21" y2="21"/></React.Fragment>,
    bookmark: <path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/>,
    clock:    <React.Fragment><circle cx="12" cy="12" r="9"/><polyline points="12 7 12 12 15 14"/></React.Fragment>,
    globe:    <React.Fragment><circle cx="12" cy="12" r="9"/><line x1="3" y1="12" x2="21" y2="12"/><path d="M12 3a15 15 0 0 1 0 18 15 15 0 0 1 0-18z"/></React.Fragment>,
    pin:      <React.Fragment><path d="M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0z"/><circle cx="12" cy="10" r="3"/></React.Fragment>,
    remote:   <React.Fragment><rect x="2" y="4" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="18" x2="12" y2="21"/></React.Fragment>,
    check:    <polyline points="20 6 9 17 4 12"/>,
    x:        <React.Fragment><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></React.Fragment>,
    chevron:  <polyline points="9 6 15 12 9 18"/>,
    users:    <React.Fragment><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/></React.Fragment>,
    spark:    <path d="M12 3l1.9 5.1L19 10l-5.1 1.9L12 17l-1.9-5.1L5 10l5.1-1.9z"/>,
    info:     <React.Fragment><circle cx="12" cy="12" r="9"/><line x1="12" y1="11" x2="12" y2="16"/><line x1="12" y1="8" x2="12.01" y2="8"/></React.Fragment>,
    layers:   <React.Fragment><polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/></React.Fragment>,
    filter:   <polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/>,
    plus:     <React.Fragment><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></React.Fragment>,
    ext:      <React.Fragment><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></React.Fragment>,
    heart:    <path d="M20.8 4.6a5.5 5.5 0 0 0-7.8 0L12 5.6l-1-1a5.5 5.5 0 0 0-7.8 7.8l1 1L12 21l7.8-7.6 1-1a5.5 5.5 0 0 0 0-7.8z"/>,
    eye:      <React.Fragment><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></React.Fragment>,
    send:     <React.Fragment><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></React.Fragment>,
    building: <React.Fragment><rect x="4" y="3" width="16" height="18" rx="1"/><line x1="9" y1="7" x2="9" y2="7.01"/><line x1="15" y1="7" x2="15" y2="7.01"/><line x1="9" y1="11" x2="9" y2="11.01"/><line x1="15" y1="11" x2="15" y2="11.01"/><line x1="9" y1="15" x2="15" y2="15"/></React.Fragment>,
    book:     <React.Fragment><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></React.Fragment>,
    shield:   <React.Fragment><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><polyline points="9 12 11 14 15 10"/></React.Fragment>,
    puzzle:   <path d="M20.5 11H19V7a2 2 0 0 0-2-2h-4V3.5a2.5 2.5 0 0 0-5 0V5H4a2 2 0 0 0-2 2v3.8h1.5a2.2 2.2 0 1 1 0 4.4H2V19a2 2 0 0 0 2 2h3.8v-1.5a2.2 2.2 0 1 1 4.4 0V21H17a2 2 0 0 0 2-2v-4h1.5a2.5 2.5 0 0 0 0-5z"/>,
    chart:    <React.Fragment><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></React.Fragment>,
    hand:     <path d="M18 11V6a2 2 0 0 0-4 0v4m4 1V5a2 2 0 0 0-4 0v5m0 0V4a2 2 0 0 0-4 0v9m-2-3a2 2 0 0 0-2 2c0 3 3 7 8 7a7 7 0 0 0 7-7v-2a2 2 0 0 0-4 0"/>,
    leaf:     <React.Fragment><path d="M11 20A7 7 0 0 1 4 13c0-6 8-11 16-11 0 8-5 16-11 16z"/><path d="M4 20c4-4 8-6 12-7"/></React.Fragment>,
    edit:     <React.Fragment><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.1 2.1 0 0 1 3 3L12 15l-4 1 1-4z"/></React.Fragment>,
    star:     <path d="M12 2l2.3 6.9H21l-5.4 4 2 6.5-5.6-4-5.6 4 2-6.5-5.4-4h6.7z"/>
  };
  return React.createElement("svg", p, paths[n] || null);
}

// ─── access + saved helpers ───────────────────────────────────────────────────
function volSignedIn() {
  try { return (typeof _accessState !== "undefined" && _accessState && _accessState.signedIn) === true; }
  catch (e) { return false; }
}
var VOL_SAVE_KEY = "globally_saved_volunteering";
function volLoadSaved() {
  try { var o = JSON.parse(localStorage.getItem(VOL_SAVE_KEY) || "{}"); return (o && typeof o === "object") ? o : {}; }
  catch (e) { return {}; }
}
function volWriteSaved(map) { try { localStorage.setItem(VOL_SAVE_KEY, JSON.stringify(map)); } catch (e) {} }

// Lightweight, privacy-respecting event hook (no third-party analytics — Globally
// deliberately runs none). Kept as a safe no-op seam for future first-party use.
function volTrack(evt, data) { try { if (window.__VOL_DEBUG) console.debug("[vol]", evt, data || {}); } catch (e) {} }

// ─── hash helpers ─────────────────────────────────────────────────────────────
function volQs(params) {
  if (!params) return "";
  return Object.keys(params).filter(function (k) {
    var v = params[k];
    if (v == null || v === "" || v === false) return false;
    if (Array.isArray(v) && !v.length) return false;
    return true;
  }).map(function (k) {
    var v = params[k]; if (Array.isArray(v)) v = v.join(",");
    return encodeURIComponent(k) + "=" + encodeURIComponent(v);
  }).join("&");
}
function volBuildHash(sub, arg, params) {
  var h = "#/volunteering";
  if (sub && sub !== "home") h += "/" + sub;
  if (arg) h += "/" + encodeURIComponent(arg);
  var qs = volQs(params);
  if (qs) h += "?" + qs;
  return h;
}
function volGo(sub, arg, params) { window.location.hash = volBuildHash(sub, arg, params); }
function volParseHash() {
  var raw = (window.location.hash || "").replace(/^#/, "");
  var qi = raw.indexOf("?");
  var path = qi >= 0 ? raw.slice(0, qi) : raw;
  var query = qi >= 0 ? raw.slice(qi + 1) : "";
  var parts = path.split("/").filter(Boolean); // ['volunteering', sub, arg?]
  var sub = parts[1] || "home";
  var arg = parts[2] ? decodeURIComponent(parts[2]) : null;
  var params = {};
  query.split("&").forEach(function (kv) {
    if (!kv) return; var i = kv.indexOf("=");
    var k = i >= 0 ? kv.slice(0, i) : kv; var v = i >= 0 ? kv.slice(i + 1) : "";
    try { params[decodeURIComponent(k)] = decodeURIComponent(v); } catch (e) { params[k] = v; }
  });
  return { sub: sub, arg: arg, params: params };
}

// ─── small shared UI ──────────────────────────────────────────────────────────
function VolModeLabel(mode) { return mode === "remote" ? "Remote" : mode === "hybrid" ? "Hybrid" : "In person"; }

function VolCausePill(props) {
  var VOL = window.VOL, o = props.opp;
  var color = VOL.topicColor(o.cause);
  return (
    <span className="vol-cause-pill" style={{ background: color + "1f", color: shadeText(color) }}>
      <span className="vol-pill-dot" style={{ background: color }} /> {o.cause}
    </span>
  );
}
// Darken a hex a touch for readable text on faint tint
function shadeText(hex) {
  try {
    var c = hex.replace("#", "");
    var r = parseInt(c.substr(0, 2), 16), g = parseInt(c.substr(2, 2), 16), b = parseInt(c.substr(4, 2), 16);
    r = Math.round(r * 0.55); g = Math.round(g * 0.55); b = Math.round(b * 0.55);
    return "rgb(" + r + "," + g + "," + b + ")";
  } catch (e) { return "#46413A"; }
}

function VolStatus(props) {
  var st = props.status;
  return <span className={"vol-status vol-status--" + st.id}><span className="vol-pill-dot" />{st.label}</span>;
}

function VolSaveButton(props) {
  var saved = props.saved;
  return (
    <button className={"vol-save" + (saved ? " is-saved" : "")}
      onClick={function (e) { e.stopPropagation(); props.onToggle(); }}
      aria-pressed={saved} aria-label={saved ? "Remove from saved" : "Save opportunity"} title={saved ? "Saved" : "Save"}>
      <VIco name="bookmark" size={16} />
    </button>
  );
}

function VolOpportunityCard(props) {
  var VOL = window.VOL, o = props.opp;
  var st = VOL.statusFor(o);
  var loc = o.mode === "remote" ? "Remote" : (o.country || "Multiple") + (o.mode === "hybrid" ? " · Hybrid" : "");
  return (
    <div className="vol-opp" role="button" tabIndex={0}
      onClick={function () { props.onOpen(o); }}
      onKeyDown={function (e) { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); props.onOpen(o); } }}>
      <div className="vol-opp-top">
        <VolCausePill opp={o} />
        <span className="vol-pill"><span className="vol-pill-dot" style={{ background: o.mode === "remote" ? "#2f7d4d" : o.mode === "hybrid" ? "#b5701e" : "#0F4B35" }} />{VolModeLabel(o.mode)}</span>
        <span style={{ flex: 1 }} />
        {props.onToggleSave && <VolSaveButton saved={props.saved} onToggle={function () { props.onToggleSave(o); }} />}
      </div>
      <div>
        <h3 className="vol-opp-role">{o.role}</h3>
        <p className="vol-opp-org">{o.organisation}<span className="vol-muted" style={{ fontWeight: 500 }}> · {o.orgType}</span></p>
      </div>
      <div className="vol-opp-meta">
        <span><VIco name="pin" size={14} /> {loc}</span>
        <span><VIco name="clock" size={14} /> {o.timeText}</span>
        {o.durationText && <span><VIco name="layers" size={14} /> {o.durationText}</span>}
      </div>
      <div className="vol-opp-skills">
        {(o.skills || []).slice(0, 3).map(function (s) { return <span key={s} className="vol-tag">{s}</span>; })}
      </div>
      {props.reasons && props.reasons.length > 0 && (
        <div className="vol-card" style={{ background: "var(--vol-surface-2)", boxShadow: "none", padding: 12 }}>
          <p className="vol-mega-feature-lab" style={{ color: "var(--vol-orange)" }}>Why this may fit</p>
          <div className="vol-opp-skills">
            {props.reasons.slice(0, 4).map(function (r, i) {
              return <span key={i} className="vol-tag" title={r.why}><VIco name="check" size={12} /> {r.k}</span>;
            })}
          </div>
        </div>
      )}
      <div className="vol-opp-foot">
        <VolStatus status={st} />
        <span className="vol-opp-view">View opportunity <VIco name="arrow" size={14} /></span>
      </div>
    </div>
  );
}

function VolDemoNotice(props) {
  return (
    <div className="vol-notice" role="note">
      <VIco name="info" size={16} />
      <span>{props.text || window.VOL.DEMO_NOTICE}</span>
    </div>
  );
}

// A reusable list that opens the detail route and wires saving.
function VolOppList(props) {
  var items = props.items || [];
  if (!items.length) {
    return (
      <div className="vol-empty">
        <div className="vol-empty-ico"><VIco name="search" size={22} /></div>
        <p className="vol-h3" style={{ marginBottom: 6 }}>{props.emptyTitle || "Nothing matches yet"}</p>
        <p className="vol-muted">{props.emptyBody || "Try widening your filters or clearing a choice."}</p>
      </div>
    );
  }
  return (
    <div className={"vol-grid " + (props.cols || "vol-grid--2")}>
      {items.map(function (it) {
        var o = it.opp ? it.opp : it;
        return <VolOpportunityCard key={o.id} opp={o} reasons={it.reasons}
          onOpen={function () { volGo("opportunity", o.id); }}
          saved={props.isSaved ? props.isSaved(o.id) : false}
          onToggleSave={props.onToggleSave} />;
      })}
    </div>
  );
}

// ─── world map (pale, stylised equirectangular composition) ───────────────────
var VOL_COORDS = {
  "Sri Lanka": [7.9, 80.8], "India": [22, 79], "Pakistan": [30, 69], "Nepal": [28.4, 84.1],
  "Bangladesh": [23.7, 90.4], "Afghanistan": [33.9, 67.7], "Maldives": [3.2, 73], "Bhutan": [27.5, 90.4],
  "Indonesia": [-2.5, 118], "Philippines": [12.9, 121.8], "Vietnam": [16, 108], "Cambodia": [12.5, 105],
  "Thailand": [15, 101], "Myanmar": [21, 96], "Malaysia": [4.2, 101.9], "Singapore": [1.35, 103.8],
  "Jordan": [31, 36.2], "Lebanon": [33.9, 35.5], "Turkey": [39, 35], "Iraq": [33.2, 43.7],
  "Palestine": [31.9, 35.2], "Syria": [35, 38], "Yemen": [15.5, 48], "Iran": [32, 53],
  "Kenya": [0.2, 37.9], "Nigeria": [9.1, 8.7], "Ghana": [7.9, -1], "Ethiopia": [9.1, 40.5],
  "Rwanda": [-1.9, 29.9], "Uganda": [1.4, 32.3], "South Africa": [-30.6, 22.9], "Tanzania": [-6.4, 34.9],
  "Sudan": [15.5, 30], "Somalia": [5.2, 46.2], "Mali": [17.6, -4], "Senegal": [14.5, -14.5],
  "Egypt": [26.8, 30.8], "Morocco": [31.8, -7.1], "Mozambique": [-18.7, 35.5], "Zimbabwe": [-19, 29.9],
  "Democratic Republic of Congo": [-4, 21.8], "Cameroon": [7.4, 12.4],
  "Brazil": [-10, -53], "Colombia": [4.6, -74.3], "Peru": [-9.2, -75], "Chile": [-35.7, -71.5],
  "Argentina": [-38.4, -63.6], "Guatemala": [15.8, -90.2], "Haiti": [18.9, -72.3], "Bolivia": [-16.3, -63.6],
  "Mexico": [23.6, -102.5], "Ecuador": [-1.8, -78.2], "Honduras": [15.2, -86.2],
  "China": [35.9, 104.2], "Japan": [36.2, 138.3], "Mongolia": [46.9, 103.8], "South Korea": [36.5, 127.9],
  "Ukraine": [48.4, 31.2], "Greece": [39.1, 21.8], "Moldova": [47.4, 28.4], "Serbia": [44, 21],
  "Germany": [51.2, 10.5], "France": [46.2, 2.2], "United Kingdom": [54, -2], "Poland": [51.9, 19.1],
  "Italy": [41.9, 12.6], "Spain": [40.2, -3.7], "Romania": [45.9, 24.9], "Sweden": [60.1, 18.6],
  "United States": [39.8, -98.6], "Canada": [56.1, -106.3]
};
function volProject(lat, lon, W, H) {
  return { x: (lon + 180) / 360 * W, y: (90 - lat) / 180 * H };
}
function VolWorldMap(props) {
  var W = 1000, H = 500;
  var counts = props.counts || {};
  var selected = props.selected;
  var maxCount = 1;
  Object.keys(counts).forEach(function (c) { if (counts[c] > maxCount) maxCount = counts[c]; });
  // Stylised continents (soft blobs) — a pale composition, not a precise atlas.
  var continents = [
    "M120,110 C170,80 250,85 300,120 C330,150 320,200 280,235 C240,265 190,255 165,220 C140,190 100,150 120,110 Z",
    "M300,300 C330,275 370,285 385,330 C400,380 380,430 345,455 C315,470 295,440 295,400 C295,360 285,325 300,300 Z",
    "M470,95 C520,80 560,95 575,120 C585,145 560,165 525,165 C495,165 460,140 470,95 Z",
    "M500,200 C545,180 600,190 615,240 C630,300 600,360 555,375 C520,385 500,340 498,290 C497,250 480,220 500,200 Z",
    "M620,110 C700,80 820,90 870,140 C900,175 880,220 820,235 C740,255 660,220 630,180 C612,155 600,125 620,110 Z",
    "M820,360 C855,345 895,355 905,385 C915,415 885,435 855,430 C828,425 805,395 820,360 Z"
  ];
  var markerCountries = Object.keys(counts);
  return (
    <div className={props.className || "vol-worldmap"}>
      <svg viewBox={"0 0 " + W + " " + H} role="img" aria-label="World map of open volunteering opportunities">
        <rect x="0" y="0" width={W} height={H} rx="16" fill="#F5F0E6" />
        {/* graticule */}
        {[1, 2, 3, 4, 5].map(function (i) { return <line key={"h" + i} x1="0" y1={H / 6 * i} x2={W} y2={H / 6 * i} stroke="#e6ddcb" strokeWidth="1" />; })}
        {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map(function (i) { return <line key={"v" + i} x1={W / 12 * i} y1="0" x2={W / 12 * i} y2={H} stroke="#efe7d6" strokeWidth="1" />; })}
        {continents.map(function (d, i) { return <path key={i} d={d} fill="#E4D9C2" opacity="0.75" />; })}
        {markerCountries.map(function (c) {
          var co = VOL_COORDS[c]; if (!co) return null;
          var p = volProject(co[0], co[1], W, H);
          var n = counts[c] || 1;
          var r = 6 + (n / maxCount) * 12;
          var on = selected === c;
          return (
            <g key={c} className="vol-mk" onClick={function () { props.onSelect && props.onSelect(c); }} tabIndex={0}
               role="button" aria-label={c + ", " + n + " open opportunities"}
               onKeyDown={function (e) { if (e.key === "Enter") { props.onSelect && props.onSelect(c); } }}>
              <circle cx={p.x} cy={p.y} r={r + 5} fill={on ? "#C8531C" : "#0F4B35"} opacity={on ? 0.18 : 0.1} />
              <circle cx={p.x} cy={p.y} r={r} fill={on ? "#C8531C" : "#0F4B35"} opacity={on ? 0.95 : 0.7} />
              <text x={p.x} y={p.y + 4} textAnchor="middle" fontSize="12" fontWeight="700" fill="#fff">{n}</text>
            </g>
          );
        })}
      </svg>
    </div>
  );
}

// ─── chips / option helpers ───────────────────────────────────────────────────
function VolChip(props) {
  return (
    <button type="button" className={"vol-chip" + (props.accent ? " vol-chip--accent" : "") + (props.on ? " is-on" : "")}
      onClick={props.onClick} aria-pressed={props.on}>
      {props.children}{props.on && props.dismissible && <VIco name="x" size={13} />}
    </button>
  );
}

// ═══════════════════════════════════════════════════════════════════════════════
//  PAGES
// ═══════════════════════════════════════════════════════════════════════════════

// ─── Home (product landing) ─────────────────────────────────────────────────
function VolMatchRing(props) {
  var pct = props.pct, r = 18, C = 2 * Math.PI * r, off = C * (1 - pct / 100);
  return (
    <span className="volh-match" aria-label={pct + "% match"}>
      <svg viewBox="0 0 44 44"><circle className="volh-match-track" cx="22" cy="22" r={r} fill="none" strokeWidth="4" /><circle className="volh-match-fill" cx="22" cy="22" r={r} fill="none" strokeWidth="4" strokeDasharray={C} strokeDashoffset={off} /></svg>
      <span className="volh-match-num">{pct}%</span>
    </span>
  );
}

function VolHome(props) {
  var VOL = window.VOL;

  // Waitlist (real localStorage flow, existing key)
  var _email = React.useState(""); var email = _email[0], setEmail = _email[1];
  var _wlDone = React.useState(false); var wlDone = _wlDone[0], setWlDone = _wlDone[1];
  function submitWaitlist(e) {
    e.preventDefault();
    try { var list = JSON.parse(localStorage.getItem("globally_vol_waitlist") || "[]"); list.push({ email: email, at: new Date().toISOString() }); localStorage.setItem("globally_vol_waitlist", JSON.stringify(list)); } catch (_) {}
    volTrack("waitlist_join", {}); setWlDone(true);
  }
  function scrollTo(id) { var el = document.getElementById(id); if (el) el.scrollIntoView({ behavior: "smooth", block: "start" }); }

  var MATCHES = [
    { cat: "Field research support", title: "Community Research Volunteer", org: "Grassroots Futures", tags: ["Research", "Community", "Kenya"], pct: 92, ico: "search", grad: "linear-gradient(135deg,#1C7852,#123F32)" },
    { cat: "Content & communication", title: "Education Content Writer", org: "Global Learners Network", tags: ["Writing", "Education", "Remote"], pct: 88, ico: "edit", grad: "linear-gradient(135deg,#86B890,#1C7852)" },
    { cat: "Monitoring & evaluation", title: "M&E Data Analyst (Volunteer)", org: "Impact Collective", tags: ["Data", "Analysis", "Remote"], pct: 84, ico: "chart", grad: "linear-gradient(135deg,#F4A13B,#d67f1f)" }
  ];
  var SKILLS = ["Writing", "Research", "Data Analysis", "Community Engagement", "Monitoring & Evaluation"];
  var INTERESTS = ["Education", "Health", "Environment", "Gender Equality", "Livelihoods"];

  var STEPS = [
    { n: "1", ico: "search", oico: false, t: "Discover needs", d: "Explore real opportunities from trusted organisations working on the issues that matter." },
    { n: "2", ico: "users", oico: false, t: "Match skills", d: "Tell us your skills and interests. We'll help you find roles where you can add the most value." },
    { n: "3", ico: "send", oico: true, t: "Take action responsibly", d: "Apply through a safe, transparent process designed to protect people and maximise impact." }
  ];
  var AUD = [
    { cls: "volh-audcard--green", ico: "building", oico: false, t: "For organisations", d: "Find skilled, values-aligned volunteers who can strengthen your work.", cta: "Register organisation interest", go: function () { volGo("post"); } },
    { cls: "volh-audcard--mint", ico: "book", oico: false, t: "For readers", d: "Be the first to know when verified volunteering opportunities open.", cta: "Join the waitlist", go: function () { scrollTo("vol-band"); } },
    { cls: "", ico: "users", oico: true, t: "For development groups", d: "Collaborate, share needs, and connect with a global pool of support.", cta: "Get in touch", go: function () { volGo("organisations"); } }
  ];
  var FEATURES = [
    { ico: "shield", t: "Verified listings", d: "Opportunities vetted for credibility and safety." },
    { ico: "puzzle", t: "Skills matching", d: "Smarter matches based on your skills and experience." },
    { ico: "globe", t: "Remote & in-person", d: "Flexible roles across time zones and locations." },
    { ico: "pin", t: "Cause & location filters", d: "Find opportunities by issue area or region." },
    { ico: "chart", t: "Light impact profiles", d: "Track your contributions and impact over time." },
    { ico: "hand", t: "Safe volunteering principles", d: "We put people, safeguarding and dignity first." }
  ];

  return (
    <div className="volh">
      {/* decorative botanicals + accents */}
      <div className="volh-decor" aria-hidden="true">
        <span className="volh-blob" style={{ width: 420, height: 420, right: "-90px", top: "40px", background: "radial-gradient(circle, #EAF4E8 0%, rgba(234,244,232,0) 70%)" }} />
        <span className="volh-blob" style={{ width: 260, height: 260, left: "-80px", top: "520px", background: "radial-gradient(circle, #F0F5E6 0%, rgba(240,245,230,0) 70%)" }} />
        <span className="volh-star" style={{ left: "3%", top: "90px" }}><VIco name="star" size={16} /></span>
        <span className="volh-star volh-star--orange" style={{ left: "38%", top: "60px" }}><VIco name="star" size={12} /></span>
        <svg style={{ position: "absolute", right: "2%", top: "20px", width: 160, height: 60, opacity: .5 }} aria-hidden="true"><path d="M4,40 C50,10 110,10 156,34" fill="none" stroke="#86B890" strokeWidth="2" strokeLinecap="round" /></svg>
        <span style={{ position: "absolute", left: "-16px", bottom: "80px", color: "#86B890", opacity: .35, transform: "rotate(12deg)" }}><VIco name="leaf" size={110} /></span>
      </div>

      {/* ── HERO ── */}
      <section className="volh-hero">
        <div className="volh-wrap">
          <div className="volh-hero-grid">
            <div className="volh-hero-left">
              <p className="volh-hero-eyebrow">Volunteering · Coming soon</p>
              <h1 className="volh-hero-h1">Turn global<br />awareness into<br />
                <span className="volh-underline">useful <span className="volh-ital">action.</span>
                  <svg viewBox="0 0 230 12" preserveAspectRatio="none" aria-hidden="true"><path d="M3,7 C60,12 160,1 227,7" /></svg>
                </span>
              </h1>

              <div className="volh-actions">
                <div className="volh-action">
                  <span className="volh-action-ico"><VIco name="eye" size={22} /></span>
                  <span className="volh-action-t">See what's<br />needed</span>
                </div>
                <div className="volh-action">
                  <svg className="volh-action-curve" viewBox="0 0 120 34" role="img" aria-label="Find where you fit">
                    <defs><path id="volh-fitarc" d="M5,30 Q60,0 115,30" fill="none" /></defs>
                    <text><textPath xlinkHref="#volh-fitarc" startOffset="4%">find where you fit</textPath></text>
                  </svg>
                  <span className="volh-action-ico"><VIco name="users" size={20} /></span>
                </div>
                <div className="volh-action">
                  <span className="volh-action-ico volh-action-ico--orange"><VIco name="send" size={20} /></span>
                  <span className="volh-action-t">Step into<br />action</span>
                </div>
              </div>

              <p className="volh-hero-copy">Volunteering opportunities are coming soon. We're building a trusted way for people, professionals and organisations to connect around development issues.</p>
              <div className="volh-hero-ctas">
                <button className="vol-btn vol-btn--primary" onClick={function () { scrollTo("vol-band"); }}>Join the waitlist <VIco name="arrow" size={15} className="vol-arrow" /></button>
                <button className="vol-btn" onClick={function () { volGo("post"); }}>Register organisation interest</button>
              </div>
            </div>

            {/* ── HERO DASHBOARD PREVIEW ── */}
            <div className="volh-hero-right">
              <div className="volh-dash" role="img" aria-label="Preview of the Globally volunteering dashboard">
                <div className="volh-dash-head">
                  <div>
                    <p className="volh-dash-hi">Hi Alex <span aria-hidden="true">👋</span></p>
                    <p className="volh-dash-sub">Here are opportunities that match your skills and interests.</p>
                  </div>
                  <button className="volh-dash-edit" onClick={function () { volGo("fit"); }}>Update my profile <VIco name="arrow" size={12} /></button>
                </div>
                <div className="volh-dash-body">
                  <div>
                    <p className="volh-dash-col-label">Your matches</p>
                    <div className="volh-opps">
                      {MATCHES.map(function (m, i) {
                        return (
                          <button key={i} className="volh-opp" onClick={function () { volGo("opportunities"); }}>
                            <span className="volh-opp-thumb" style={{ background: m.grad }}><VIco name={m.ico} size={20} /></span>
                            <span style={{ minWidth: 0 }}>
                              <span className="volh-opp-cat">{m.cat}</span>
                              <span className="volh-opp-title" style={{ display: "block" }}>{m.title}</span>
                              <span className="volh-opp-org">{m.org}</span>
                              <span className="volh-opp-tags">{m.tags.map(function (t) { return <span key={t} className="volh-opp-tag">{t}</span>; })}</span>
                            </span>
                            <VolMatchRing pct={m.pct} />
                          </button>
                        );
                      })}
                    </div>
                  </div>
                  <div className="volh-profile">
                    <div>
                      <p className="volh-dash-col-label">Your skills</p>
                      <div className="volh-chips">{SKILLS.map(function (s) { return <span key={s} className="volh-chip2">{s}</span>; })}</div>
                      <button className="volh-editlink" onClick={function () { volGo("skills"); }}>Edit skills</button>
                    </div>
                    <div>
                      <p className="volh-dash-col-label">Your impact interests</p>
                      <div className="volh-chips">{INTERESTS.map(function (s) { return <span key={s} className="volh-chip2 volh-chip2--interest">{s}</span>; })}</div>
                      <button className="volh-editlink" onClick={function () { volGo("causes"); }}>Edit interests</button>
                    </div>
                    <div className="volh-impact">
                      <p className="volh-impact-t">Make a bigger impact</p>
                      <p className="volh-impact-c">Complete your profile to unlock better matches.</p>
                      <div className="volh-progress"><div className="volh-progress-bar" style={{ width: "60%" }} /></div>
                      <div className="volh-progress-num">60% complete</div>
                      <span className="volh-leaf"><VIco name="leaf" size={44} /></span>
                    </div>
                  </div>
                </div>
              </div>
              <div className="volh-disclosure"><VIco name="info" size={13} /> Preview opportunities shown for demonstration. Live verified listings are coming soon.</div>
            </div>
          </div>
        </div>
      </section>

      {/* ── HOW IT WORKS ── */}
      <section className="volh-sec">
        <div className="volh-wrap">
          <div className="volh-hiw">
            <div>
              <p className="volh-kicker">How it works</p>
              <h2 className="volh-hiw-title">Good intentions.<br />
                <span className="volh-underline">Clear path.
                  <svg viewBox="0 0 150 12" preserveAspectRatio="none" aria-hidden="true"><path d="M3,7 C40,11 110,2 147,7" /></svg>
                </span>
              </h2>
              <p className="volh-hiw-copy">We make it simple to go from curious to contributing.</p>
            </div>
            <div className="volh-steps">
              {STEPS.map(function (s, i) {
                return (
                  <div key={i} className="volh-step">
                    <div className="volh-step-num">{s.n}</div>
                    <span className={"volh-step-ico" + (s.oico ? " volh-step-ico--orange" : "")}><VIco name={s.ico} size={20} /></span>
                    <h3 className="volh-step-t">{s.t}</h3>
                    <p className="volh-step-d">{s.d}</p>
                    {i < STEPS.length - 1 && <span className="volh-step-arrow"><VIco name="chevron" size={18} /></span>}
                  </div>
                );
              })}
            </div>
          </div>
        </div>
      </section>

      {/* ── WHO IS THIS FOR ── */}
      <section className="volh-sec">
        <div className="volh-wrap">
          <h2 className="volh-serif" style={{ fontSize: "clamp(26px,3vw,38px)", margin: "0 0 24px" }}>Who is this for?</h2>
          <div className="volh-aud">
            {AUD.map(function (a, i) {
              return (
                <div key={i} className={"volh-audcard " + a.cls}>
                  <span className={"volh-aud-ico" + (a.oico ? " volh-aud-ico--orange" : "")}><VIco name={a.ico} size={22} /></span>
                  <h3 className="volh-aud-t">{a.t}</h3>
                  <p className="volh-aud-d">{a.d}</p>
                  <button className="volh-aud-cta" onClick={a.go}>{a.cta} <VIco name="arrow" size={14} /></button>
                </div>
              );
            })}
          </div>
        </div>
      </section>

      {/* ── WHAT WE'RE BUILDING ── */}
      <section className="volh-sec">
        <div className="volh-wrap">
          <div className="volh-build">
            <div><h2 className="volh-build-title">What we're<br />building</h2></div>
            <div className="volh-features">
              {FEATURES.map(function (f, i) {
                return (
                  <div key={i}>
                    <span className="volh-feat-ico"><VIco name={f.ico} size={26} /></span>
                    <p className="volh-feat-t">{f.t}</p>
                    <p className="volh-feat-d">{f.d}</p>
                  </div>
                );
              })}
            </div>
          </div>
        </div>
      </section>

      {/* ── BOTTOM CONVERSION BAND ── */}
      <section className="volh-sec" id="vol-band">
        <div className="volh-wrap">
          <div className="volh-band">
            <span className="volh-band-leaf" aria-hidden="true"><VIco name="leaf" size={150} /></span>
            <div className="volh-band-grid">
              <div>
                <div className="volh-quotemark" aria-hidden="true">&ldquo;</div>
                <p className="volh-quote-t">Globally is building the bridge between awareness and action — I'm excited to be part of it.</p>
                <div className="volh-supporter">
                  <span className="volh-avatar">PS</span>
                  <span><span className="volh-supporter-n" style={{ display: "block" }}>Priya S.</span><span className="volh-supporter-l">Early supporter preview</span></span>
                </div>
              </div>
              <div>
                <p className="volh-band-mid-t">Join early supporters from around the world</p>
                <div className="volh-avatars" aria-hidden="true">
                  <span className="volh-avatar" style={{ background: "#1C7852" }}>AK</span>
                  <span className="volh-avatar" style={{ background: "#86B890" }}>MR</span>
                  <span className="volh-avatar" style={{ background: "#F4A13B" }}>JD</span>
                  <span className="volh-avatar" style={{ background: "#123F32" }}>LB</span>
                  <span className="volh-more">+ more</span>
                </div>
                <p className="vol-field-hint" style={{ marginTop: 12 }}>An early community forming as we build.</p>
              </div>
              <div>
                <p className="volh-wait-t">Be first in line for volunteering opportunities</p>
                <p className="volh-wait-c">Join the waitlist to get early access and shape what we build.</p>
                {wlDone ? (
                  <div className="vol-card vol-card--pad" style={{ background: "var(--vol-surface)" }}>
                    <p style={{ margin: 0, fontWeight: 700, color: "var(--vol-green-d)" }}><VIco name="check" size={15} /> You're on the list.</p>
                    <p className="vol-field-hint" style={{ marginTop: 6 }}>We'll be in touch as verified opportunities go live.</p>
                  </div>
                ) : (
                  <form className="volh-wait-form" onSubmit={submitWaitlist}>
                    <label htmlFor="volh-wl" style={{ position: "absolute", width: 1, height: 1, overflow: "hidden", clip: "rect(0 0 0 0)" }}>Your email address</label>
                    <input id="volh-wl" type="email" required placeholder="Your email address" value={email} onChange={function (e) { setEmail(e.target.value); }} />
                    <button className="vol-btn vol-btn--primary" type="submit">Join the waitlist <VIco name="arrow" size={15} className="vol-arrow" /></button>
                  </form>
                )}
                {!wlDone && <p className="volh-wait-note">No spam. Unsubscribe anytime.</p>}
              </div>
            </div>
          </div>
        </div>
      </section>
    </div>
  );
}

// ─── Database (browse everything) ─────────────────────────────────────────────
function VolDatabase(props) {
  var VOL = window.VOL;
  var initial = props.params || {};
  var _f = React.useState({
    q: initial.q || "",
    cause: initial.cause || null,
    causeGroup: initial.causeGroup || null,
    country: initial.country || null,
    region: initial.region || null,
    mode: initial.mode || null,
    remote: initial.remote === "true" || false,
    time: initial.time || null,
    skills: initial.skills ? initial.skills.split(",") : [],
    language: initial.language || null,
    orgType: initial.orgType || null,
    newly: initial.newly === "true" || false
  });
  var f = _f[0], setF = _f[1];
  var _sheet = React.useState(false); var sheetOpen = _sheet[0], setSheetOpen = _sheet[1];
  var _q = React.useState(f.q); var qInput = _q[0], setQInput = _q[1];

  // debounce search into filter (rule 43)
  React.useEffect(function () {
    var t = setTimeout(function () { setF(function (p) { return Object.assign({}, p, { q: qInput }); }); }, 220);
    return function () { clearTimeout(t); };
  }, [qInput]);

  // reflect filters into the URL hash (shareable, rule 44)
  React.useEffect(function () {
    var params = {};
    ["q", "cause", "causeGroup", "country", "region", "mode", "time", "language", "orgType"].forEach(function (k) { if (f[k]) params[k] = f[k]; });
    if (f.remote) params.remote = "true";
    if (f.newly) params.newly = "true";
    if (f.skills.length) params.skills = f.skills.join(",");
    var want = volBuildHash("opportunities", null, params);
    if (window.location.hash !== want) history.replaceState(null, "", want);
  }, [f]);

  var opps = VOL.allOpportunities();
  var results = VOL.filterOpportunities(opps, f);
  var VOLcolsExpired = VOL.filterOpportunities(opps, Object.assign({}, f, { includeClosed: true })).length - results.length;

  function set(k, v) { setF(function (p) { var n = Object.assign({}, p); n[k] = v; return n; }); }
  function toggleSkill(s) { setF(function (p) { var n = Object.assign({}, p); n.skills = p.skills.indexOf(s) !== -1 ? p.skills.filter(function (x) { return x !== s; }) : p.skills.concat([s]); return n; }); }
  function clearAll() { setQInput(""); setF({ q: "", cause: null, causeGroup: null, country: null, region: null, mode: null, remote: false, time: null, skills: [], language: null, orgType: null, newly: false }); }

  var countries = VOL.allCountries();
  var languages = ["English", "Arabic", "French", "Spanish", "German", "Bengali"];

  var activeChips = [];
  if (f.causeGroup) { var cg = VOL.causeGroupById(f.causeGroup); activeChips.push({ k: "causeGroup", label: cg ? cg.label : f.causeGroup }); }
  if (f.cause) activeChips.push({ k: "cause", label: f.cause });
  if (f.country) activeChips.push({ k: "country", label: f.country });
  if (f.region) activeChips.push({ k: "region", label: f.region });
  if (f.mode) activeChips.push({ k: "mode", label: VolModeLabel(f.mode) });
  if (f.remote) activeChips.push({ k: "remote", label: "Remote or hybrid" });
  if (f.time) { var tb = VOL.TIME_BANDS.filter(function (t) { return t.id === f.time; })[0]; activeChips.push({ k: "time", label: tb ? tb.label : f.time }); }
  if (f.language) activeChips.push({ k: "language", label: f.language });
  if (f.orgType) activeChips.push({ k: "orgType", label: f.orgType });
  if (f.newly) activeChips.push({ k: "newly", label: "Newly added" });
  f.skills.forEach(function (s) { activeChips.push({ k: "skill:" + s, label: s }); });

  function clearChip(c) {
    if (c.k.indexOf("skill:") === 0) return toggleSkill(c.k.slice(6));
    if (c.k === "remote" || c.k === "newly") return set(c.k, false);
    set(c.k, null);
  }

  var filtersUI = (
    <div className={"vol-filters" + (sheetOpen ? " is-open" : "")}>
      <div className="vol-filter-group">
        <p className="vol-filter-label">Cause</p>
        <div className="vol-filter-opts">
          {VOL.CAUSE_GROUPS.map(function (g) { return <VolChip key={g.id} on={f.causeGroup === g.id} onClick={function () { set("causeGroup", f.causeGroup === g.id ? null : g.id); }}>{g.label.split(" & ")[0]}</VolChip>; })}
        </div>
      </div>
      <div className="vol-filter-group">
        <p className="vol-filter-label">Where</p>
        <div className="vol-filter-opts" style={{ marginBottom: 8 }}>
          <VolChip on={f.remote} onClick={function () { set("remote", !f.remote); }}>Remote / hybrid</VolChip>
          {VOL.MODES.map(function (m) { return <VolChip key={m.id} on={f.mode === m.id} onClick={function () { set("mode", f.mode === m.id ? null : m.id); }}>{m.label}</VolChip>; })}
        </div>
        <select className="" value={f.region || ""} onChange={function (e) { set("region", e.target.value || null); }}
          style={{ width: "100%", padding: "9px 12px", border: "1px solid var(--vol-border)", borderRadius: 10, background: "var(--vol-surface)", fontFamily: "var(--vol-sans)", fontSize: 13, marginBottom: 8 }}>
          <option value="">Any region</option>
          {VOL.REGIONS.map(function (r) { return <option key={r} value={r}>{r}</option>; })}
        </select>
        <select value={f.country || ""} onChange={function (e) { set("country", e.target.value || null); }}
          style={{ width: "100%", padding: "9px 12px", border: "1px solid var(--vol-border)", borderRadius: 10, background: "var(--vol-surface)", fontFamily: "var(--vol-sans)", fontSize: 13 }}>
          <option value="">Any country</option>
          {countries.slice().sort().map(function (c) { return <option key={c} value={c}>{c}</option>; })}
        </select>
      </div>
      <div className="vol-filter-group">
        <p className="vol-filter-label">Time commitment</p>
        <div className="vol-filter-opts">
          {VOL.TIME_BANDS.map(function (b) { return <VolChip key={b.id} on={f.time === b.id} onClick={function () { set("time", f.time === b.id ? null : b.id); }}>{b.short}</VolChip>; })}
        </div>
      </div>
      <div className="vol-filter-group">
        <p className="vol-filter-label">Skills</p>
        <div className="vol-filter-opts">
          {VOL.SKILLS.map(function (s) { return <VolChip key={s} on={f.skills.indexOf(s) !== -1} onClick={function () { toggleSkill(s); }}>{s}</VolChip>; })}
        </div>
      </div>
      <div className="vol-filter-group">
        <p className="vol-filter-label">Language</p>
        <div className="vol-filter-opts">
          {languages.map(function (l) { return <VolChip key={l} on={f.language === l} onClick={function () { set("language", f.language === l ? null : l); }}>{l}</VolChip>; })}
        </div>
      </div>
      <div className="vol-filter-group">
        <p className="vol-filter-label">Organisation type</p>
        <div className="vol-filter-opts">
          {VOL.ORG_TYPES.map(function (o) { return <VolChip key={o} on={f.orgType === o} onClick={function () { set("orgType", f.orgType === o ? null : o); }}>{o}</VolChip>; })}
        </div>
      </div>
      <div className="vol-filter-group">
        <VolChip on={f.newly} onClick={function () { set("newly", !f.newly); }}>Newly added (last 3 weeks)</VolChip>
      </div>
    </div>
  );

  return (
    <div className="vol-section">
      <div className="vol-wrap vol-wrap--wide">
        <p className="vol-eyebrow">Volunteer database</p>
        <h1 className="vol-h1" style={{ fontSize: "clamp(28px,3.6vw,42px)" }}>Browse every opportunity.</h1>
        <p className="vol-sub" style={{ marginBottom: 18 }}>Search, filter and open anything. Save the ones you're considering.</p>
        <div style={{ marginBottom: 16 }}><VolDemoNotice /></div>

        <div className="vol-db-layout">
          <div>
            {/* desktop filters render in-flow; mobile via sheet */}
            <div className="vol-hide-mobile">{filtersUI}</div>
          </div>
          <div>
            <div className="vol-search" style={{ marginBottom: 14 }}>
              <VIco name="search" size={16} />
              <input type="search" placeholder="Search roles, organisations, countries, skills…" value={qInput}
                onChange={function (e) { setQInput(e.target.value); }} aria-label="Search opportunities" />
            </div>
            <div className="vol-db-head">
              <span className="vol-db-count">{results.length} {results.length === 1 ? "opportunity" : "opportunities"}{VOLcolsExpired > 0 ? " · " + VOLcolsExpired + " closed hidden" : ""}</span>
              <div style={{ display: "flex", gap: 8 }}>
                <button className="vol-btn vol-btn--sm vol-filter-btn" onClick={function () { setSheetOpen(true); }}><VIco name="filter" size={14} /> Filters</button>
                {activeChips.length > 0 && <button className="vol-btn vol-btn--sm" onClick={clearAll}>Clear all</button>}
              </div>
            </div>
            {activeChips.length > 0 && (
              <div className="vol-active-filters">
                {activeChips.map(function (c, i) {
                  return <span key={i} className="vol-active-filter">{c.label}<button onClick={function () { clearChip(c); }} aria-label={"Remove " + c.label}><VIco name="x" size={12} /></button></span>;
                })}
              </div>
            )}
            <VolOppList items={results} isSaved={props.isSaved} onToggleSave={props.onToggleSave}
              emptyTitle="Nothing matches those filters" emptyBody="Clear a filter or widen your search." />
          </div>
        </div>
      </div>

      {/* mobile bottom sheet */}
      {sheetOpen && (
        <div className="vol-sheet-backdrop" onClick={function () { setSheetOpen(false); }}>
          <div className="vol-sheet" onClick={function (e) { e.stopPropagation(); }}>
            <div className="vol-sheet-handle" />
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8 }}>
              <h3 className="vol-h3">Filters</h3>
              <button className="vol-save" onClick={function () { setSheetOpen(false); }} aria-label="Close filters"><VIco name="x" size={16} /></button>
            </div>
            <div className="vol-filters is-open" style={{ display: "block" }}>{filtersUI.props.children}</div>
            <div className="vol-sheet-foot">
              <button className="vol-btn vol-btn--block" onClick={clearAll}>Clear</button>
              <button className="vol-btn vol-btn--primary vol-btn--block" onClick={function () { setSheetOpen(false); }}>Show {results.length}</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

// ─── Opportunity detail ───────────────────────────────────────────────────────
function VolOpportunityDetail(props) {
  var VOL = window.VOL;
  var opps = VOL.allOpportunities();
  var o = opps.filter(function (x) { return x.id === props.id; })[0];
  if (!o) {
    return (
      <div className="vol-section"><div className="vol-wrap vol-wrap--narrow">
        <button className="vol-linkback" onClick={function () { volGo("opportunities"); }}><VIco name="back" size={14} /> Back to opportunities</button>
        <div className="vol-empty"><p className="vol-h3">This opportunity isn't available.</p><p className="vol-muted">It may have closed or the link is out of date.</p>
          <div style={{ marginTop: 16 }}><button className="vol-btn vol-btn--primary" onClick={function () { volGo("opportunities"); }}>Browse opportunities</button></div></div>
      </div></div>
    );
  }
  var st = VOL.statusFor(o);
  var saved = props.isSaved(o.id);
  var isOrg = o.source === "organisation-submitted";
  return (
    <div className="vol-section">
      <div className="vol-wrap vol-wrap--wide">
        <button className="vol-linkback" onClick={function () { window.history.length > 1 ? window.history.back() : volGo("opportunities"); }} style={{ marginBottom: 18 }}><VIco name="back" size={14} /> Back</button>
        <div className="vol-detail">
          <div className="vol-detail-main">
            <div>
              <div className="vol-opp-top" style={{ marginBottom: 10 }}>
                <VolCausePill opp={o} />
                <span className="vol-pill"><span className="vol-pill-dot" style={{ background: o.mode === "remote" ? "#2f7d4d" : "#0F4B35" }} />{VolModeLabel(o.mode)}</span>
                <VolStatus status={st} />
                <span className="vol-demo-badge"><VIco name="info" size={12} /> {isOrg ? "Organisation-submitted (demo)" : "Sample listing"}</span>
              </div>
              <h1 className="vol-h1" style={{ fontSize: "clamp(26px,3.4vw,40px)" }}>{o.role}</h1>
              <p className="vol-opp-org" style={{ fontSize: 16, marginTop: 8 }}>{o.organisation} · {o.orgType}</p>
            </div>

            <div className="vol-detail-block"><h4>What you'd do</h4><p>{o.whatYouDo}</p></div>
            <div className="vol-detail-block"><h4>Why it matters</h4><p>{o.whyItMatters}</p></div>

            {(o.requirements && o.requirements.length) ? (
              <div className="vol-detail-block"><h4>Requirements</h4>
                <ul className="vol-req-list">{o.requirements.map(function (r, i) { return <li key={i}>{r}</li>; })}</ul>
              </div>
            ) : null}

            {(o.sensitive || o.qualifications) && (
              <div className="vol-safety">
                <strong>Please note: </strong>
                {o.qualifications ? o.qualifications + " " : ""}
                This role may involve contact with children, patients or people in vulnerable situations. Only apply if you meet the checks the organisation requires. Globally does not vet organisations or verify safety.
              </div>
            )}

            <div className="vol-detail-block"><h4>How to apply</h4>
              <p>{o.applicationProcess === "external"
                ? "Applications are handled by the organisation on the original platform. Globally does not process applications."
                : "Contact the organisation directly using the details below."}</p>
              <div style={{ display: "flex", gap: 10, flexWrap: "wrap", marginTop: 14 }}>
                <a className="vol-btn vol-btn--accent" href={o.applyUrl} target="_blank" rel="noopener noreferrer" onClick={function () { volTrack("apply_click", { id: o.id }); }}>Apply on {o.sourceName} <VIco name="ext" size={14} /></a>
                <a className="vol-btn" href={o.sourceUrl} target="_blank" rel="noopener noreferrer">Original listing <VIco name="ext" size={14} /></a>
              </div>
            </div>

            <div className="vol-notice" style={{ marginTop: 8 }}>
              <VIco name="info" size={16} />
              <span>This is a demonstration listing used to show how Globally will present real roles. It is not a live vacancy. Always check the organisation's own website before applying, travelling or sharing personal details.</span>
            </div>
          </div>

          <aside className="vol-detail-side">
            <div className="vol-card vol-card--pad">
              <button className={"vol-btn vol-btn--block " + (saved ? "" : "vol-btn--primary")} onClick={function () { props.onToggleSave(o); }}>
                <VIco name="bookmark" size={15} /> {saved ? "Saved" : "Save this"}
              </button>
              <ul className="vol-facts" style={{ marginTop: 16 }}>
                <li><span className="vol-facts-k">Cause</span><span className="vol-facts-v">{o.cause}</span></li>
                <li><span className="vol-facts-k">Location</span><span className="vol-facts-v">{o.mode === "remote" ? "Remote" : o.country}</span></li>
                <li><span className="vol-facts-k">Remote status</span><span className="vol-facts-v">{o.mode === "remote" ? (o.remoteScope === "global" ? "Fully remote" : o.remoteScope === "timezone-restricted" ? "Remote · timezone overlap" : o.remoteScope === "country-restricted" ? "Remote within country" : "Remote") : VolModeLabel(o.mode)}</span></li>
                <li><span className="vol-facts-k">Time</span><span className="vol-facts-v">{o.timeText}</span></li>
                <li><span className="vol-facts-k">Duration</span><span className="vol-facts-v">{o.durationText}</span></li>
                <li><span className="vol-facts-k">Languages</span><span className="vol-facts-v">{(o.languages || []).join(", ") || "—"}</span></li>
                {o.deadline ? <li><span className="vol-facts-k">Deadline</span><span className="vol-facts-v">{o.deadline}</span></li> : null}
                <li><span className="vol-facts-k">Expenses</span><span className="vol-facts-v">{o.expenses ? "Some covered" : "Not stated"}</span></li>
                <li><span className="vol-facts-k">Accommodation</span><span className="vol-facts-v">{o.accommodation ? "Provided" : "Not provided"}</span></li>
                <li><span className="vol-facts-k">Travel</span><span className="vol-facts-v">{o.travel || "—"}</span></li>
              </ul>
              <div style={{ marginTop: 14 }}>
                <p className="vol-mega-feature-lab">Skills needed</p>
                <div className="vol-opp-skills">{(o.skills || []).map(function (s) { return <span key={s} className="vol-tag" style={{ cursor: "pointer" }} onClick={function () { volGo("skills", null, { skills: s }); }}>{s}</span>; })}</div>
              </div>
            </div>
          </aside>
        </div>
      </div>
    </div>
  );
}

// ─── Find volunteering (personalised) ─────────────────────────────────────────
function VolFind(props) {
  var VOL = window.VOL;
  var init = props.params || {};
  var _in = React.useState({
    mode: null, country: null, causeGroup: init.cause || null, skills: [], language: null, time: null
  });
  var inp = _in[0], setInp = _in[1];
  var _done = React.useState(false); var done = _done[0], setDone = _done[1];
  function set(k, v) { setInp(function (p) { var n = Object.assign({}, p); n[k] = v; return n; }); }
  function toggleSkill(s) { setInp(function (p) { var n = Object.assign({}, p); n.skills = p.skills.indexOf(s) !== -1 ? p.skills.filter(function (x) { return x !== s; }) : p.skills.concat([s]); return n; }); }

  var opps = VOL.allOpportunities().filter(function (o) { return !VOL.isExpired(o); });
  var recs = VOL.recommend(opps, { mode: inp.mode, remote: inp.mode === "remote", country: inp.country, causeGroup: inp.causeGroup, skills: inp.skills, language: inp.language, time: inp.time }, 12);

  return (
    <div className="vol-section">
      <div className="vol-wrap vol-wrap--wide">
        <p className="vol-eyebrow">Find volunteering</p>
        <h1 className="vol-h1" style={{ fontSize: "clamp(28px,3.6vw,42px)" }}>What might suit you?</h1>
        <p className="vol-sub" style={{ marginBottom: 20 }}>Tell us a little — only what helps. No sign-in, no personal details.</p>

        <div className="vol-grid vol-grid--2" style={{ alignItems: "start" }}>
          <div className="vol-card vol-card--pad vol-form">
            <div className="vol-field">
              <label>How would you like to help?</label>
              <div className="vol-give-opts">
                {[["remote", "Remotely"], ["in-person", "In person"], [null, "Either"]].map(function (m) {
                  return <VolChip key={String(m[0])} on={inp.mode === m[0]} onClick={function () { set("mode", m[0]); }}>{m[1]}</VolChip>;
                })}
              </div>
            </div>
            <div className="vol-field">
              <label>Anywhere in particular?</label>
              <select value={inp.country || ""} onChange={function (e) { set("country", e.target.value || null); }}>
                <option value="">No preference</option>
                {VOL.allCountries().slice().sort().map(function (c) { return <option key={c} value={c}>{c}</option>; })}
              </select>
            </div>
            <div className="vol-field">
              <label>Which causes interest you?</label>
              <div className="vol-give-opts">
                {VOL.CAUSE_GROUPS.map(function (g) { return <VolChip key={g.id} accent on={inp.causeGroup === g.id} onClick={function () { set("causeGroup", inp.causeGroup === g.id ? null : g.id); }}>{g.label.split(" & ")[0]}</VolChip>; })}
              </div>
            </div>
            <div className="vol-field">
              <label>What skills could you offer?</label>
              <div className="vol-give-opts">
                {VOL.SKILLS.map(function (s) { return <VolChip key={s} on={inp.skills.indexOf(s) !== -1} onClick={function () { toggleSkill(s); }}>{s}</VolChip>; })}
              </div>
            </div>
            <div className="vol-form-row">
              <div className="vol-field">
                <label>Languages you speak</label>
                <select value={inp.language || ""} onChange={function (e) { set("language", e.target.value || null); }}>
                  <option value="">Any</option>
                  {["English", "Arabic", "French", "Spanish", "German", "Bengali"].map(function (l) { return <option key={l} value={l}>{l}</option>; })}
                </select>
              </div>
              <div className="vol-field">
                <label>How much time?</label>
                <select value={inp.time || ""} onChange={function (e) { set("time", e.target.value || null); }}>
                  <option value="">Flexible</option>
                  {VOL.TIME_BANDS.map(function (b) { return <option key={b.id} value={b.id}>{b.label}</option>; })}
                </select>
              </div>
            </div>
            <button className="vol-btn vol-btn--primary vol-btn--block" onClick={function () { setDone(true); volTrack("find_submit", inp); }}>Show what may suit me</button>
          </div>

          <div>
            <h3 className="vol-h3" style={{ marginBottom: 6 }}>{done ? "Opportunities that may suit you" : "Your results appear here"}</h3>
            <p className="vol-muted" style={{ fontSize: 14, marginBottom: 14 }}>{done ? "Each shows why it may fit — in plain terms, never a mystery score." : "Fill in what you can on the left, then press the button."}</p>
            {done
              ? <VolOppList items={recs} cols="vol-grid--2" isSaved={props.isSaved} onToggleSave={props.onToggleSave}
                  emptyTitle="No clear match yet" emptyBody="Try selecting a cause or a couple of skills — those match most widely." />
              : <div className="vol-empty"><div className="vol-empty-ico"><VIco name="spark" size={22} /></div><p className="vol-muted">We'll suggest realistic options based on what you tell us.</p></div>}
          </div>
        </div>
      </div>
    </div>
  );
}

// ─── Skill matcher (SKILL STACK) ──────────────────────────────────────────────
function VolSkillMatcher(props) {
  var VOL = window.VOL;
  var init = props.params && props.params.skills ? props.params.skills.split(",") : [];
  var _sel = React.useState(init); var sel = _sel[0], setSel = _sel[1];
  function toggle(s) { setSel(function (p) { return p.indexOf(s) !== -1 ? p.filter(function (x) { return x !== s; }) : p.concat([s]); }); }

  var opps = VOL.allOpportunities().filter(function (o) { return !VOL.isExpired(o); });
  var matched = sel.length
    ? opps.map(function (o) { return { opp: o, n: (o.skills || []).filter(function (s) { return sel.indexOf(s) !== -1; }).length }; })
        .filter(function (x) { return x.n > 0; }).sort(function (a, b) { return b.n - a.n; })
        .map(function (x) { return { opp: x.opp, reasons: (x.opp.skills || []).filter(function (s) { return sel.indexOf(s) !== -1; }).map(function (s) { return { k: s, why: "Uses a skill you have" }; }) }; })
    : [];

  return (
    <div className="vol-section">
      <div className="vol-wrap vol-wrap--wide">
        <p className="vol-eyebrow">Match my skills</p>
        <h1 className="vol-h1" style={{ fontSize: "clamp(28px,3.6vw,42px)" }}>What are you good at?</h1>
        <p className="vol-sub" style={{ marginBottom: 22 }}>Pick a few. They gather into your toolkit, and opportunities reorganise around them.</p>
        <div className="vol-skill-layout">
          <div>
            {VOL.SKILL_GROUPS.map(function (g) {
              return (
                <div key={g.id} className="vol-skill-group">
                  <p className="vol-skill-group-label">{g.label}</p>
                  <div className="vol-skill-palette">
                    {g.skills.map(function (s) { return <VolChip key={s} on={sel.indexOf(s) !== -1} onClick={function () { toggle(s); }}>{s}</VolChip>; })}
                  </div>
                </div>
              );
            })}
          </div>
          <div className="vol-toolkit">
            <p className="vol-toolkit-head">Your toolkit</p>
            <p className="vol-muted" style={{ fontSize: 13 }}>{sel.length ? sel.length + " skill" + (sel.length > 1 ? "s" : "") + " selected" : "Nothing yet"}</p>
            <div className="vol-toolkit-tags">
              {sel.length === 0 && <span className="vol-toolkit-empty">Your chosen skills appear here.</span>}
              {sel.map(function (s) { return <span key={s} className="vol-toolkit-tag">{s}<button onClick={function () { toggle(s); }} aria-label={"Remove " + s}><VIco name="x" size={12} /></button></span>; })}
            </div>
            {sel.length > 0 && <button className="vol-btn vol-btn--sm vol-btn--block" onClick={function () { setSel([]); }}>Clear toolkit</button>}
          </div>
        </div>
        <div style={{ marginTop: 28 }}>
          <h3 className="vol-h3" style={{ marginBottom: 14 }}>{sel.length ? "Ways you could use these skills" : "Pick a skill to begin"}</h3>
          {sel.length
            ? <VolOppList items={matched} isSaved={props.isSaved} onToggleSave={props.onToggleSave} emptyTitle="No roles use those exact skills yet" emptyBody="Try adding a broader skill like Research or Writing." />
            : <div className="vol-empty"><div className="vol-empty-ico"><VIco name="layers" size={22} /></div><p className="vol-muted">Choose skills above and matching opportunities will appear here.</p></div>}
        </div>
      </div>
    </div>
  );
}

// ─── Time matcher (TIME WINDOW / TIME REVEAL) ─────────────────────────────────
function VolTimeMatcher(props) {
  var VOL = window.VOL;
  var _i = React.useState(props.params && props.params.time ? VOL.timeOrder(props.params.time) : 1);
  var idx = _i[0], setIdx = _i[1];
  var bands = VOL.TIME_BANDS;
  var current = bands[idx];
  var opps = VOL.allOpportunities().filter(function (o) { return !VOL.isExpired(o) && VOL.timeOrder(o.timeBand) <= idx; })
    .sort(function (a, b) { return VOL.timeOrder(a.timeBand) - VOL.timeOrder(b.timeBand); });

  return (
    <div className="vol-section">
      <div className="vol-wrap vol-wrap--wide">
        <p className="vol-eyebrow">How much time do you have?</p>
        <h1 className="vol-h1" style={{ fontSize: "clamp(28px,3.6vw,42px)" }}>A few hours can still matter.</h1>
        <p className="vol-sub" style={{ marginBottom: 22 }}>Slide the window open. The more time you have, the more kinds of volunteering appear — but even 30 minutes counts.</p>

        <div className="vol-timewindow">
          <div className="vol-time-track" role="group" aria-label="How much time do you have?">
            {bands.map(function (b, i) {
              return (
                <button key={b.id} className={"vol-time-step" + (i === idx ? " is-active" : i < idx ? " is-in" : "")}
                  onClick={function () { setIdx(i); }} aria-pressed={i === idx}>
                  <span className="vol-time-step-label">{b.short}</span>
                </button>
              );
            })}
          </div>
          <p className="vol-time-blurb"><strong>{current.label}.</strong> {current.blurb}</p>
        </div>

        <div style={{ marginTop: 26 }}>
          <div className="vol-preview-head">
            <h3 className="vol-h3">Realistic with {current.label.toLowerCase()}</h3>
            <span className="vol-preview-count">{opps.length} shown</span>
          </div>
          <VolOppList items={opps} isSaved={props.isSaved} onToggleSave={props.onToggleSave}
            emptyTitle="Nothing in that window yet" emptyBody="Try opening the window a little wider." />
        </div>
      </div>
    </div>
  );
}

// ─── What suits me? (diagnostic) ──────────────────────────────────────────────
function VolFit(props) {
  var VOL = window.VOL;
  var STEPS = [
    { key: "motive", q: "What draws you to volunteering?", multi: false, opts: [
      { v: "skills", l: "Use my professional skills" }, { v: "local", l: "Help locally" },
      { v: "international", l: "Work internationally" }, { v: "learn", l: "Learn something" },
      { v: "people", l: "Meet people" }, { v: "remote", l: "Contribute remotely" } ] },
    { key: "time", q: "How much time can you give?", multi: false, opts: VOL.TIME_BANDS.map(function (b) { return { v: b.id, l: b.label }; }) },
    { key: "cause", q: "Which causes pull at you?", multi: true, opts: VOL.CAUSE_GROUPS.map(function (g) { return { v: g.id, l: g.label }; }) },
    { key: "place", q: "Where would you rather be?", multi: false, opts: [ { v: "remote", l: "Remote" }, { v: "in-person", l: "In person" }, { v: "either", l: "Either" } ] },
    { key: "skills", q: "What could you offer?", multi: true, opts: VOL.SKILLS.map(function (s) { return { v: s, l: s }; }) }
  ];
  var _step = React.useState(0); var step = _step[0], setStep = _step[1];
  var _a = React.useState({ motive: null, time: null, cause: [], place: null, skills: [] });
  var ans = _a[0], setAns = _a[1];
  var _done = React.useState(false); var done = _done[0], setDone = _done[1];

  function pick(key, v, multi) {
    setAns(function (p) {
      var n = Object.assign({}, p);
      if (multi) { n[key] = p[key].indexOf(v) !== -1 ? p[key].filter(function (x) { return x !== v; }) : p[key].concat([v]); }
      else { n[key] = v; }
      return n;
    });
  }
  function next() { if (step < STEPS.length - 1) setStep(step + 1); else { setDone(true); volTrack("fit_complete", ans); } }
  function back() { if (done) setDone(false); else if (step > 0) setStep(step - 1); }

  var cur = STEPS[step];
  var curVal = ans[cur.key];
  var canNext = cur.multi ? (curVal.length > 0) : !!curVal;

  // Results — descriptive categories from answers + real opportunities
  function results() {
    var cats = [];
    if (ans.motive === "skills" || ans.skills.length) cats.push("Skills-based remote volunteering");
    if (ans.place === "in-person" || ans.motive === "local") cats.push("Local short-term projects");
    if (ans.time === "weekly" || ans.time === "longterm") cats.push("Ongoing specialist support");
    if (ans.place === "remote" || ans.motive === "remote") cats.push("Remote micro-volunteering");
    if (!cats.length) cats.push("A gentle mix of remote and local roles");
    var inputs = {
      skills: ans.skills, time: ans.time,
      mode: ans.place === "either" ? null : ans.place,
      remote: ans.place === "remote" || ans.motive === "remote"
    };
    ans.cause.forEach(function () {});
    var opps = VOL.allOpportunities().filter(function (o) { return !VOL.isExpired(o); });
    // prefer chosen causes
    if (ans.cause.length) opps = opps.filter(function (o) { return ans.cause.indexOf(o.causeGroup) !== -1; }).concat(opps.filter(function (o) { return ans.cause.indexOf(o.causeGroup) === -1; }));
    var recs = VOL.recommend(opps, inputs, 9);
    if (!recs.length) recs = opps.slice(0, 6).map(function (o) { return { opp: o, reasons: [] }; });
    return { cats: cats, recs: recs };
  }

  if (done) {
    var r = results();
    return (
      <div className="vol-section"><div className="vol-wrap vol-wrap--wide">
        <button className="vol-linkback" onClick={back} style={{ marginBottom: 16 }}><VIco name="back" size={14} /> Change answers</button>
        <p className="vol-eyebrow">What suits me?</p>
        <h1 className="vol-h1" style={{ fontSize: "clamp(26px,3.4vw,38px)" }}>You may be well suited to…</h1>
        <div className="vol-grid vol-grid--3" style={{ margin: "20px 0 30px" }}>
          {r.cats.map(function (c, i) { return <div key={i} className="vol-card vol-card--pad"><VIco name="check" size={18} /><h3 className="vol-h3" style={{ marginTop: 8 }}>{c}</h3></div>; })}
        </div>
        <h3 className="vol-h3" style={{ marginBottom: 14 }}>Real opportunities to start with</h3>
        <VolOppList items={r.recs} cols="vol-grid--3" isSaved={props.isSaved} onToggleSave={props.onToggleSave} />
      </div></div>
    );
  }

  return (
    <div className="vol-section"><div className="vol-wrap vol-wrap--narrow">
      <p className="vol-eyebrow" style={{ textAlign: "center" }}>What suits me?</p>
      <div className="vol-step-dots">
        {STEPS.map(function (s, i) { return <span key={i} className={"vol-step-dot" + (i === step ? " is-on" : i < step ? " is-done" : "")} />; })}
      </div>
      <h2 className="vol-question">{cur.q}</h2>
      <div className="vol-optgrid">
        {cur.opts.map(function (o) {
          var on = cur.multi ? curVal.indexOf(o.v) !== -1 : curVal === o.v;
          return <button key={o.v} className={"vol-opt" + (on ? " is-on" : "")} onClick={function () { pick(cur.key, o.v, cur.multi); }} aria-pressed={on}>{o.l}</button>;
        })}
      </div>
      <div style={{ display: "flex", justifyContent: "space-between", marginTop: 28 }}>
        <button className="vol-btn" onClick={back} disabled={step === 0}><VIco name="back" size={14} /> Back</button>
        <button className="vol-btn vol-btn--primary" onClick={next} disabled={!canNext}>{step === STEPS.length - 1 ? "See what suits me" : "Next"} <VIco name="arrow" size={14} className="vol-arrow" /></button>
      </div>
    </div></div>
  );
}

// ─── Cause explorer + cause page ──────────────────────────────────────────────
function VolCauseExplorer(props) {
  var VOL = window.VOL;
  var opps = VOL.allOpportunities().filter(function (o) { return !VOL.isExpired(o); });
  return (
    <div className="vol-section"><div className="vol-wrap vol-wrap--wide">
      <p className="vol-eyebrow">Explore by cause</p>
      <h1 className="vol-h1" style={{ fontSize: "clamp(28px,3.6vw,42px)" }}>Find ways to help the issues you care about.</h1>
      <p className="vol-sub" style={{ marginBottom: 22 }}>Grouped into friendly themes that map onto Globally's development topics.</p>
      <div className="vol-grid vol-grid--3">
        {VOL.CAUSE_GROUPS.map(function (g) {
          var n = opps.filter(function (o) { return o.causeGroup === g.id; }).length;
          return (
            <button key={g.id} className="vol-cause-card" onClick={function () { volGo("cause", g.id); }}>
              <span className="vol-cause-card-wash" style={{ background: "linear-gradient(150deg," + g.tint + " 0%, transparent 70%)" }} />
              <span className="vol-cause-pill" style={{ background: g.tint, color: g.accent }}><span className="vol-pill-dot" style={{ background: g.accent }} /> {n} open</span>
              <h3 className="vol-h3" style={{ margin: "12px 0 6px" }}>{g.label}</h3>
              <p className="vol-muted" style={{ fontSize: 13.5 }}>{g.blurb}</p>
              <div className="vol-cause-topics">{g.topics.map(function (t) { return <span key={t} className="vol-tag">{t}</span>; })}</div>
            </button>
          );
        })}
      </div>
    </div></div>
  );
}

function VolCausePage(props) {
  var VOL = window.VOL;
  var g = VOL.causeGroupById(props.id);
  if (!g) { volGo("causes"); return null; }
  var all = VOL.allOpportunities().filter(function (o) { return !VOL.isExpired(o); });
  var opps = all.filter(function (o) { return o.causeGroup === g.id; });
  var skills = {}; var countries = {}; var orgs = {}; var remote = [];
  opps.forEach(function (o) {
    (o.skills || []).forEach(function (s) { skills[s] = (skills[s] || 0) + 1; });
    if (o.country) countries[o.country] = (countries[o.country] || 0) + 1;
    orgs[o.organisation] = (orgs[o.organisation] || 0) + 1;
    if (o.mode === "remote") remote.push(o);
  });
  var topSkills = Object.keys(skills).sort(function (a, b) { return skills[b] - skills[a]; });
  var topCountries = Object.keys(countries).sort(function (a, b) { return countries[b] - countries[a]; });
  var thread = opps[0];

  return (
    <div className="vol-section"><div className="vol-wrap vol-wrap--wide">
      <button className="vol-linkback" onClick={function () { volGo("causes"); }} style={{ marginBottom: 16 }}><VIco name="back" size={14} /> All causes</button>
      <span className="vol-cause-pill" style={{ background: g.tint, color: g.accent }}><span className="vol-pill-dot" style={{ background: g.accent }} /> {g.topics.join(" · ")}</span>
      <h1 className="vol-h1" style={{ fontSize: "clamp(28px,3.6vw,42px)", marginTop: 12 }}>{g.label}</h1>
      <p className="vol-lead" style={{ marginTop: 10 }}>How can I help with this? Here's what organisations working on {g.label.toLowerCase()} are looking for.</p>

      {thread && (
        <div style={{ marginTop: 8 }}>
          <p className="vol-mega-feature-lab" style={{ marginTop: 18 }}>How Globally connects cause to action</p>
          <div className="vol-thread">
            <span className="vol-thread-node" style={{ borderColor: g.accent }}>{g.label.split(" & ")[0]}</span>
            <span className="vol-thread-line" />
            <span className="vol-thread-node">{thread.country || "Remote"}</span>
            <span className="vol-thread-line" />
            <span className="vol-thread-node">{thread.role}</span>
            <span className="vol-thread-line" />
            <span className="vol-thread-node">{thread.organisation}</span>
          </div>
        </div>
      )}

      {topSkills.length > 0 && (
        <div style={{ marginTop: 18 }}>
          <p className="vol-mega-feature-lab">Skills organisations need</p>
          <div className="vol-opp-skills">{topSkills.map(function (s) { return <span key={s} className="vol-tag" style={{ cursor: "pointer" }} onClick={function () { volGo("skills", null, { skills: s }); }}>{s}</span>; })}</div>
        </div>
      )}
      {topCountries.length > 0 && (
        <div style={{ marginTop: 14 }}>
          <p className="vol-mega-feature-lab">Countries</p>
          <div className="vol-opp-skills">{topCountries.map(function (c) { return <span key={c} className="vol-tag" style={{ cursor: "pointer" }} onClick={function () { volGo("countries", null, { country: c }); }}><VIco name="pin" size={12} /> {c}</span>; })}</div>
        </div>
      )}

      <h3 className="vol-h3" style={{ margin: "28px 0 14px" }}>Opportunities ({opps.length})</h3>
      <VolOppList items={opps} cols="vol-grid--3" isSaved={props.isSaved} onToggleSave={props.onToggleSave} />

      {remote.length > 0 && (
        <div style={{ marginTop: 30 }}>
          <h3 className="vol-h3" style={{ marginBottom: 14 }}>Remote ways to help</h3>
          <VolOppList items={remote} cols="vol-grid--3" isSaved={props.isSaved} onToggleSave={props.onToggleSave} />
        </div>
      )}
    </div></div>
  );
}

// ─── Country explorer / where organisations are looking ───────────────────────
function VolCountryExplorer(props) {
  var VOL = window.VOL;
  var opps = VOL.allOpportunities().filter(function (o) { return !VOL.isExpired(o); });
  var counts = VOL.countryCounts(opps);
  var _sel = React.useState(props.params && props.params.country ? props.params.country : null);
  var sel = _sel[0], setSel = _sel[1];
  var _search = React.useState(""); var search = _search[0], setSearch = _search[1];
  var whereMode = props.variant === "where";

  React.useEffect(function () { if (props.params && props.params.country) setSel(props.params.country); }, [props.params && props.params.country]);

  var countryList = Object.keys(counts).sort(function (a, b) { return counts[b] - counts[a]; })
    .filter(function (c) { return !search || c.toLowerCase().indexOf(search.toLowerCase()) !== -1; });

  var selOpps = sel ? opps.filter(function (o) { return o.country === sel || (o.countries || []).indexOf(sel) !== -1; }) : [];
  var selCauses = {}; var selOrgs = {}; var selRemote = [];
  selOpps.forEach(function (o) { selCauses[o.cause] = (selCauses[o.cause] || 0) + 1; selOrgs[o.organisation] = 1; if (o.mode !== "in-person") selRemote.push(o); });

  return (
    <div className="vol-section"><div className="vol-wrap vol-wrap--wide">
      <p className="vol-eyebrow">{whereMode ? "Where organisations are looking for support" : "Explore a country"}</p>
      <h1 className="vol-h1" style={{ fontSize: "clamp(28px,3.6vw,42px)" }}>{whereMode ? "Where organisations are looking for support." : "See volunteering connected to a place."}</h1>
      <p className="vol-sub" style={{ marginBottom: 18 }}>Marker size reflects the number of open opportunities in our data — we don't claim where help is needed most.</p>
      <div style={{ marginBottom: 16 }}><VolDemoNotice /></div>

      <div className="vol-country-layout">
        <VolWorldMap counts={counts} selected={sel} onSelect={function (c) { setSel(c); volTrack("country_select", { country: c }); }} />
        <div className="vol-country-panel">
          <div className="vol-card vol-card--pad">
            <div className="vol-search" style={{ marginBottom: 12 }}>
              <VIco name="search" size={15} />
              <input type="search" placeholder="Search countries" value={search} onChange={function (e) { setSearch(e.target.value); }} aria-label="Search countries" />
            </div>
            <div className="vol-country-list">
              {countryList.map(function (c) {
                return (
                  <div key={c} className={"vol-country-row" + (sel === c ? " is-on" : "")} onClick={function () { setSel(c); }}
                    role="button" tabIndex={0} onKeyDown={function (e) { if (e.key === "Enter") setSel(c); }}>
                    <span style={{ fontWeight: 600, fontSize: 14 }}><VIco name="pin" size={13} /> {c}</span>
                    <span className="vol-count-bubble">{counts[c]}</span>
                  </div>
                );
              })}
              {countryList.length === 0 && <p className="vol-muted" style={{ fontSize: 13, padding: 8 }}>No countries match.</p>}
            </div>
          </div>
        </div>
      </div>

      {sel && (
        <div style={{ marginTop: 30 }}>
          <h2 className="vol-h2">{sel}</h2>
          {Object.keys(selCauses).length > 0 && (
            <div style={{ margin: "12px 0" }}>
              <span className="vol-muted" style={{ fontSize: 13, marginRight: 8 }}>Causes:</span>
              {Object.keys(selCauses).map(function (c) { return <span key={c} className="vol-tag" style={{ marginRight: 6 }}>{c}</span>; })}
            </div>
          )}
          <h3 className="vol-h3" style={{ margin: "18px 0 12px" }}>Open opportunities ({selOpps.length})</h3>
          <VolOppList items={selOpps} cols="vol-grid--3" isSaved={props.isSaved} onToggleSave={props.onToggleSave}
            emptyTitle={"No open roles in " + sel + " yet"} emptyBody="Try another country, or explore remote roles you can do from anywhere." />
          {selRemote.length > 0 && (
            <div style={{ marginTop: 24 }}>
              <h3 className="vol-h3" style={{ marginBottom: 12 }}>Remote & hybrid ways to help connected to {sel}</h3>
              <VolOppList items={selRemote} cols="vol-grid--3" isSaved={props.isSaved} onToggleSave={props.onToggleSave} />
            </div>
          )}
        </div>
      )}
    </div></div>
  );
}

// ─── Remote volunteering ──────────────────────────────────────────────────────
function VolRemote(props) {
  var VOL = window.VOL;
  var _f = React.useState({ skills: [], causeGroup: null, time: null, language: null });
  var f = _f[0], setF = _f[1];
  function set(k, v) { setF(function (p) { var n = Object.assign({}, p); n[k] = v; return n; }); }
  function toggleSkill(s) { setF(function (p) { var n = Object.assign({}, p); n.skills = p.skills.indexOf(s) !== -1 ? p.skills.filter(function (x) { return x !== s; }) : p.skills.concat([s]); return n; }); }

  var opps = VOL.allOpportunities().filter(function (o) { return !VOL.isExpired(o) && (o.mode === "remote" || o.mode === "hybrid"); });
  var results = VOL.filterOpportunities(opps, { causeGroup: f.causeGroup, time: f.time, language: f.language, skills: f.skills, includeClosed: false });

  function scopeLabel(o) {
    if (o.mode === "hybrid") return "Hybrid";
    if (o.remoteScope === "global") return "Fully remote";
    if (o.remoteScope === "timezone-restricted") return "Remote · timezone overlap needed";
    if (o.remoteScope === "country-restricted") return "Remote within a country";
    return "Remote";
  }

  return (
    <div className="vol-section"><div className="vol-wrap vol-wrap--wide">
      <p className="vol-eyebrow">Remote volunteering</p>
      <h1 className="vol-h1" style={{ fontSize: "clamp(28px,3.6vw,42px)" }}>Help from wherever you are.</h1>
      <p className="vol-sub" style={{ marginBottom: 20 }}>Contribute your time and skills without leaving home. Each role states its remote conditions clearly.</p>

      <div className="vol-card vol-card--pad" style={{ marginBottom: 20 }}>
        <div className="vol-filter-group" style={{ paddingTop: 0 }}>
          <p className="vol-filter-label">Cause</p>
          <div className="vol-filter-opts">{VOL.CAUSE_GROUPS.map(function (g) { return <VolChip key={g.id} on={f.causeGroup === g.id} onClick={function () { set("causeGroup", f.causeGroup === g.id ? null : g.id); }}>{g.label.split(" & ")[0]}</VolChip>; })}</div>
        </div>
        <div className="vol-filter-group">
          <p className="vol-filter-label">Skills</p>
          <div className="vol-filter-opts">{VOL.SKILLS.map(function (s) { return <VolChip key={s} on={f.skills.indexOf(s) !== -1} onClick={function () { toggleSkill(s); }}>{s}</VolChip>; })}</div>
        </div>
        <div className="vol-form-row" style={{ marginTop: 4 }}>
          <div className="vol-field"><label>Time</label>
            <select value={f.time || ""} onChange={function (e) { set("time", e.target.value || null); }}>
              <option value="">Any</option>{VOL.TIME_BANDS.map(function (b) { return <option key={b.id} value={b.id}>{b.label}</option>; })}
            </select>
          </div>
          <div className="vol-field"><label>Language</label>
            <select value={f.language || ""} onChange={function (e) { set("language", e.target.value || null); }}>
              <option value="">Any</option>{["English", "Arabic", "French", "Spanish", "German", "Bengali"].map(function (l) { return <option key={l} value={l}>{l}</option>; })}
            </select>
          </div>
        </div>
      </div>

      <div className="vol-preview-head"><h3 className="vol-h3">{results.length} remote & hybrid roles</h3></div>
      <div className="vol-grid vol-grid--3">
        {results.map(function (o) {
          return (
            <div key={o.id} className="vol-opp" role="button" tabIndex={0} onClick={function () { volGo("opportunity", o.id); }}
              onKeyDown={function (e) { if (e.key === "Enter") volGo("opportunity", o.id); }}>
              <div className="vol-opp-top"><VolCausePill opp={o} /><span style={{ flex: 1 }} />{props.onToggleSave && <VolSaveButton saved={props.isSaved(o.id)} onToggle={function () { props.onToggleSave(o); }} />}</div>
              <h3 className="vol-opp-role">{o.role}</h3>
              <p className="vol-opp-org">{o.organisation}</p>
              <span className="vol-pill" style={{ alignSelf: "flex-start" }}><VIco name="remote" size={12} /> {scopeLabel(o)}</span>
              <div className="vol-opp-meta"><span><VIco name="clock" size={14} /> {o.timeText}</span></div>
              <div className="vol-opp-foot"><VolStatus status={VOL.statusFor(o)} /><span className="vol-opp-view">View <VIco name="arrow" size={14} /></span></div>
            </div>
          );
        })}
      </div>
      {results.length === 0 && <div className="vol-empty"><p className="vol-muted">No remote roles match those filters — try clearing one.</p></div>}
    </div></div>
  );
}

// ─── Saved ────────────────────────────────────────────────────────────────────
function VolSaved(props) {
  var VOL = window.VOL;
  var saved = props.saved; // map id -> status
  var _tab = React.useState("saved"); var tab = _tab[0], setTab = _tab[1];
  var opps = VOL.allOpportunities();
  var ids = Object.keys(saved);
  var items = ids.map(function (id) { return { o: opps.filter(function (x) { return x.id === id; })[0], status: saved[id] }; }).filter(function (x) { return x.o; });
  var shown = items.filter(function (x) { return (x.status || "saved") === tab; });

  if (!volSignedIn()) {
    return (
      <div className="vol-section"><div className="vol-wrap vol-wrap--narrow">
        <p className="vol-eyebrow">Saved opportunities</p>
        <h1 className="vol-h1" style={{ fontSize: "clamp(26px,3.4vw,38px)" }}>Keep track of roles you're considering.</h1>
        <div className="vol-card vol-card--pad" style={{ textAlign: "center", marginTop: 20 }}>
          <div className="vol-empty-ico" style={{ margin: "0 auto 12px" }}><VIco name="bookmark" size={22} /></div>
          <p className="vol-lead" style={{ margin: "0 auto 16px" }}>Sign in to save opportunities and come back to them across your devices.</p>
          <button className="vol-btn vol-btn--primary" onClick={function () { props.onRequestAuth && props.onRequestAuth("login"); }}>Sign in to save</button>
          <div style={{ marginTop: 12 }}><button className="vol-btn vol-btn--ghost" onClick={function () { volGo("opportunities"); }}>Keep browsing without saving</button></div>
        </div>
      </div></div>
    );
  }

  return (
    <div className="vol-section"><div className="vol-wrap vol-wrap--wide">
      <p className="vol-eyebrow">Saved opportunities</p>
      <h1 className="vol-h1" style={{ fontSize: "clamp(28px,3.6vw,42px)" }}>Your shortlist.</h1>
      <div className="vol-saved-tabs" style={{ marginTop: 16 }}>
        {[["saved", "Saved"], ["applied", "Applied"], ["upcoming", "Upcoming"]].map(function (t) {
          var n = items.filter(function (x) { return (x.status || "saved") === t[0]; }).length;
          return <VolChip key={t[0]} on={tab === t[0]} onClick={function () { setTab(t[0]); }}>{t[1]} ({n})</VolChip>;
        })}
        <span style={{ flex: 1 }} />
        {ids.length > 0 && <button className="vol-btn vol-btn--sm" onClick={function () { props.onClearAll(); }}>Clear all</button>}
      </div>
      {shown.length === 0
        ? <div className="vol-empty"><div className="vol-empty-ico"><VIco name="bookmark" size={22} /></div><p className="vol-h3" style={{ marginBottom: 6 }}>Nothing here yet</p><p className="vol-muted">Save opportunities as you browse and move them through Saved → Applied → Upcoming.</p><div style={{ marginTop: 14 }}><button className="vol-btn vol-btn--primary" onClick={function () { volGo("opportunities"); }}>Browse opportunities</button></div></div>
        : (
          <div className="vol-grid vol-grid--3">
            {shown.map(function (x) {
              return (
                <div key={x.o.id}>
                  <VolOpportunityCard opp={x.o} onOpen={function () { volGo("opportunity", x.o.id); }} saved={true} onToggleSave={function () { props.onToggleSave(x.o); }} />
                  <div style={{ display: "flex", gap: 6, marginTop: 8 }}>
                    {[["saved", "Saved"], ["applied", "Applied"], ["upcoming", "Upcoming"]].map(function (t) {
                      return <button key={t[0]} className={"vol-chip vol-chip--sm" + ((x.status || "saved") === t[0] ? " is-on" : "")} style={{ fontSize: 12, padding: "5px 10px" }} onClick={function () { props.onSetStatus(x.o.id, t[0]); }}>{t[1]}</button>;
                    })}
                  </div>
                </div>
              );
            })}
          </div>
        )}
    </div></div>
  );
}

// ─── For organisations ────────────────────────────────────────────────────────
function VolOrgPortal(props) {
  return (
    <div className="vol-section"><div className="vol-wrap vol-wrap--wide">
      <p className="vol-eyebrow">For organisations</p>
      <h1 className="vol-h1" style={{ fontSize: "clamp(28px,3.6vw,42px)" }}>Find people who want to help.</h1>
      <p className="vol-lead" style={{ marginTop: 12 }}>Reach readers who understand global development and want to contribute their time and skills.</p>
      <div className="vol-grid vol-grid--2" style={{ marginTop: 26 }}>
        <div className="vol-card vol-card--pad">
          <VIco name="plus" size={22} />
          <h3 className="vol-h3" style={{ marginTop: 10 }}>Post an opportunity</h3>
          <p className="vol-muted" style={{ fontSize: 14, margin: "8px 0 16px" }}>Describe a real role — what the volunteer will do, the time it takes and who they'll support.</p>
          <button className="vol-btn vol-btn--primary" onClick={function () { volGo("post"); }}>Post an opportunity</button>
        </div>
        <div className="vol-card vol-card--pad">
          <VIco name="layers" size={22} />
          <h3 className="vol-h3" style={{ marginTop: 10 }}>Manage opportunities</h3>
          <p className="vol-muted" style={{ fontSize: 14, margin: "8px 0 16px" }}>Keep your open roles organised and remove them once they're filled.</p>
          <button className="vol-btn" onClick={function () { volGo("manage"); }}>Manage opportunities</button>
        </div>
      </div>
      <div className="vol-card vol-card--pad" style={{ marginTop: 20 }}>
        <h3 className="vol-h3" style={{ marginBottom: 10 }}>What makes a good listing</h3>
        <p className="vol-muted" style={{ fontSize: 14, marginBottom: 12 }}>"Volunteer wanted to help our mission" isn't enough. Every listing should explain:</p>
        <div className="vol-opp-skills">
          {["What the person will actually do", "Time required", "Where", "Skills needed", "Who they'll support", "How to apply"].map(function (s) { return <span key={s} className="vol-tag"><VIco name="check" size={12} /> {s}</span>; })}
        </div>
      </div>
      <div style={{ marginTop: 18 }}>
        <VolDemoNotice text="Listings you post are saved on this device for demonstration. A shared, moderated database with organisation verification will follow once real ingestion is in place." />
      </div>
    </div></div>
  );
}

// ─── Post an opportunity ──────────────────────────────────────────────────────
function VolPost(props) {
  var VOL = window.VOL;
  var _fd = React.useState({
    role: "", organisation: "", orgType: "NGO", cause: "Climate", country: "", mode: "remote",
    whatYouDo: "", whyItMatters: "", skills: "", languages: "English", timeBand: "weekly", timeText: "",
    durationText: "", deadline: "", requirements: "", applyUrl: ""
  });
  var fd = _fd[0], setFd = _fd[1];
  var _err = React.useState({}); var errs = _err[0], setErrs = _err[1];
  var _ok = React.useState(false); var ok = _ok[0], setOk = _ok[1];
  function set(k, v) { setFd(function (p) { var n = Object.assign({}, p); n[k] = v; return n; }); }
  function field(k) { return { value: fd[k], onChange: function (e) { set(k, e.target.value); } }; }

  if (!volSignedIn()) {
    return (
      <div className="vol-section"><div className="vol-wrap vol-wrap--narrow">
        <button className="vol-linkback" onClick={function () { volGo("organisations"); }} style={{ marginBottom: 16 }}><VIco name="back" size={14} /> For organisations</button>
        <div className="vol-card vol-card--pad" style={{ textAlign: "center" }}>
          <div className="vol-empty-ico" style={{ margin: "0 auto 12px" }}><VIco name="plus" size={22} /></div>
          <h1 className="vol-h2">Sign in to post a role</h1>
          <p className="vol-lead" style={{ margin: "10px auto 18px" }}>Posting an opportunity requires an account, so you can manage and remove it later.</p>
          <button className="vol-btn vol-btn--primary" onClick={function () { props.onRequestAuth && props.onRequestAuth("signup"); }}>Sign in or create an account</button>
        </div>
      </div></div>
    );
  }

  function validate() {
    var e = {};
    ["role", "organisation", "whatYouDo", "timeText", "applyUrl"].forEach(function (k) { if (!String(fd[k]).trim()) e[k] = "Required"; });
    if (fd.whatYouDo && fd.whatYouDo.trim().length < 30) e.whatYouDo = "Please describe the actual work (at least a sentence or two).";
    if (fd.applyUrl && !/^https?:\/\//i.test(fd.applyUrl)) e.applyUrl = "Enter a full URL starting with http.";
    if (fd.mode !== "remote" && !String(fd.country).trim()) e.country = "Add a country for in-person or hybrid roles.";
    setErrs(e); return Object.keys(e).length === 0;
  }
  function submit(ev) {
    ev.preventDefault();
    if (!validate()) return;
    var opp = {
      id: "org-" + Math.abs(hashStr(fd.role + fd.organisation + fd.applyUrl)).toString(36),
      role: fd.role.trim(), organisation: fd.organisation.trim(), orgType: fd.orgType,
      cause: fd.cause, topics: [fd.cause], causeGroup: (VOL.causeGroupFor(fd.cause) || {}).id || "climate",
      country: fd.mode === "remote" ? null : fd.country.trim(), countries: fd.mode === "remote" ? [] : [fd.country.trim()],
      mode: fd.mode, remoteScope: fd.mode === "remote" ? "global" : null,
      skills: fd.skills.split(",").map(function (s) { return s.trim(); }).filter(Boolean),
      languages: fd.languages.split(",").map(function (s) { return s.trim(); }).filter(Boolean),
      timeBand: fd.timeBand, timeText: fd.timeText.trim(), durationText: fd.durationText.trim(),
      whatYouDo: fd.whatYouDo.trim(), whyItMatters: fd.whyItMatters.trim() || "Supports the organisation's work.",
      requirements: fd.requirements.split("\n").map(function (s) { return s.trim(); }).filter(Boolean),
      qualifications: null, applicationProcess: "external", applyUrl: fd.applyUrl.trim(),
      sourceName: fd.organisation.trim(), sourceUrl: fd.applyUrl.trim(),
      deadline: fd.deadline || null, postedAt: new Date().toISOString().slice(0, 10),
      expenses: false, accommodation: false, travel: fd.mode === "remote" ? "None — remote" : "Not stated",
      sensitive: false, source: "organisation-submitted"
    };
    try {
      var list = JSON.parse(localStorage.getItem("globally_vol_posted") || "[]");
      list.unshift(opp);
      localStorage.setItem("globally_vol_posted", JSON.stringify(list));
    } catch (e) {}
    volTrack("org_post", { id: opp.id });
    setOk(true);
    setTimeout(function () { volGo("manage"); }, 1400);
  }
  function hashStr(s) { var h = 0; for (var i = 0; i < s.length; i++) { h = (h << 5) - h + s.charCodeAt(i); h |= 0; } return h; }

  if (ok) {
    return (
      <div className="vol-section"><div className="vol-wrap vol-wrap--narrow">
        <div className="vol-card vol-card--pad vol-form-success">
          <div className="vol-empty-ico" style={{ margin: "0 auto 12px", color: "#2f7d4d" }}><VIco name="check" size={24} /></div>
          <h2 className="vol-h2">Opportunity saved</h2>
          <p className="vol-lead" style={{ margin: "8px auto 0" }}>Taking you to manage your listings…</p>
        </div>
      </div></div>
    );
  }

  function err(k) { return errs[k] ? <span className="vol-field-err">{errs[k]}</span> : null; }

  return (
    <div className="vol-section"><div className="vol-wrap vol-wrap--narrow">
      <button className="vol-linkback" onClick={function () { volGo("organisations"); }} style={{ marginBottom: 16 }}><VIco name="back" size={14} /> For organisations</button>
      <p className="vol-eyebrow">Post an opportunity</p>
      <h1 className="vol-h1" style={{ fontSize: "clamp(26px,3.4vw,38px)" }}>Describe the role.</h1>
      <p className="vol-sub" style={{ marginBottom: 20 }}>Tell people what they'd actually do. Required fields are marked.</p>
      <form className="vol-form vol-card vol-card--pad" onSubmit={submit} noValidate>
        <div className="vol-form-row">
          <div className="vol-field"><label>Role title <span className="vol-req">*</span></label><input {...field("role")} placeholder="e.g. Research volunteer" />{err("role")}</div>
          <div className="vol-field"><label>Organisation <span className="vol-req">*</span></label><input {...field("organisation")} placeholder="Your organisation" />{err("organisation")}</div>
        </div>
        <div className="vol-form-row">
          <div className="vol-field"><label>Organisation type</label><select {...field("orgType")}>{VOL.ORG_TYPES.map(function (o) { return <option key={o} value={o}>{o}</option>; })}</select></div>
          <div className="vol-field"><label>Cause</label><select {...field("cause")}>{VOL.TOPICS.map(function (t) { return <option key={t} value={t}>{t}</option>; })}</select></div>
        </div>
        <div className="vol-form-row">
          <div className="vol-field"><label>Location type</label><select {...field("mode")}>{VOL.MODES.map(function (m) { return <option key={m.id} value={m.id}>{m.label}</option>; })}</select></div>
          <div className="vol-field"><label>Country {fd.mode !== "remote" && <span className="vol-req">*</span>}</label><input {...field("country")} placeholder="e.g. Kenya (leave blank if remote)" />{err("country")}</div>
        </div>
        <div className="vol-field"><label>What the volunteer will do <span className="vol-req">*</span></label><textarea {...field("whatYouDo")} placeholder="Describe the actual tasks — be specific." />{err("whatYouDo")}<span className="vol-field-hint">Vague listings ("help our mission") aren't accepted. Explain the real work.</span></div>
        <div className="vol-field"><label>Why it matters</label><textarea {...field("whyItMatters")} placeholder="Who does this help, and how?" /></div>
        <div className="vol-form-row">
          <div className="vol-field"><label>Skills needed</label><input {...field("skills")} placeholder="Comma separated, e.g. Research, Writing" /></div>
          <div className="vol-field"><label>Languages</label><input {...field("languages")} placeholder="Comma separated" /></div>
        </div>
        <div className="vol-form-row">
          <div className="vol-field"><label>Time commitment (band)</label><select {...field("timeBand")}>{VOL.TIME_BANDS.map(function (b) { return <option key={b.id} value={b.id}>{b.label}</option>; })}</select></div>
          <div className="vol-field"><label>Time in words <span className="vol-req">*</span></label><input {...field("timeText")} placeholder="e.g. 3–5 hours/week" />{err("timeText")}</div>
        </div>
        <div className="vol-form-row">
          <div className="vol-field"><label>Duration</label><input {...field("durationText")} placeholder="e.g. 8 weeks" /></div>
          <div className="vol-field"><label>Application deadline</label><input type="date" {...field("deadline")} /></div>
        </div>
        <div className="vol-field"><label>Requirements (one per line)</label><textarea {...field("requirements")} placeholder={"e.g. Comfortable reading reports\nBackground check where relevant"} /></div>
        <div className="vol-field"><label>Where to apply (URL) <span className="vol-req">*</span></label><input {...field("applyUrl")} placeholder="https://…" />{err("applyUrl")}<span className="vol-field-hint">Applications are handled on your own site — Globally links out to it.</span></div>
        <button className="vol-btn vol-btn--primary vol-btn--block" type="submit">Post opportunity</button>
      </form>
    </div></div>
  );
}

// ─── Manage opportunities ─────────────────────────────────────────────────────
function VolManage(props) {
  var _v = React.useState(0); var v = _v[0], setV = _v[1];
  var posted = window.VOL.loadOrgSubmitted();
  function remove(id) {
    try { var list = window.VOL.loadOrgSubmitted().filter(function (o) { return o.id !== id; }); localStorage.setItem("globally_vol_posted", JSON.stringify(list)); } catch (e) {}
    setV(v + 1);
  }
  if (!volSignedIn()) {
    return (
      <div className="vol-section"><div className="vol-wrap vol-wrap--narrow">
        <div className="vol-card vol-card--pad" style={{ textAlign: "center" }}>
          <h1 className="vol-h2">Sign in to manage listings</h1>
          <p className="vol-lead" style={{ margin: "10px auto 18px" }}>Your posted roles are tied to your account.</p>
          <button className="vol-btn vol-btn--primary" onClick={function () { props.onRequestAuth && props.onRequestAuth("login"); }}>Sign in</button>
        </div>
      </div></div>
    );
  }
  return (
    <div className="vol-section"><div className="vol-wrap vol-wrap--wide">
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", flexWrap: "wrap", gap: 12 }}>
        <div><p className="vol-eyebrow">Manage opportunities</p><h1 className="vol-h1" style={{ fontSize: "clamp(26px,3.4vw,38px)" }}>Your open roles.</h1></div>
        <button className="vol-btn vol-btn--primary" onClick={function () { volGo("post"); }}><VIco name="plus" size={15} /> Post a new one</button>
      </div>
      {posted.length === 0
        ? <div className="vol-empty"><div className="vol-empty-ico"><VIco name="layers" size={22} /></div><p className="vol-h3" style={{ marginBottom: 6 }}>No listings yet</p><p className="vol-muted">Post your first opportunity to see it here.</p></div>
        : (
          <div className="vol-grid vol-grid--2" style={{ marginTop: 20 }}>
            {posted.map(function (o) {
              return (
                <div key={o.id} className="vol-card vol-card--pad">
                  <div className="vol-opp-top"><VolCausePill opp={o} /><span className="vol-demo-badge">Org-submitted</span></div>
                  <h3 className="vol-opp-role" style={{ marginTop: 8 }}>{o.role}</h3>
                  <p className="vol-opp-org">{o.organisation}</p>
                  <div className="vol-opp-meta" style={{ marginTop: 8 }}><span><VIco name="pin" size={13} /> {o.mode === "remote" ? "Remote" : o.country}</span><span><VIco name="clock" size={13} /> {o.timeText}</span></div>
                  <div style={{ display: "flex", gap: 8, marginTop: 14 }}>
                    <button className="vol-btn vol-btn--sm" onClick={function () { volGo("opportunity", o.id); }}>View</button>
                    <button className="vol-btn vol-btn--sm" onClick={function () { remove(o.id); }}><VIco name="x" size={13} /> Remove</button>
                  </div>
                </div>
              );
            })}
          </div>
        )}
    </div></div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════════
//  MEGA MENU
// ═══════════════════════════════════════════════════════════════════════════════
function VolunteeringMegaMenu(props) {
  var VOL = window.VOL;
  var go = function (sub, arg, params) { props.onNavigate(volBuildHash(sub, arg, params)); };
  var _t = React.useState(null); var t = _t[0], setT = _t[1];
  var _s = React.useState([]); var s = _s[0], setS = _s[1];
  var _c = React.useState(null); var c = _c[0], setC = _c[1];
  function toggleS(x) { setS(function (p) { return p.indexOf(x) !== -1 ? p.filter(function (y) { return y !== x; }) : p.concat([x]); }); }

  var COLS = [
    { label: "Find something to do", items: [
      { t: "Find volunteering", d: "Around your skills, interests, location and time.", sub: "find" },
      { t: "Volunteer database", d: "Browse opportunities around the world yourself.", sub: "opportunities" },
      { t: "Remote volunteering", d: "Find ways to contribute from wherever you are.", sub: "remote" },
      { t: "Saved opportunities", d: "Come back to roles you're considering.", sub: "saved" }
    ] },
    { label: "Explore the world", items: [
      { t: "Explore a country", d: "See volunteering connected to a place.", sub: "countries" },
      { t: "Explore by cause", d: "Find ways to contribute to the issues you care about.", sub: "causes" },
      { t: "Where organisations are looking", d: "See where organisations have open opportunities.", sub: "where" },
      { t: "Latest opportunities", d: "See recently added ways to get involved.", sub: "opportunities", params: { newly: "true" } }
    ] },
    { label: "Find your fit", items: [
      { t: "Match my skills", d: "See where the skills you have could be useful.", sub: "skills" },
      { t: "How much time do you have?", d: "Realistic opportunities around your time.", sub: "time" },
      { t: "What suits me?", d: "Build a simple profile and discover what may fit.", sub: "fit" },
      { t: "For organisations", d: "Post a role and reach people who want to help.", sub: "organisations" }
    ] }
  ];

  return (
    <div className="vol-mega" role="menu" aria-label="Volunteering">
      {COLS.map(function (col, ci) {
        return (
          <div key={ci}>
            <p className="vol-mega-col-label">{col.label}</p>
            {col.items.map(function (it, ii) {
              return (
                <button key={ii} className="vol-mega-item" role="menuitem" onClick={function () { go(it.sub, null, it.params); }}>
                  <span className="vol-mega-item-t">{it.t}</span>
                  <span className="vol-mega-item-d">{it.d}</span>
                </button>
              );
            })}
          </div>
        );
      })}
      <div className="vol-mega-feature">
        <p className="vol-mega-feature-h">Find your next opportunity</p>
        <div className="vol-mega-feature-row">
          <p className="vol-mega-feature-lab">Your time</p>
          <div className="vol-mega-mini">
            {[["2hours", "2 hours"], ["weekly", "Weekly"], ["weekend", "Weekend"]].map(function (x) { return <button key={x[0]} className={"vol-mega-mini-chip" + (t === x[0] ? " is-on" : "")} onClick={function () { setT(t === x[0] ? null : x[0]); }}>{x[1]}</button>; })}
          </div>
        </div>
        <div className="vol-mega-feature-row">
          <p className="vol-mega-feature-lab">Your skills</p>
          <div className="vol-mega-mini">
            {["Research", "Finance", "Design"].map(function (x) { return <button key={x} className={"vol-mega-mini-chip" + (s.indexOf(x) !== -1 ? " is-on" : "")} onClick={function () { toggleS(x); }}>{x}</button>; })}
          </div>
        </div>
        <div className="vol-mega-feature-row">
          <p className="vol-mega-feature-lab">Your cause</p>
          <div className="vol-mega-mini">
            {[["climate", "Climate"], ["health", "Health"], ["conflict", "Migration"]].map(function (x) { return <button key={x[0]} className={"vol-mega-mini-chip" + (c === x[0] ? " is-on" : "")} onClick={function () { setC(c === x[0] ? null : x[0]); }}>{x[1]}</button>; })}
          </div>
        </div>
        <div className="vol-mega-feature-cta">
          <button className="vol-btn vol-btn--accent vol-btn--sm vol-btn--block" onClick={function () {
            var p = {}; if (t) p.time = t; if (s.length) p.skills = s.join(","); if (c) p.cause = c;
            go("find", null, p);
          }}>Find my fit <VIco name="arrow" size={14} className="vol-arrow" /></button>
        </div>
      </div>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════════════════════
//  APP (internal sub-router)
// ═══════════════════════════════════════════════════════════════════════════════
var VOL_SUBNAV = [
  { sub: "home", label: "Home" },
  { sub: "opportunities", label: "Database" },
  { sub: "find", label: "Find volunteering" },
  { sub: "skills", label: "Match skills" },
  { sub: "time", label: "Time" },
  { sub: "causes", label: "Causes" },
  { sub: "countries", label: "Countries" },
  { sub: "remote", label: "Remote" },
  { sub: "fit", label: "What suits me?" },
  { sub: "saved", label: "Saved" },
  { sub: "organisations", label: "For organisations" }
];

function VolunteeringApp(props) {
  var _r = React.useState(volParseHash()); var route = _r[0], setRoute = _r[1];
  var _saved = React.useState(volLoadSaved()); var saved = _saved[0], setSaved = _saved[1];

  React.useEffect(function () {
    function onHash() { setRoute(volParseHash()); }
    window.addEventListener("hashchange", onHash);
    return function () { window.removeEventListener("hashchange", onHash); };
  }, []);

  // Scroll to top when the sub-page changes (not on filter param changes).
  React.useEffect(function () {
    var el = document.getElementById("gl-main-scroll");
    if (el) el.scrollTop = 0; else window.scrollTo(0, 0);
  }, [route.sub, route.arg]);

  function requestAuth(mode) { if (props.onRequestAuth) props.onRequestAuth(mode || "login"); }

  function toggleSave(opp) {
    if (!volSignedIn()) { requestAuth("signup"); return; }
    setSaved(function (p) {
      var n = Object.assign({}, p);
      if (n[opp.id]) delete n[opp.id]; else n[opp.id] = "saved";
      volWriteSaved(n); volTrack("save_toggle", { id: opp.id, saved: !!n[opp.id] });
      return n;
    });
  }
  function setStatus(id, status) { setSaved(function (p) { var n = Object.assign({}, p); n[id] = status; volWriteSaved(n); return n; }); }
  function clearAllSaved() { setSaved({}); volWriteSaved({}); }
  function isSaved(id) { return !!saved[id]; }

  var shared = { isSaved: isSaved, onToggleSave: toggleSave, onRequestAuth: requestAuth, params: route.params };

  var page;
  switch (route.sub) {
    case "opportunities": page = <VolDatabase {...shared} key={"db" + volQs(route.params)} />; break;
    case "opportunity":   page = <VolOpportunityDetail id={route.arg} {...shared} />; break;
    case "find":          page = <VolFind {...shared} />; break;
    case "skills":        page = <VolSkillMatcher {...shared} />; break;
    case "time":          page = <VolTimeMatcher {...shared} />; break;
    case "fit":           page = <VolFit {...shared} />; break;
    case "causes":        page = <VolCauseExplorer {...shared} />; break;
    case "cause":         page = <VolCausePage id={route.arg} {...shared} />; break;
    case "countries":     page = <VolCountryExplorer {...shared} />; break;
    case "where":         page = <VolCountryExplorer variant="where" {...shared} />; break;
    case "remote":        page = <VolRemote {...shared} />; break;
    case "saved":         page = <VolSaved saved={saved} onSetStatus={setStatus} onClearAll={clearAllSaved} {...shared} />; break;
    case "organisations": page = <VolOrgPortal {...shared} />; break;
    case "post":          page = <VolPost {...shared} />; break;
    case "manage":        page = <VolManage {...shared} />; break;
    default:              page = <VolHome {...shared} />;
  }

  var activeSub = route.sub === "opportunity" ? "opportunities" : route.sub === "cause" ? "causes" : route.sub === "where" ? "countries" : (route.sub === "post" || route.sub === "manage") ? "organisations" : route.sub;

  return (
    <div className="vol">
      {/* Ecosystem sub-nav on every page except the landing home, which mirrors
          the approved reference (main site nav only). */}
      {route.sub !== "home" && (
        <div className="vol-subnav">
          <div className="vol-wrap vol-wrap--wide vol-subnav-inner">
            {VOL_SUBNAV.map(function (n) {
              return <button key={n.sub} className={"vol-subnav-link" + (activeSub === n.sub ? " is-on" : "")}
                onClick={function () { volGo(n.sub); }}>{n.label}</button>;
            })}
          </div>
        </div>
      )}
      {page}
    </div>
  );
}
