PageSourceSearch

https://khchenlab.github.io/direction-c2.js

js khchenlab.github.io collected 2026-10-03 09:27:26 UTC 56,939 bytes, 1,674 lines download raw bytes

1/* Direction C v2: Academic, refined.
2 * Fixes: no emoji, EB Garamond (not Playfair), split hero, flat buttons, rectangular portraits,
3 * stripped publication list, mono metadata, section numbering, muted teal.
4 */
5
6const C2 = {};
7const C2_COLORS = {
8  ink: "#0E1A2B",
9  // deeper than 0F2044, slightly warmer
10  text: "#1C2A3E",
11  muted: "#5B6778",
12  line: "#E6E3DD",
13  paper: "#FAF8F3",
14  // warm paper
15  white: "#FFFFFF",
16  accent: "#0F5F6E",
17  // muted teal — less saturated than sky-500
18  accent2: "#B85C38",
19  // terracotta rust — secondary register: hiring, key papers
20  accentSoft: "#7FB8C0"
21};
22
23// ───────── line icons (thin stroke, no emoji)
24C2.Icon = function Icon({
25  name,
26  size = 20,
27  stroke = C2_COLORS.ink
28}) {
29  const p = {
30    width: size,
31    height: size,
32    viewBox: "0 0 24 24",
33    fill: "none",
34    stroke,
35    strokeWidth: 1.5,
36    strokeLinecap: "round",
37    strokeLinejoin: "round"
38  };
39  const paths = {
40    microscope: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("path", {
41      d: "M6 20h12M10 20V9a2 2 0 0 1 2-2h0a2 2 0 0 1 2 2v11M8 16h8M11 7V4h2v3M12 4h4"
42    })),
43    dna: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("path", {
44      d: "M4 4c4 4 12 12 16 16M20 4c-4 4-12 12-16 16M7 7h4M13 13h4M7 13h4M13 7h4"
45    })),
46    code: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("path", {
47      d: "m8 8-4 4 4 4M16 8l4 4-4 4M14 4l-4 16"
48    })),
49    cell: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("circle", {
50      cx: "12",
51      cy: "12",
52      r: "9"
53    }), /*#__PURE__*/React.createElement("circle", {
54      cx: "9",
55      cy: "10",
56      r: "1.5"
57    }), /*#__PURE__*/React.createElement("circle", {
58      cx: "15",
59      cy: "14",
60      r: "1.5"
61    }), /*#__PURE__*/React.createElement("circle", {
62      cx: "13",
63      cy: "8",
64      r: "1"
65    })),
66    pin: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("path", {
67      d: "M12 21c-4-5-7-8-7-12a7 7 0 0 1 14 0c0 4-3 7-7 12z"
68    }), /*#__PURE__*/React.createElement("circle", {
69      cx: "12",
70      cy: "9",
71      r: "2.5"
72    })),
73    mail: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("rect", {
74      x: "3",
75      y: "5",
76      width: "18",
77      height: "14",
78      rx: "1"
79    }), /*#__PURE__*/React.createElement("path", {
80      d: "m3 7 9 6 9-6"
81    })),
82    inbox: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("path", {
83      d: "M4 12v7a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-7M4 12l2-8h12l2 8M4 12h5l1 2h4l1-2h5"
84    })),
85    twitter: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("path", {
86      d: "M4 4l7 9-7 7h2l6-6 4 6h4l-7-10 7-6h-2l-6 5-4-5z"
87    })),
88    arrow: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("path", {
89      d: "M5 12h14M13 6l6 6-6 6"
90    }))
91  };
92  return /*#__PURE__*/React.createElement("svg", p, paths[name]);
93};
94
95// ───────── Nav
96C2.Nav = function NavC2() {
97  const [scrolled, setScrolled] = React.useState(false);
98  const [active, setActive] = React.useState("top");
99  const [open, setOpen] = React.useState(false);
100  const links = [["top", "Home"], ["research", "Research"], ["news", "News"], ["members", "Members"], ["publications", "Publications"], ["software", "Software"], ["lab-life", "Lab life"], ["contact", "Contact"]];
101  React.useEffect(() => {
102    const onScroll = () => {
103      setScrolled(window.scrollY > 40);
104      for (let i = links.length - 1; i >= 0; i--) {
105        const el = document.getElementById(links[i][0]);
106        if (el && window.scrollY >= el.offsetTop - 140) {
107          setActive(links[i][0]);
108          break;
109        }
110      }
111    };
112    window.addEventListener("scroll", onScroll, {
113      passive: true
114    });
115    onScroll();
116    return () => window.removeEventListener("scroll", onScroll);
117  }, []);
118  const go = id => {
119    const el = document.getElementById(id);
120    if (el) window.scrollTo({
121      top: el.offsetTop - 70,
122      behavior: "smooth"
123    });
124    setOpen(false);
125  };
126  return /*#__PURE__*/React.createElement("header", {
127    className: "fixed top-0 left-0 right-0 z-40 transition-all duration-300",
128    style: {
129      background: scrolled || open ? "rgba(250,248,243,0.96)" : "transparent",
130      backdropFilter: scrolled || open ? "blur(12px)" : "none",
131      borderBottom: scrolled || open ? `1px solid ${C2_COLORS.line}` : "1px solid transparent"
132    }
133  }, /*#__PURE__*/React.createElement("div", {
134    className: "mx-auto max-w-[1280px] px-5 md:px-8 flex items-center justify-between h-14 md:h-[72px]"
135  }, /*#__PURE__*/React.createElement("button", {
136    onClick: () => go("top"),
137    className: "flex items-baseline gap-3 text-left"
138  }, /*#__PURE__*/React.createElement("span", {
139    style: {
140      fontFamily: "'EB Garamond', Georgia, serif",
141      fontWeight: 500,
142      fontSize: 24,
143      color: C2_COLORS.ink,
144      letterSpacing: "-0.01em"
145    }
146  }, "Chen Lab"), /*#__PURE__*/React.createElement("span", {
147    style: {
148      fontFamily: "'IBM Plex Mono', monospace",
149      fontSize: 10,
150      letterSpacing: "0.2em",
151      textTransform: "uppercase",
152      color: C2_COLORS.muted
153    },
154    className: "hidden sm:inline"
155  }, "GIS \xB7 Singapore")), /*#__PURE__*/React.createElement("nav", {
156    className: "hidden md:flex items-center gap-0"
157  }, links.map(([id, label]) => {
158    const isActive = active === id;
159    return /*#__PURE__*/React.createElement("button", {
160      key: id,
161      onClick: () => go(id),
162      className: "relative px-4 py-2 transition-colors",
163      style: {
164        fontFamily: "'Manrope', sans-serif",
165        fontWeight: 500,
166        fontSize: 13,
167        color: isActive ? C2_COLORS.accent : C2_COLORS.text
168      }
169    }, label, isActive && /*#__PURE__*/React.createElement("span", {
170      className: "absolute left-4 right-4 -bottom-0.5 h-px",
171      style: {
172        background: C2_COLORS.accent
173      }
174    }));
175  })), /*#__PURE__*/React.createElement("button", {
176    onClick: () => setOpen(o => !o),
177    "aria-label": "Menu",
178    "aria-expanded": open,
179    className: "md:hidden inline-flex items-center justify-center w-10 h-10",
180    style: {
181      color: C2_COLORS.ink
182    }
183  }, /*#__PURE__*/React.createElement("svg", {
184    width: "22",
185    height: "22",
186    viewBox: "0 0 22 22",
187    fill: "none"
188  }, open ? /*#__PURE__*/React.createElement("g", {
189    stroke: C2_COLORS.ink,
190    strokeWidth: "1.4",
191    strokeLinecap: "round"
192  }, /*#__PURE__*/React.createElement("line", {
193    x1: "5",
194    y1: "5",
195    x2: "17",
196    y2: "17"
197  }), /*#__PURE__*/React.createElement("line", {
198    x1: "17",
199    y1: "5",
200    x2: "5",
201    y2: "17"
202  })) : /*#__PURE__*/React.createElement("g", {
203    stroke: C2_COLORS.ink,
204    strokeWidth: "1.4",
205    strokeLinecap: "round"
206  }, /*#__PURE__*/React.createElement("line", {
207    x1: "3",
208    y1: "7",
209    x2: "19",
210    y2: "7"
211  }), /*#__PURE__*/React.createElement("line", {
212    x1: "3",
213    y1: "11",
214    x2: "19",
215    y2: "11"
216  }), /*#__PURE__*/React.createElement("line", {
217    x1: "3",
218    y1: "15",
219    x2: "19",
220    y2: "15"
221  }))))), open && /*#__PURE__*/React.createElement("div", {
222    className: "md:hidden border-t",
223    style: {
224      borderColor: C2_COLORS.line
225    }
226  }, /*#__PURE__*/React.createElement("nav", {
227    className: "mx-auto max-w-[1280px] px-5 py-2 flex flex-col"
228  }, links.map(([id, label]) => {
229    const isActive = active === id;
230    return /*#__PURE__*/React.createElement("button", {
231      key: id,
232      onClick: () => go(id),
233      className: "flex items-center justify-between py-3 border-b last:border-b-0 text-left",
234      style: {
235        fontFamily: "'Manrope', sans-serif",
236        fontWeight: 500,
237        fontSize: 15,
238        color: isActive ? C2_COLORS.accent : C2_COLORS.ink,
239        borderColor: C2_COLORS.line
240      }
241    }, /*#__PURE__*/React.createElement("span", null, label));
242  }))));
243};
244
245// ───────── Hero (split layout, no gradient scrim)
246C2.Hero = function HeroC2() {
247  return /*#__PURE__*/React.createElement("section", {
248    id: "top",
249    className: "relative pt-20 pb-10 md:pt-24 md:pb-20 overflow-hidden",
250    style: {
251      background: C2_COLORS.paper
252    }
253  }, /*#__PURE__*/React.createElement("div", {
254    className: "absolute inset-0 pointer-events-none",
255    "aria-hidden": "true"
256  }, /*#__PURE__*/React.createElement("img", {
257    src: "hero-group.jpg",
258    alt: "",
259    className: "w-full h-full object-cover",
260    style: {
261      opacity: 0.62,
262      filter: "saturate(0.75) contrast(1)",
263      objectPosition: "center 30%"
264    }
265  }), /*#__PURE__*/React.createElement("div", {
266    className: "absolute inset-0 md:hidden",
267    style: {
268      background: `linear-gradient(to bottom, ${C2_COLORS.paper}f2 0%, ${C2_COLORS.paper}cc 45%, ${C2_COLORS.paper}b3 100%)`
269    }
270  }), /*#__PURE__*/React.createElement("div", {
271    className: "hidden md:block absolute inset-0",
272    style: {
273      background: `linear-gradient(to right, ${C2_COLORS.paper}e6 0%, ${C2_COLORS.paper}99 40%, ${C2_COLORS.paper}33 80%, ${C2_COLORS.paper}1a 100%)`
274    }
275  }), /*#__PURE__*/React.createElement("div", {
276    className: "absolute inset-x-0 top-0 h-24 md:h-32",
277    style: {
278      background: `linear-gradient(to bottom, ${C2_COLORS.paper} 0%, ${C2_COLORS.paper}00 100%)`
279    }
280  }), /*#__PURE__*/React.createElement("div", {
281    className: "absolute inset-x-0 bottom-0 h-32 md:h-40",
282    style: {
283      background: `linear-gradient(to top, ${C2_COLORS.paper} 0%, ${C2_COLORS.paper}00 100%)`
284    }
285  })), /*#__PURE__*/React.createElement("div", {
286    className: "relative mx-auto max-w-[1280px] px-5 md:px-8",
287    style: {
288      zIndex: 1
289    }
290  }, /*#__PURE__*/React.createElement("div", {
291    className: "hidden md:flex items-center justify-between gap-4 pb-4 mb-8 border-b flex-wrap",
292    style: {
293      borderColor: C2_COLORS.line
294    }
295  }, /*#__PURE__*/React.createElement("span", {
296    style: {
297      fontFamily: "'IBM Plex Mono', monospace",
298      fontSize: 10,
299      letterSpacing: "0.22em",
300      textTransform: "uppercase",
301      color: C2_COLORS.accent
302    }
303  }, "The Chen Laboratory \xB7 Genome Institute of Singapore \xB7 Agency for Science, Technology and Research (A*STAR)"), /*#__PURE__*/React.createElement("span", {
304    style: {
305      fontFamily: "'IBM Plex Mono', monospace",
306      fontSize: 10,
307      letterSpacing: "0.22em",
308      textTransform: "uppercase",
309      color: C2_COLORS.muted
310    }
311  }, "Spatial omics \xB7 Systems biology")), /*#__PURE__*/React.createElement("div", {
312    className: "max-w-[1100px]"
313  }, /*#__PURE__*/React.createElement("h1", {
314    style: {
315      fontFamily: "'EB Garamond', Georgia, serif",
316      fontWeight: 400,
317      fontSize: "clamp(48px, 11vw, 132px)",
318      lineHeight: 0.92,
319      letterSpacing: "-0.025em",
320      color: C2_COLORS.ink,
321      fontVariationSettings: "'SOFT' 50, 'opsz' 144"
322    }
323  }, "Mapping the", /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("span", {
324    style: {
325      color: C2_COLORS.accent
326    }
327  }, "Language"), /*#__PURE__*/React.createElement("br", null), "of Cells"), /*#__PURE__*/React.createElement("p", {
328    className: "mt-8 md:mt-12 max-w-[640px]",
329    style: {
330      fontFamily: "'EB Garamond', Georgia, serif",
331      fontWeight: 400,
332      fontSize: "clamp(20px, 2vw, 26px)",
333      lineHeight: 1.4,
334      letterSpacing: "-0.005em",
335      color: C2_COLORS.ink,
336      textWrap: "pretty"
337    }
338  }, "We combine spatial omics with machine learning to decode how RNA localization shapes cell function and disease. Our work is interdisciplinary, collaborative, and driven by a vision of making RNA localization predictable and programmable."), /*#__PURE__*/React.createElement("div", {
339    className: "hidden md:flex mt-10 flex-wrap items-center gap-4"
340  }, /*#__PURE__*/React.createElement("a", {
341    href: "#research",
342    className: "group inline-flex items-center gap-3 px-6 py-3 transition-colors",
343    style: {
344      fontFamily: "'Manrope', sans-serif",
345      fontWeight: 600,
346      fontSize: 13,
347      letterSpacing: "0.02em",
348      background: C2_COLORS.ink,
349      color: C2_COLORS.paper,
350      borderRadius: 4
351    }
352  }, "Our Research", /*#__PURE__*/React.createElement(C2.Icon, {
353    name: "arrow",
354    size: 16,
355    stroke: C2_COLORS.paper
356  })), /*#__PURE__*/React.createElement("a", {
357    href: "#contact",
358    className: "inline-flex items-center gap-2 px-6 py-3 transition-colors",
359    style: {
360      fontFamily: "'Manrope', sans-serif",
361      fontWeight: 600,
362      fontSize: 13,
363      color: C2_COLORS.accent2,
364      border: `1px solid ${C2_COLORS.accent2}`,
365      borderRadius: 4
366    }
367  }, "Join the Lab")))));
368};
369
370// ───────── Email — obfuscated to deter bot scraping.
371// Render @-sign as HTML entity, assemble href on click; no `mailto:` in static source.
372C2.Email = function Email({
373  children,
374  className,
375  style
376}) {
377  const u = "chenkh";
378  const d = "a-star.edu.sg";
379  const onClick = e => {
380    e.preventDefault();
381    window.location.href = "mail" + "to:" + u + String.fromCharCode(64) + d;
382  };
383  return /*#__PURE__*/React.createElement("a", {
384    href: "#contact",
385    onClick: onClick,
386    className: className,
387    style: style
388  }, children || /*#__PURE__*/React.createElement(React.Fragment, null, u, /*#__PURE__*/React.createElement("span", {
389    dangerouslySetInnerHTML: {
390      __html: "@"
391    }
392  }), d));
393};
394
395// ───────── Section head with § numbering
396C2.Head = function Head({
397  idx,
398  eyebrow,
399  title
400}) {
401  return /*#__PURE__*/React.createElement("div", {
402    className: "mb-10"
403  }, /*#__PURE__*/React.createElement("div", {
404    className: "flex items-baseline gap-4 mb-3"
405  }, /*#__PURE__*/React.createElement("span", {
406    style: {
407      fontFamily: "'IBM Plex Mono', monospace",
408      fontSize: 11,
409      letterSpacing: "0.22em",
410      color: C2_COLORS.accent
411    }
412  }, "\xA7 ", idx), /*#__PURE__*/React.createElement("span", {
413    className: "h-px flex-1 max-w-[60px]",
414    style: {
415      background: C2_COLORS.accent
416    }
417  }), /*#__PURE__*/React.createElement("span", {
418    style: {
419      fontFamily: "'IBM Plex Mono', monospace",
420      fontSize: 10,
421      letterSpacing: "0.22em",
422      textTransform: "uppercase",
423      color: C2_COLORS.muted
424    }
425  }, eyebrow)), /*#__PURE__*/React.createElement("h2", {
426    style: {
427      fontFamily: "'EB Garamond', Georgia, serif",
428      fontWeight: 400,
429      fontSize: "clamp(44px, 5.5vw, 68px)",
430      lineHeight: 0.95,
431      letterSpacing: "-0.02em",
432      color: C2_COLORS.ink
433    }
434  }, title));
435};
436C2.Research = function ResearchC2() {
437  const d = window.LAB_DATA;
438  // Adapt B's accent strategy to C2's academic palette: a single muted teal, but each module gets a subtle tonal variation for the progress dots.
439  const tones = [{
440    label: C2_COLORS.accent,
441    soft: "#7FB8C0"
442  }, {
443    label: "#6A5B3E",
444    soft: "#C9B890"
445  },
446  // warm umber (pairs w/ teal)
447  {
448    label: "#5B4A7A",
449    soft: "#B0A4C6"
450  },
451  // muted plum
452  {
453    label: "#1F5233",
454    soft: "#9CC5AA"
455  } // forest
456  ];
457  return /*#__PURE__*/React.createElement("section", {
458    id: "research",
459    className: "py-10 md:py-20",
460    style: {
461      background: C2_COLORS.white,
462      borderTop: `1px solid ${C2_COLORS.line}`
463    }
464  }, /*#__PURE__*/React.createElement("div", {
465    className: "mx-auto max-w-[1280px] px-5 md:px-8"
466  }, /*#__PURE__*/React.createElement(C2.Head, {
467    idx: "01",
468    eyebrow: "Research // capabilities",
469    title: /*#__PURE__*/React.createElement(React.Fragment, null, "The ", /*#__PURE__*/React.createElement("span", {
470      style: {
471        color: C2_COLORS.accent
472      }
473    }, "Grammar"), " of RNA Localization")
474  }), /*#__PURE__*/React.createElement("div", {
475    style: {
476      fontFamily: "'IBM Plex Mono', monospace",
477      fontSize: 11,
478      letterSpacing: "0.22em",
479      textTransform: "uppercase",
480      color: C2_COLORS.muted,
481      marginBottom: 28
482    }
483  }, "Two questions guide our work"), /*#__PURE__*/React.createElement("div", {
484    className: "grid grid-cols-1 md:grid-cols-2 gap-x-12 gap-y-12 mb-16"
485  }, [{
486    num: "Q1",
487    tag: "Subcellular localization",
488    question: /*#__PURE__*/React.createElement(React.Fragment, null, "What rules govern ", /*#__PURE__*/React.createElement("em", {
489      style: {
490        color: C2_COLORS.accent,
491        fontStyle: "italic",
492        fontWeight: 500
493      }
494    }, "where"), " a transcript lives inside a cell?"),
495    prose: "Where a transcript lives inside a cell shapes when and how it is translated, yet these rules remain largely uncharacterized. We build subcellular spatial readouts to identify the molecular machinery that targets specific RNAs to dendrites, the ER, mitochondria, cytoplasmic granules, or other locations."
496  }, {
497    num: "Q2",
498    tag: "mRNA therapeutics",
499    question: /*#__PURE__*/React.createElement(React.Fragment, null, "Where does delivered mRNA ", /*#__PURE__*/React.createElement("em", {
500      style: {
501        color: C2_COLORS.accent,
502        fontStyle: "italic",
503        fontWeight: 500
504      }
505    }, "actually go"), " inside the cell?"),
506    prose: "The efficacy and toxicity of mRNA therapeutics depend on which compartment the delivered RNA lands in, how long it persists, and whether it triggers innate sensors. These intracellular fates are largely invisible to current assays."
507  }].map(({
508    num,
509    tag,
510    question,
511    prose
512  }) => /*#__PURE__*/React.createElement("div", {
513    key: num,
514    className: "flex flex-col"
515  }, /*#__PURE__*/React.createElement("div", {
516    className: "flex items-baseline gap-3 mb-4"
517  }, /*#__PURE__*/React.createElement("span", {
518    style: {
519      fontFamily: "'IBM Plex Mono', monospace",
520      fontSize: 13,
521      letterSpacing: "0.18em",
522      color: C2_COLORS.accent,
523      fontWeight: 500
524    }
525  }, num), /*#__PURE__*/React.createElement("span", {
526    style: {
527      fontFamily: "'IBM Plex Mono', monospace",
528      fontSize: 10,
529      letterSpacing: "0.2em",
530      textTransform: "uppercase",
531      color: C2_COLORS.muted
532    }
533  }, tag)), /*#__PURE__*/React.createElement("h3", {
534    style: {
535      fontFamily: "'EB Garamond', Georgia, serif",
536      fontWeight: 400,
537      fontSize: "clamp(28px, 2.6vw, 38px)",
538      lineHeight: 1.15,
539      letterSpacing: "-0.01em",
540      color: C2_COLORS.ink,
541      marginBottom: 16
542    }
543  }, question), /*#__PURE__*/React.createElement("p", {
544    style: {
545      fontFamily: "'EB Garamond', Georgia, serif",
546      fontWeight: 400,
547      fontSize: "clamp(17px, 1.3vw, 19px)",
548      lineHeight: 1.6,
549      color: C2_COLORS.text
550    }
551  }, prose)))), /*#__PURE__*/React.createElement("div", {
552    className: "grid grid-cols-1 md:grid-cols-2 gap-0"
553  }, [{
554    title: "Spatial omics technology",
555    tag: "Imaging × Sequencing",
556    desc: "We develop sequencing- and imaging-based methods to map RNA in intact tissues without dissociation.",
557    img: "research-imaging.png",
558    imgTag: "Microscopy"
559  }, {
560    title: "Systems biology",
561    tag: "Open-source tools",
562    desc: "We build open-source tools to analyze large-scale spatial datasets, revealing cell identity, tissue architecture, and intracellular signaling networks.",
563    img: "research-banksy.png",
564    imgTag: "BANKSY"
565  }, {
566    title: "Subcellular localization",
567    tag: "CRISPR/Cas9",
568    desc: "We use CRISPR/Cas9 perturbations to uncover mechanisms of RNA localization in healthy and diseased tissues.",
569    img: "research-crispr.png",
570    imgTag: "split-FISH"
571  }, {
572    title: "mRNA therapeutics",
573    tag: "Delivery & distribution",
574    desc: "We study RNA delivery and intracellular distribution to improve the efficacy and safety of RNA therapeutics.",
575    img: "research-rna.png",
576    imgTag: "Lipid nanoparticles"
577  }].map((r, i) => {
578    const tone = tones[i];
579    const programId = String(i + 1).padStart(2, "0");
580    return /*#__PURE__*/React.createElement("article", {
581      key: r.title,
582      className: "relative p-8 transition-colors flex flex-col",
583      style: {
584        border: `1px solid ${C2_COLORS.line}`,
585        marginLeft: i % 2 === 1 ? -1 : 0,
586        marginTop: i >= 2 ? -1 : 0,
587        background: C2_COLORS.white
588      },
589      onMouseOver: e => e.currentTarget.style.background = C2_COLORS.paper,
590      onMouseOut: e => e.currentTarget.style.background = C2_COLORS.white
591    }, /*#__PURE__*/React.createElement("div", {
592      className: "flex items-center justify-between gap-4 mb-5"
593    }, /*#__PURE__*/React.createElement("div", {
594      className: "inline-block px-2 py-1",
595      style: {
596        fontFamily: "'IBM Plex Mono', monospace",
597        fontSize: 10,
598        letterSpacing: "0.18em",
599        textTransform: "uppercase",
600        color: tone.label,
601        border: `1px solid ${tone.label}`
602      }
603    }, "[", r.tag, "]"), /*#__PURE__*/React.createElement("div", {
604      className: "flex gap-1.5 flex-none"
605    }, [0, 1, 2, 3].map(j => /*#__PURE__*/React.createElement("span", {
606      key: j,
607      className: "w-1.5 h-1.5 rounded-full",
608      style: {
609        background: j <= i ? tone.label : C2_COLORS.line
610      }
611    })))), /*#__PURE__*/React.createElement("h3", {
612      style: {
613        fontFamily: "'EB Garamond', Georgia, serif",
614        fontWeight: 400,
615        fontSize: 30,
616        letterSpacing: "-0.015em",
617        lineHeight: 1.1,
618        color: C2_COLORS.ink,
619        marginBottom: 12
620      }
621    }, r.title), /*#__PURE__*/React.createElement("p", {
622      style: {
623        fontFamily: "'Manrope', sans-serif",
624        fontSize: 15,
625        lineHeight: 1.7,
626        color: C2_COLORS.text,
627        marginBottom: 24
628      }
629    }, r.desc), /*#__PURE__*/React.createElement("div", {
630      className: "mt-auto relative overflow-hidden",
631      style: {
632        border: `1px solid ${C2_COLORS.line}`
633      }
634    }, /*#__PURE__*/React.createElement("img", {
635      src: r.img,
636      alt: r.title,
637      className: "w-full aspect-[4/3] object-cover"
638    }), /*#__PURE__*/React.createElement("span", {
639      className: "absolute bottom-3 right-3 px-2 py-0.5",
640      style: {
641        fontFamily: "'IBM Plex Mono', monospace",
642        fontSize: 10,
643        letterSpacing: "0.22em",
644        textTransform: "uppercase",
645        background: tone.label,
646        color: C2_COLORS.paper
647      }
648    }, r.imgTag)));
649  })), /*#__PURE__*/React.createElement("div", {
650    className: "mt-20 pt-10 border-t-2",
651    style: {
652      borderColor: C2_COLORS.ink
653    }
654  }, /*#__PURE__*/React.createElement("div", {
655    className: "flex items-baseline justify-between mb-8 flex-wrap gap-4"
656  }, /*#__PURE__*/React.createElement("h3", {
657    style: {
658      fontFamily: "'EB Garamond', Georgia, serif",
659      fontStyle: "italic",
660      fontWeight: 400,
661      fontSize: 28,
662      letterSpacing: "-0.01em",
663      color: C2_COLORS.ink
664    }
665  }, "Featured work")), /*#__PURE__*/React.createElement("div", {
666    className: "grid grid-cols-1 md:grid-cols-3 gap-x-10 gap-y-10"
667  }, [{
668    thumb: "pub-merfish.png",
669    j: "Science",
670    y: "2015",
671    t: "MERFISH — spatially resolved, highly multiplexed RNA profiling in single cells",
672    href: "https://www.science.org/doi/10.1126/science.aaa6090",
673    c: "#A03030"
674  }, {
675    thumb: "pub-splitfish.png",
676    j: "Nat. Methods",
677    y: "2020",
678    t: "split-FISH — highly specific multiplexed RNA imaging in t
678issues",
679    href: "https://www.nature.com/articles/s41592-020-0858-0",
680    c: "#5B3A8A"
681  }, {
682    thumb: "pub-banksy.png",
683    j: "Nat. Genetics",
684    y: "2024",
685    t: "BANKSY — scalable spatial omics data analysis",
686    href: "https://www.nature.com/articles/s41588-024-01664-3",
687    c: "#2D6E44"
688  }].map(({
689    thumb,
690    j,
691    y,
692    t,
693    href,
694    c
695  }) => /*#__PURE__*/React.createElement("a", {
696    key: t,
697    href: href,
698    target: "_blank",
699    rel: "noopener",
700    className: "group block"
701  }, /*#__PURE__*/React.createElement("div", {
702    className: "flex gap-4 items-start"
703  }, /*#__PURE__*/React.createElement("figure", {
704    className: "flex-none overflow-hidden",
705    style: {
706      width: 88,
707      height: 88,
708      border: `1px solid ${C2_COLORS.line}`,
709      background: C2_COLORS.paper
710    }
711  }, /*#__PURE__*/React.createElement("img", {
712    src: thumb,
713    alt: t,
714    className: "w-full h-full transition-transform duration-700 group-hover:scale-[1.06]",
715    style: {
716      objectFit: "cover",
717      objectPosition: "top"
718    }
719  })), /*#__PURE__*/React.createElement("div", {
720    className: "flex-1 min-w-0"
721  }, /*#__PURE__*/React.createElement("div", {
722    className: "flex items-baseline gap-2.5 mb-2"
723  }, /*#__PURE__*/React.createElement("span", {
724    style: {
725      fontFamily: "'EB Garamond', Georgia, serif",
726      fontWeight: 400,
727      fontSize: 28,
728      letterSpacing: "-0.02em",
729      color: c,
730      fontVariantNumeric: "tabular-nums",
731      lineHeight: 1
732    }
733  }, y), /*#__PURE__*/React.createElement("span", {
734    style: {
735      fontFamily: "'IBM Plex Mono', monospace",
736      fontSize: 10,
737      letterSpacing: "0.1em",
738      color: c,
739      borderBottom: `1px solid ${c}`,
740      paddingBottom: 1
741    }
742  }, j)), /*#__PURE__*/React.createElement("p", {
743    style: {
744      fontFamily: "'EB Garamond', Georgia, serif",
745      fontWeight: 400,
746      fontSize: 16,
747      lineHeight: 1.4,
748      letterSpacing: "-0.005em",
749      color: C2_COLORS.ink
750    }
751  }, t))), /*#__PURE__*/React.createElement("div", {
752    className: "mt-3 inline-flex items-center gap-1.5 transition-opacity opacity-60 group-hover:opacity-100",
753    style: {
754      fontFamily: "'IBM Plex Mono', monospace",
755      fontSize: 10,
756      letterSpacing: "0.18em",
757      textTransform: "uppercase",
758      color: c
759    }
760  }, "Read article ", /*#__PURE__*/React.createElement("span", {
761    "aria-hidden": "true"
762  }, "\u2197"))))))));
763};
764C2.Members = function MembersC2() {
765  const d = window.LAB_DATA;
766  return /*#__PURE__*/React.createElement("section", {
767    id: "members",
768    className: "py-10 md:py-20",
769    style: {
770      background: C2_COLORS.paper,
771      borderTop: `1px solid ${C2_COLORS.line}`
772    }
773  }, /*#__PURE__*/React.createElement("div", {
774    className: "mx-auto max-w-[1280px] px-5 md:px-8"
775  }, /*#__PURE__*/React.createElement(C2.Head, {
776    idx: "03",
777    eyebrow: "People",
778    title: "The Laboratory"
779  }), /*#__PURE__*/React.createElement("article", {
780    className: "grid grid-cols-1 md:grid-cols-12 gap-10 mb-14 pb-12 border-b",
781    style: {
782      borderColor: C2_COLORS.line
783    }
784  }, /*#__PURE__*/React.createElement("div", {
785    className: "md:col-span-3 min-w-0"
786  }, /*#__PURE__*/React.createElement("figure", {
787    className: "relative overflow-hidden mx-auto md:mx-0 max-w-[160px] md:max-w-[240px]",
788    style: {
789      background: C2_COLORS.line
790    }
791  }, /*#__PURE__*/React.createElement("img", {
792    src: d.pi.photo,
793    alt: d.pi.name,
794    className: "w-full aspect-[4/5] object-cover",
795    style: {
796      filter: "grayscale(1) contrast(1.05)"
797    }
798  }))), /*#__PURE__*/React.createElement("div", {
799    className: "md:col-span-9 md:pt-2 min-w-0"
800  }, /*#__PURE__*/React.createElement("h3", {
801    style: {
802      fontFamily: "'EB Garamond', Georgia, serif",
803      fontWeight: 400,
804      fontSize: "clamp(40px, 4.5vw, 56px)",
805      lineHeight: 0.95,
806      letterSpacing: "-0.02em",
807      color: C2_COLORS.ink
808    }
809  }, "Chen Kok Hao, ", /*#__PURE__*/React.createElement("em", {
810    style: {
811      color: C2_COLORS.accent
812    }
813  }, "Ph.D.")), /*#__PURE__*/React.createElement("ul", {
814    style: {
815      fontFamily: "'Manrope', sans-serif",
816      fontSize: 15.5,
817      lineHeight: 1.65,
818      color: C2_COLORS.text,
819      marginTop: 24,
820      listStyle: "none",
821      padding: 0
822    }
823  }, /*#__PURE__*/React.createElement("li", {
824    style: {
825      paddingLeft: 18,
826      position: "relative"
827    }
828  }, /*#__PURE__*/React.createElement("span", {
829    style: {
830      position: "absolute",
831      left: 0,
832      color: C2_COLORS.accent
833    }
834  }, "\u2014"), "Group Leader, Laboratory of Imagenomics"), /*#__PURE__*/React.createElement("li", {
835    style: {
836      paddingLeft: 18,
837      position: "relative"
838    }
839  }, /*#__PURE__*/React.createElement("span", {
840    style: {
841      position: "absolute",
842      left: 0,
843      color: C2_COLORS.accent
844    }
845  }, "\u2014"), "Principal Scientist II, Genome Institute of Singapore"), /*#__PURE__*/React.createElement("li", {
846    style: {
847      paddingLeft: 18,
848      position: "relative"
849    }
850  }, /*#__PURE__*/React.createElement("span", {
851    style: {
852      position: "absolute",
853      left: 0,
854      color: C2_COLORS.accent
855    }
856  }, "\u2014"), "Agency for Science, Technology, and Research"), /*#__PURE__*/React.createElement("li", {
857    style: {
858      paddingLeft: 18,
859      position: "relative"
860    }
861  }, /*#__PURE__*/React.createElement("span", {
862    style: {
863      position: "absolute",
864      left: 0,
865      color: C2_COLORS.accent
866    }
867  }, "\u2014"), "Member, National Initiative for RNA Biology and its Applications (NIRBA)")), /*#__PURE__*/React.createElement("div", {
868    className: "mt-6 flex flex-wrap gap-x-6 gap-y-2"
869  }, [["ORCID", d.pi.orcid], ["Google Scholar", d.pi.scholar], ["A*STAR Profile", "https://www.a-star.edu.sg/gis/our-people/faculty-staff/members/kok-hao-chen"]].map(([label, href]) => /*#__PURE__*/React.createElement("a", {
870    key: label,
871    href: href,
872    target: "_blank",
873    rel: "noopener",
874    style: {
875      fontFamily: "'IBM Plex Mono', monospace",
876      fontSize: 10,
877      letterSpacing: "0.18em",
878      textTransform: "uppercase",
879      color: C2_COLORS.ink,
880      borderBottom: `1px solid ${C2_COLORS.accent}`,
881      paddingBottom: 2
882    }
883  }, label, " \u2197"))))), /*#__PURE__*/React.createElement("div", {
884    className: "flex items-baseline justify-between mb-8"
885  }, /*#__PURE__*/React.createElement("h3", {
886    style: {
887      fontFamily: "'EB Garamond', Georgia, serif",
888      fontWeight: 400,
889      fontSize: 28,
890      letterSpacing: "-0.01em",
891      color: C2_COLORS.ink
892    }
893  }, "Current members"), /*#__PURE__*/React.createElement("span", {
894    style: {
895      fontFamily: "'IBM Plex Mono', monospace",
896      fontSize: 10,
897      letterSpacing: "0.22em",
898      textTransform: "uppercase",
899      color: C2_COLORS.muted
900    }
901  }, d.members.length, " scientists")), /*#__PURE__*/React.createElement("div", {
902    className: "grid grid-cols-2 md:grid-cols-4 lg:grid-cols-5 gap-x-6 gap-y-12"
903  }, d.members.map(m => /*#__PURE__*/React.createElement("figure", {
904    key: m.name,
905    className: "group"
906  }, /*#__PURE__*/React.createElement("div", {
907    className: "relative overflow-hidden",
908    style: {
909      background: C2_COLORS.line
910    }
911  }, m.photo ? /*#__PURE__*/React.createElement("img", {
912    src: m.photo,
913    alt: m.name,
914    className: "w-full aspect-[4/5] object-cover transition-all duration-500",
915    style: {
916      filter: "grayscale(1) contrast(1.05)"
917    },
918    onMouseEnter: e => e.currentTarget.style.filter = "grayscale(0) contrast(1)",
919    onMouseLeave: e => e.currentTarget.style.filter = "grayscale(1) contrast(1.05)"
920  }) : /*#__PURE__*/React.createElement("div", {
921    className: "w-full aspect-[4/5] flex items-center justify-center",
922    style: {
923      background: C2_COLORS.accent
924    }
925  }, /*#__PURE__*/React.createElement("div", {
926    style: {
927      fontFamily: "'EB Garamond', Georgia, serif",
928      fontWeight: 400,
929      fontSize: "clamp(64px, 7vw, 96px)",
930      color: C2_COLORS.paper,
931      lineHeight: 1,
932      letterSpacing: "-0.02em"
933    }
934  }, m.initial))), /*#__PURE__*/React.createElement("figcaption", {
935    className: "mt-3"
936  }, /*#__PURE__*/React.createElement("div", {
937    style: {
938      fontFamily: "'EB Garamond', Georgia, serif",
939      fontWeight: 500,
940      fontSize: 16,
941      lineHeight: 1.2,
942      color: C2_COLORS.ink
943    }
944  }, m.name, m.credentials && /*#__PURE__*/React.createElement("span", {
945    style: {
946      fontWeight: 400,
947      color: C2_COLORS.muted
948    }
949  }, ", ", m.credentials)), /*#__PURE__*/React.createElement("div", {
950    style: {
951      fontFamily: "'IBM Plex Mono', monospace",
952      fontSize: 10,
953      letterSpacing: "0.15em",
954      textTransform: "uppercase",
955      color: C2_COLORS.muted,
956      marginTop: 4
957    }
958  }, m.role))))), /*#__PURE__*/React.createElement("div", {
959    className: "mt-24 pt-12 border-t",
960    style: {
961      borderColor: C2_COLORS.line
962    }
963  }, /*#__PURE__*/React.createElement("div", {
964    className: "flex items-baseline justify-between mb-8"
965  }, /*#__PURE__*/React.createElement("h3", {
966    style: {
967      fontFamily: "'EB Garamond', Georgia, serif",
968      fontWeight: 400,
969      fontSize: 28,
970      letterSpacing: "-0.01em",
971      color: C2_COLORS.ink
972    }
973  }, "Alumni"), /*#__PURE__*/React.createElement("span", {
974    style: {
975      fontFamily: "'IBM Plex Mono', monospace",
976      fontSize: 10,
977      letterSpacing: "0.22em",
978      textTransform: "uppercase",
979      color: C2_COLORS.muted
980    }
981  }, d.alumni.length, " alumni")), /*#__PURE__*/React.createElement("div", {
982    className: "grid grid-cols-1 md:grid-cols-2 gap-x-12"
983  }, d.alumni.map(a => /*#__PURE__*/React.createElement("div", {
984    key: a.name,
985    className: "flex items-baseline gap-4 py-3 border-b",
986    style: {
987      borderColor: C2_COLORS.line
988    }
989  }, /*#__PURE__*/React.createElement("span", {
990    style: {
991      fontFamily: "'IBM Plex Mono', monospace",
992      fontSize: 10,
993      letterSpacing: "0.15em",
994      color: C2_COLORS.muted,
995      width: 72,
996      flexShrink: 0
997    }
998  }, a.years), /*#__PURE__*/React.createElement("span", {
999    style: {
1000      fontFamily: "'EB Garamond', Georgia, serif",
1001      fontWeight: 500,
1002      fontSize: 15,
1003      color: C2_COLORS.ink,
1004      flexShrink: 0
1005    }
1006  }, a.name), a.current && /*#__PURE__*/React.createElement("span", {
1007    style: {
1008      fontFamily: "'Manrope', sans-serif",
1009      fontSize: 12,
1010      color: C2_COLORS.muted,
1011      lineHeight: 1.4,
1012      marginLeft: "auto",
1013      textAlign: "right",
1014      maxWidth: "55%"
1015    }
1016  }, a.current)))))));
1017};
1018C2.Publications = function PublicationsC2() {
1019  const d = window.LAB_DATA;
1020  const list = d.publications;
1021  // journals as colored text, not pill backgrounds
1022  const journalColor = {
1023    "Science": "#a03030",
1024    "Nature Methods": "#5b3a8a",
1025    "Nature Genetics": "#2d6e44",
1026    "Nature Communications": "#0f5f6e",
1027    "PNAS": "#2d4c8a"
1028  };
1029  return /*#__PURE__*/React.createElement("section", {
1030    id: "publications",
1031    className: "py-10 md:py-20",
1032    style: {
1033      background: C2_COLORS.white,
1034      borderTop: `1px solid ${C2_COLORS.line}`
1035    }
1036  }, /*#__PURE__*/React.createElement("div", {
1037    className: "mx-auto max-w-[1280px] px-5 md:px-8"
1038  }, /*#__PURE__*/React.createElement(C2.Head, {
1039    idx: "04",
1040    eyebrow: "Our work",
1041    title: "Publications"
1042  }), /*#__PURE__*/React.createElement("div", null, list.map(p => {
1043    const c = journalColor[p.journal] || C2_COLORS.muted;
1044    return /*#__PURE__*/React.createElement("a", {
1045      key: p.title,
1046      href: p.doi,
1047      target: "_blank",
1048      rel: "noopener",
1049      className: "group block md:grid md:grid-cols-12 md:gap-6 py-4 md:py-6 border-b transition-colors",
1050      style: {
1051        borderColor: C2_COLORS.line
1052      },
1053      onMouseEnter: e => e.currentTarget.style.background = C2_COLORS.paper,
1054      onMouseLeave: e => e.currentTarget.style.background = "transparent"
1055    }, /*#__PURE__*/React.createElement("div", {
1056      className: "md:hidden flex items-center gap-3 mb-2"
1057    }, /*#__PURE__*/React.createElement("span", {
1058      style: {
1059        fontFamily: "'IBM Plex Mono', monospace",
1060        fontSize: 12,
1061        color: C2_COLORS.ink,
1062        fontVariantNumeric: "tabular-nums"
1063      }
1064    }, p.year), /*#__PURE__*/React.createElement("span", {
1065      style: {
1066        fontFamily: "'IBM Plex Mono', monospace",
1067        fontSize: 10,
1068        letterSpacing: "0.1em",
1069        color: c,
1070        borderBottom: `1px solid ${c}`,
1071        paddingBottom: 1
1072      }
1073    }, p.journal)), /*#__PURE__*/React.createElement("div", {
1074      className: "hidden md:block md:col-span-1 min-w-0"
1075    }, /*#__PURE__*/React.createElement("span", {
1076      style: {
1077        fontFamily: "'IBM Plex Mono', monospace",
1078        fontSize: 13,
1079        color: C2_COLORS.ink,
1080        fontVariantNumeric: "tabular-nums"
1081      }
1082    }, p.year)), /*#__PURE__*/React.createElement("div", {
1083      className: "hidden md:block md:col-span-3 min-w-0"
1084    }, /*#__PURE__*/React.createElement("span", {
1085      style: {
1086        fontFamily: "'IBM Plex Mono', monospace",
1087        fontSize: 11,
1088        letterSpacing: "0.1em",
1089        color: c,
1090        borderBottom: `1px solid ${c}`,
1091        paddingBottom: 1
1092      }
1093    }, p.journal)), /*#__PURE__*/React.createElement("div", {
1094      className: "md:col-span-8 min-w-0"
1095    }, /*#__PURE__*/React.createElement("h4", {
1096      style: {
1097        fontFamily: "'EB Garamond', Georgia, serif",
1098        fontWeight: 500,
1099        fontSize: 17,
1100        lineHeight: 1.4,
1101        letterSpacing: "-0.005em",
1102        color: C2_COLORS.ink,
1103        transition: "color 0.2s"
1104      },
1105      onMouseEnter: e => e.currentTarget.style.color = C2_COLORS.accent,
1106      onMouseLeave: e => e.currentTarget.style.color = C2_COLORS.ink
1107    }, p.title, " ", /*#__PURE__*/React.createElement("span", {
1108      style: {
1109        color: C2_COLORS.muted,
1110        fontSize: 13
1111      }
1112    }, "\u2197")), /*#__PURE__*/React.createElement("p", {
1113      style: {
1114        fontFamily: "'Manrope', sans-serif",
1115        fontSize: 12,
1116        lineHeight: 1.6,
1117        color: C2_COLORS.muted,
1118        marginTop: 6
1119      }
1120    }, p.authors)));
1121  })), /*#__PURE__*/React.createElement("p", {
1122    style: {
1123      fontFamily: "'IBM Plex Mono', monospace",
1124      fontSize: 10,
1125      letterSpacing: "0.18em",
1126      textTransform: "uppercase",
1127      color: C2_COLORS.muted,
1128      marginTop: 24
1129    }
1130  }, "* equal contribution \xA0\xB7\xA0 # co-corresponding authors")));
1131};
1132C2.News = function NewsC2() {
1133  const d = window.LAB_DATA;
1134  return /*#__PURE__*/React.createElement("section", {
1135    id: "news",
1136    className: "py-10 md:py-20",
1137    style: {
1138      background: C2_COLORS.paper,
1139      borderTop: `1px solid ${C2_COLORS.line}`
1140    }
1141  }, /*#__PURE__*/React.createElement("div", {
1142    className: "mx-auto max-w-[1280px] px-5 md:px-8"
1143  }, /*#__PURE__*/React.createElement(C2.Head, {
1144    idx: "02",
1145    eyebrow: "Dispatches",
1146    title: "News"
1147  }), /*#__PURE__*/React.createElement("div", {
1148    className: "grid grid-cols-1 md:grid-cols-2 gap-x-12 gap-y-10"
1149  }, d.news.map((n, i) => /*#__PURE__*/React.createElement("article", {
1150    key: n.title,
1151    className: "pt-6 border-t",
1152    style: {
1153      borderColor: C2_COLORS.ink
1154    }
1155  }, /*#__PURE__*/React.createElement("div", {
1156    style: {
1157      fontFamily: "'IBM Plex Mono', monospace",
1158      fontSize: 10,
1159      letterSpacing: "0.22em",
1160      textTransform: "uppercase",
1161      color: C2_COLORS.accent,
1162      marginBottom: 12
1163    }
1164  }, n.date, " \xB7 Log.", String(i + 1).padStart(3, "0")), /*#__PURE__*/React.createElement("h3", {
1165    style: {
1166      fontFamily: "'EB Garamond', Georgia, serif",
1167      fontWeight: 400,
1168      fontSize: 24,
1169      lineHeight: 1.15,
1170      letterSpacing: "-0.01em",
1171      color: C2_COLORS.ink,
1172      marginBottom: 10
1173    }
1174  }, n.title), /*#__PURE__*/React.createElement("p", {
1175    style: {
1176      fontFamily: "'Manrope', sans-serif",
1177      fontSize: 15,
1178      lineHeight: 1.7,
1179      color: C2_COLORS.text
1180    }
1181  }, n.note))))));
1182};
1183
1184// Embedded OSM map via static tile (no key needed) — we'll use a schematic SVG to guarantee offline
1185C2.MapFig = function MapFig() {
1186  return /*#__PURE__*/React.createElement("div", {
1187    className: "relative w-full aspect-[4/3] overflow-hidden",
1188    style: {
1189      background: C2_COLORS.paper,
1190      border: `1px solid ${C2_COLORS.line}`
1191    }
1192  }, /*#__PURE__*/React.createElement("iframe", {
1193    title: "Genome Institute of Singapore \u2014 map",
1194    src: "https://www.google.com/maps?q=Genome+Institute+of+Singapore,+60+Biopolis+Street,+Singapore&output=embed&z=16",
1195    loading: "lazy",
1196    referrerPolicy: "no-referrer-when-downgrade",
1197    style: {
1198      width: "100%",
1199      height: "100%",
1200      border: 0,
1201      filter: "grayscale(0.25) contrast(0.96)"
1202    }
1203  }), /*#__PURE__*/React.createElement("div", {
1204    style: {
1205      position: "absolute",
1206      left: 12,
1207      top: 10,
1208      padding: "4px 8px",
1209      background: "rgba(248,245,238,0.92)",
1210      border: `1px solid ${C2_COLORS.line}`,
1211      fontFamily: "'IBM Plex Mono', monospace",
1212      fontSize: 9,
1213      letterSpacing: "0.18em",
1214      textTransform: "uppercase",
1215      color: C2_COLORS.muted,
1216      pointerEvents: "none"
1217    }
1218  }, "1.3054\xB0N \xB7 103.7883\xB0E"), /*#__PURE__*/React.createElement("a", {
1219    href: "https://www.google.com/maps/place/Genome+Institute+of+Singapore/@1.3054,103.7883,17z",
1220    target: "_blank",
1221    rel: "noopener",
1222    style: {
1223      position: "absolute",
1224      right: 12,
1225      bottom: 10,
1226      padding: "5px 10px",
1227      background: C2_COLORS.ink,
1228      color: C2_COLORS.paper,
1229      fontFamily: "'IBM Plex Mono', monospace",
1230      fontSize: 10,
1231      letterSpacing: "0.18em",
1232      textTransform: "uppercase",
1233      textDecoration: "none"
1234    }
1235  }, "Open in Maps \u2197"));
1236};
1237C2.Software = function SoftwareC2() {
1238  const d = window.LAB_DATA;
1239  const list = d.software || [];
1240  return /*#__PURE__*/React.createElement("section", {
1241    id: "software",
1242    className: "py-10 md:py-20",
1243    style: {
1244      background: C2_COLORS.paper,
1245      borderTop: `1px solid ${C2_COLORS.line}`
1246    }
1247  }, /*#__PURE__*/React.createElement("div", {
1248    className: "mx-auto max-w-[1280px] px-5 md:px-8"
1249  }, /*#__PURE__*/React.createElement(C2.Head, {
1250    idx: "05",
1251    eyebrow: "Open source",
1252    title: /*#__PURE__*/React.createElement(React.Fragment, null, "Software ", /*#__PURE__*/React.createElement("em", {
1253      style: {
1254        color: C2_COLORS.accent,
1255        fontStyle: "italic"
1256      }
1257    }, "& code"))
1258  }), /*#__PURE__*/React.createElement("p", {
1259    style: {
1260      fontFamily: "'EB Garamond', Georgia, serif",
1261      fontWeight: 400,
1262      fontSize: "clamp(17px, 1.3vw, 19px)",
1263      lineHeight: 1.55,
1264      color: C2_COLORS.text,
1265      marginBottom: 36
1266    }
1267  }, "We release our analysis pipelines, image processors, and computational tools openly. Browse the full collection on GitHub, or jump straight to a project below."), /*#__PURE__*/React.createElement("div", {
1268    className: "grid grid-cols-1 md:grid-cols-3 gap-6"
1269  }, list.map(s => /*#__PURE__*/React.createElement("a", {
1270    key: s.name,
1271    href: s.repo,
1272    target: "_blank",
1273    rel: "noopener",
1274    className: "group p-6 transition-colors",
1275    style: {
1276      background: C2_COLORS.white,
1277      border: `1px solid ${C2_COLORS.line}`
1278    },
1279    onMouseEnter: e => e.currentTarget.style.borderColor = C2_COLORS.accent,
1280    onMouseLeave: e => e.currentTarget.style.borderColor = C2_COLORS.line
1281  }, /*#__PURE__*/React.createElement("div", {
1282    className: "flex items-center justify-between mb-5"
1283  }, /*#__PURE__*/React.createElement("span", {
1284    style: {
1285      fontFamily: "'IBM Plex Mono', monospace",
1286      fontSize: 10,
1287      letterSpacing: "0.22em",
1288      textTransform: "uppercase",
1289      color: C2_COLORS.accent
1290    }
1291  }, "Repository"), /*#__PURE__*/React.createElement(C2.Icon, {
1292    name: "code",
1293    size: 16,
1294    stroke: C2_COLORS.muted
1295  })), /*#__PURE__*/React.createElement("h3", {
1296    style: {
1297      fontFamily: "'EB Garamond', Georgia, serif",
1298      fontWeight: 500,
1299      fontSize: 26,
1300      letterSpacing: "-0.015em",
1301      lineHeight: 1.1,
1302      color: C2_COLORS.ink,
1303      marginBottom: 10
1304    }
1305  }, s.name), /*#__PURE__*/React.createElement("p", {
1306    style: {
1307      fontFamily: "'Manrope', sans-serif",
1308      fontSize: 14,
1309      lineHeight: 1.6,
1310      color: C2_COLORS.text,
1311      marginBottom: 16
1312    }
1313  }, s.desc), /*#__PURE__*/React.createElement("div", {
1314    className: "flex items-center gap-3 flex-wrap",
1315    style: {
1316      paddingTop: 14,
1317      borderTop: `1px solid ${C2_COLORS.line}`
1318    }
1319  }, /*#__PURE__*/React.createElement("span", {
1320    style: {
1321      fontFamily: "'IBM Plex Mono', monospace",
1322      fontSize: 10,
1323      letterSpacing: "0.15em",
1324      textTransform: "uppercase",
1325      color: C2_COLORS.muted
1326    }
1327  }, s.lang), /*#__PURE__*/React.createElement("span", {
1328    style: {
1329      width: 3,
1330      height: 3,
1331      borderRadius: "50%",
1332      background: C2_COLORS.muted,
1333      opacity: 0.5
1334    }
1335  }), /*#__PURE__*/React.createElement("span", {
1336    style: {
1337      fontFamily: "'IBM Plex Mono', monospace",
1338      fontSize: 10,
1339      letterSpacing: "0.15em",
1340      textTransform: "uppercase",
1341      color: C2_COLORS.muted
1342    }
1343  }, s.paper)), /*#__PURE__*/React.createElement("div", {
1344    className: "mt-5 inline-flex items-center gap-2 transition-opacity opacity-70 group-hover:opacity-100",
1345    style: {
1346      fontFamily: "'IBM Plex Mono', monospace",
1347      fontSize: 10,
1348      letterSpacing: "0.18em",
1349      textTransform: "uppercase",
1350      color: C2_COLORS.accent,
1351      borderBottom: `1px solid ${C2_COLORS.accent}`,
1352      paddingBottom: 2
1353    }
1354  }, "View on GitHub ", /*#__PURE__*/React.createElement("span", {
1355    "aria-hidden": "true"
1356  }, "\u2197"))))), /*#__PURE__*/React.createElement("div", {
1357    className: "mt-10"
1358  }, /*#__PURE__*/React.createElement("a", {
1359    href: "https://github.com/KHChenLab",
1360    target: "_blank",
1361    rel: "noopener",
1362    style: {
1363      fontFamily: "'IBM Plex Mono', monospace",
1364      fontSize: 11,
1365      letterSpacing: "0.18em",
1366      textTransform: "uppercase",
1367      color: C2_COLORS.ink,
1368      borderBottom: `1px solid ${C2_COLORS.ink}`,
1369      paddingBottom: 2
1370    }
1371  }, "All repositories on github.com/KHChenLab \u2197"))));
1372};
1373C2.LabLife = function LabLifeC2() {
1374  const d = window.LAB_DATA;
1375  const list = d.gallery || [];
1376  const [open, setOpen] = React.useState(null);
1377  React.useEffect(() => {
1378    if (open === null) return;
1379    const onKey = e => {
1380      if (e.key === "Escape") setOpen(null);
1381      if (e.key === "ArrowRight") setOpen(o => (o + 1) % list.length);
1382      if (e.key === "ArrowLeft") setOpen(o => (o - 1 + list.length) % list.length);
1383    };
1384    window.addEventListener("keydown", onKey);
1385    document.body.style.overflow = "hidden";
1386    return () => {
1387      window.removeEventListener("keydown", onKey);
1388      document.body.style.overflow = "";
1389    };
1390  }, [open, list.length]);
1391  return /*#__PURE__*/React.createElement("section", {
1392    id: "lab-life",
1393    className: "py-10 md:py-20",
1394    style: {
1395      background: C2_COLORS.white,
1396      borderTop: `1px solid ${C2_COLORS.line}`
1397    }
1398  }, /*#__PURE__*/React.createElement("div", {
1399    className: "mx-auto max-w-[1280px] px-5 md:px-8"
1400  }, /*#__PURE__*/React.createElement(C2.Head, {
1401    idx: "06",
1402    eyebrow: "Album",
1403    title: "Lab Life"
1404  }), /*#__PURE__*/React.createElement("p", {
1405    style: {
1406      fontFamily: "'EB Garamond', Georgia, serif",
1407      fontWeight: 400,
1408      fontSize: "clamp(17px, 1.3vw, 19px)",
1409      lineHeight: 1.55,
1410      color: C2_COLORS.text,
1411      marginBottom: 36
1412    }
1413  }, "Moments from the lab \u2014 retreats, milestones, and the people behind the science."), /*#__PURE__*/React.createElement("div", {
1414    className: "grid grid-cols-2 md:grid-cols-4 gap-x-4 gap-y-7"
1415  }, list.map((g, i) => /*#__PURE__*/React.createElement("button", {
1416    key: g.src,
1417    type: "button",
1418    onClick: () => setOpen(i),
1419    className: "group text-left",
1420    style: {
1421      background: "none",
1422      border: "none",
1423      padding: 0,
1424      cursor: "zoom-in"
1425    }
1426  }, /*#__PURE__*/React.createElement("figure", null, /*#__PURE__*/React.createElement("div", {
1427    className: "overflow-hidden",
1428    style: {
1429      background: C2_COLORS.line,
1430      border: `1px solid ${C2_COLORS.line}`
1431    }
1432  }, /*#__PURE__*/React.createElement("img", {
1433    src: g.src,
1434    alt: g.caption,
1435    className: "w-full aspect-[4/3] object-cover transition-all duration-500",
1436    style: {
1437      filter: "grayscale(0.6) contrast(1.02)"
1438    },
1439    onMouseEnter: e => e.currentTarget.style.filter = "grayscale(0) contrast(1)",
1440    onMouseLeave: e => e.currentTarget.style.filter = "grayscale(0.6) contrast(1.02)"
1441  })), /*#__PURE__*/React.createElement("figcaption", {
1442    className: "flex items-baseline justify-between mt-3"
1443  }, /*#__PURE__*/React.createElement("span", {
1444    style: {
1445      fontFamily: "'IBM Plex Mono', monospace",
1446      fontSize: 10,
1447      letterSpacing: "0.22em",
1448      textTransform: "uppercase",
1449      color: C2_COLORS.muted
1450    }
1451  }, g.date), /*#__PURE__*/React.createElement("span", {
1452    style: {
1453      fontFamily: "'EB Garamond', Georgia, serif",
1454      fontStyle: "italic",
1455      fontSize: 13,
1456      color: C2_COLORS.text
1457    }
1458  }, g.caption))))))), open !== null && /*#__PURE__*/React.createElement("div", {
1459    onClick: () => setOpen(null),
1460    style: {
1461      position: "fixed",
1462      inset: 0,
1463      zIndex: 100,
1464      background: "rgba(14,26,43,0.92)",
1465      display: "flex",
1466      flexDirection: "column",
1467      alignItems: "center",
1468      justifyContent: "center",
1469      padding: "5vh 5vw",
1470      cursor: "zoom-out"
1471    }
1472  }, /*#__PURE__*/React.createElement("img", {
1473    src: list[open].src,
1474    alt: list[open].caption,
1475    onClick: e => e.stopPropagation(),
1476    style: {
1477      maxWidth: "100%",
1478      maxHeight: "82vh",
1479      objectFit: "contain",
1480      boxShadow: "0 20px 80px rgba(0,0,0,0.5)",
1481      cursor: "default"
1482    }
1483  }), /*#__PURE__*/React.createElement("div", {
1484    className: "flex items-center justify-between gap-6 mt-4",
1485    style: {
1486      width: "min(900px, 100%)",
1487      color: C2_COLORS.paper
1488    }
1489  }, /*#__PURE__*/React.createElement("span", {
1490    style: {
1491      fontFamily: "'IBM Plex Mono', monospace",
1492      fontSize: 11,
1493      letterSpacing: "0.22em",
1494      textTransform: "uppercase",
1495      opacity: 0.7
1496    }
1497  }, list[open].date, " \xB7 ", String(open + 1).padStart(2, "0"), "/", String(list.length).padStart(2, "0")), /*#__PURE__*/React.createElement("span", {
1498    style: {
1499      fontFamily: "'EB Garamond', Georgia, serif",
1500      fontStyle: "italic",
1501      fontSize: 16
1502    }
1503  }, list[open].caption), /*#__PURE__*/React.createElement("button", {
1504    onClick: e => {
1505      e.stopPropagation();
1506      setOpen(null);
1507    },
1508    style: {
1509      fontFamily: "'IBM Plex Mono', monospace",
1510      fontSize: 11,
1511      letterSpacing: "0.22em",
1512      textTransform: "uppercase",
1513      color: C2_COLORS.paper,
1514      background: "none",
1515      border: `1px solid ${C2_COLORS.paper}`,
1516      padding: "6px 12px",
1517      cursor: "pointer"
1518    }
1519  }, "Close \u2715"))));
1520};
1521C2.Contact = function ContactC2() {
1522  return /*#__PURE__*/React.createElement("section", {
1523    id: "contact",
1524    className: "py-10 md:py-20",
1525    style: {
1526      background: C2_COLORS.white,
1527      borderTop: `1px solid ${C2_COLORS.line}`
1528    }
1529  }, /*#__PURE__*/React.createElement("div", {
1530    className: "mx-auto max-w-[1280px] px-5 md:px-8"
1531  }, /*#__PURE__*/React.createElement(C2.Head, {
1532    idx: "07",
1533    eyebrow: "Correspondence",
1534    title: /*#__PURE__*/React.createElement(React.Fragment, null, "Get in ", /*#__PURE__*/React.createElement("em", {
1535      style: {
1536        color: C2_COLORS.accent,
1537        fontStyle: "italic"
1538      }
1539    }, "touch"), ".")
1540  }), /*#__PURE__*/React.createElement("div", {
1541    className: "grid grid-cols-1 lg:grid-cols-12 gap-10"
1542  }, /*#__PURE__*/React.createElement("div", {
1543    className: "lg:col-span-7 min-w-0"
1544  }, /*#__PURE__*/React.createElement("div", {
1545    className: "p-6 mb-12",
1546    style: {
1547      border: `1px solid ${C2_COLORS.accent2}`,
1548      background: C2_COLORS.paper
1549    }
1550  }, /*#__PURE__*/React.createElement("div", {
1551    style: {
1552      fontFamily: "'IBM Plex Mono', monospace",
1553      fontSize: 10,
1554      letterSpacing: "0.22em",
1555      textTransform: "uppercase",
1556      color: C2_COLORS.accent2,
1557      marginBottom: 8
1558    }
1559  }, "\u25CF Now hiring"), /*#__PURE__*/React.createElement("h3", {
1560    style: {
1561      fontFamily: "'EB Garamond', Georgia, serif",
1562      fontWeight: 400,
1563      fontSize: 24,
1564      lineHeight: 1.2,
1565      letterSpacing: "-0.01em",
1566      color: C2_COLORS.ink,
1567      marginBottom: 10
1568    }
1569  }, "We are hiring."), /*#__PURE__*/React.createElement("p", {
1570    style: {
1571      fontFamily: "'Manrope', sans-serif",
1572      fontSize: 15,
1573      lineHeight: 1.7,
1574      color: C2_COLORS.text,
1575      marginBottom: 12
1576    }
1577  }, "Post-doctoral fellows, PhD students, and research officers at all levels \u2014 if you are passionate about spatial omics and systems biology, we'd love to hear from you."), /*#__PURE__*/React.createElement(C2.Email, {
1578    style: {
1579      fontFamily: "'IBM Plex Mono', monospace",
1580      fontSize: 11,
1581      letterSpacing: "0.18em",
1582      textTransform: "uppercase",
1583      color: C2_COLORS.ink,
1584      borderBottom: `1px solid ${C2_COLORS.accent2}`,
1585      paddingBottom: 2
1586    }
1587  }, "Send your CV \u2197")), /*#__PURE__*/React.createElement("dl", {
1588    className: "grid grid-cols-1 sm:grid-cols-2 gap-x-6 gap-y-8"
1589  }
1589, [["Location", /*#__PURE__*/React.createElement(React.Fragment, null, "Level 5, Genome Institute of Singapore", /*#__PURE__*/React.createElement("br", null), "Biopolis research campus, One-North"), "pin"], ["Mailing address", /*#__PURE__*/React.createElement(React.Fragment, null, "60 Biopolis Street, Level 5", /*#__PURE__*/React.createElement("br", null), "Genome Building, Singapore 138672"), "inbox"], ["Email", /*#__PURE__*/React.createElement(C2.Email, {
1590    style: {
1591      color: C2_COLORS.ink,
1592      borderBottom: `1px solid ${C2_COLORS.accent}`,
1593      paddingBottom: 1
1594    }
1595  }), "mail"], ["Twitter / X", /*#__PURE__*/React.createElement("a", {
1596    href: "https://twitter.com/KHChenLab",
1597    target: "_blank",
1598    rel: "noopener",
1599    style: {
1600      color: C2_COLORS.ink,
1601      borderBottom: `1px solid ${C2_COLORS.accent}`,
1602      paddingBottom: 1
1603    }
1604  }, "@KHChenLab"), "twitter"]].map(([label, v, icon]) => /*#__PURE__*/React.createElement("div", {
1605    key: label,
1606    className: "flex items-start gap-3"
1607  }, /*#__PURE__*/React.createElement("div", {
1608    className: "pt-1 shrink-0"
1609  }, /*#__PURE__*/React.createElement(C2.Icon, {
1610    name: icon,
1611    size: 18,
1612    stroke: C2_COLORS.accent
1613  })), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("dt", {
1614    style: {
1615      fontFamily: "'IBM Plex Mono', monospace",
1616      fontSize: 10,
1617      letterSpacing: "0.22em",
1618      textTransform: "uppercase",
1619      color: C2_COLORS.muted,
1620      marginBottom: 4
1621    }
1622  }, label), /*#__PURE__*/React.createElement("dd", {
1623    style: {
1624      fontFamily: "'Manrope', sans-serif",
1625      fontSize: 14,
1626      lineHeight: 1.6,
1627      color: C2_COLORS.ink
1628    }
1629  }, v)))))), /*#__PURE__*/React.createElement("div", {
1630    className: "lg:col-span-5 min-w-0"
1631  }, /*#__PURE__*/React.createElement(C2.MapFig, null), /*#__PURE__*/React.createElement("p", {
1632    style: {
1633      fontFamily: "'IBM Plex Mono', monospace",
1634      fontSize: 10,
1635      letterSpacing: "0.2em",
1636      textTransform: "uppercase",
1637      color: C2_COLORS.muted,
1638      marginTop: 10,
1639      textAlign: "center"
1640    }
1641  }, "Genome Institute of Singapore \xB7 60 Biopolis Street \xB7 Singapore")))));
1642};
1643C2.Page = function PageC2() {
1644  return /*#__PURE__*/React.createElement("div", {
1645    style: {
1646      background: C2_COLORS.paper,
1647      color: C2_COLORS.ink,
1648      fontFamily: "'Manrope', sans-serif"
1649    }
1650  }, /*#__PURE__*/React.createElement(C2.Nav, null), /*#__PURE__*/React.createElement(C2.Hero, null), /*#__PURE__*/React.createElement(C2.Research, null), /*#__PURE__*/React.createElement(C2.News, null), /*#__PURE__*/React.createElement(C2.Members, null), /*#__PURE__*/React.createElement(C2.Publications, null), /*#__PURE__*/React.createElement(C2.Software, null), /*#__PURE__*/React.createElement(C2.LabLife, null), /*#__PURE__*/React.createElement(C2.Contact, null), /*#__PURE__*/React.createElement("footer", {
1651    className: "py-10",
1652    style: {
1653      background: C2_COLORS.ink,
1654      color: "rgba(250,248,243,0.6)"
1655    }
1656  }, /*#__PURE__*/React.createElement("div", {
1657    className: "mx-auto max-w-[1280px] px-5 md:px-8 flex items-center justify-between flex-wrap gap-4"
1658  }, /*#__PURE__*/React.createElement("span", {
1659    style: {
1660      fontFamily: "'IBM Plex Mono', monospace",
1661      fontSize: 10,
1662      letterSpacing: "0.22em",
1663      textTransform: "uppercase"
1664    }
1665  }, "\xA9 2026 Chen Laboratory \xB7 GIS \xB7 A*STAR"), /*#__PURE__*/React.createElement("span", {
1666    style: {
1667      fontFamily: "'IBM Plex Mono', monospace",
1668      fontSize: 10,
1669      letterSpacing: "0.22em",
1670      textTransform: "uppercase"
1671    }
1672  }, "Biopolis \xB7 Singapore"))));
1673};
1674window.C2 = C2;

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.