1<!DOCTYPE html> 2<html lang="en" data-theme="dark"> 3<head> 4 <meta charset="utf-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1" /> 6 <title>Haotian Xue</title> 7 <meta name="description" content="Haotian Xue â ML PhD @ Georgia Tech" /> 8 <link rel="shortcut icon" href="static/image/logos/georgia-tech-yellow-jackets-ncaa-logo-sticker-5145-756891.png" /> 9 <style> 10 :root { 11 --bg: #0d1117; 12 --surface: #161b22; 13 --border: #30363d; 14 --text: #e6edf3; 15 --muted: #8b949e; 16 --green: #39d353; 17 --cyan: #58a6ff; 18 --accent: #58a6ff; 19 --purple: #bc8cff; 20 --red: #ff7b72; 21 --yellow: #e3b341; 22 --radius: 10px; 23 --font: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'Consolas', monospace; 24 } 25 html[data-theme="light"] { 26 --bg: #f6f8fa; 27 --surface: #ffffff; 28 --border: #d0d7de; 29 --text: #1f2328; 30 --muted: #636c76; 31 --green: #1a7f37; 32 --cyan: #0969da; 33 --accent: #0969da; 34 --purple: #8250df; 35 --red: #cf222e; 36 --yellow: #9a6700; 37 } 38 39 *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } 40 html, body { 41 background: var(--bg); 42 color: var(--text); 43 font-family: var(--font); 44 font-size: 14px; 45 line-height: 1.6; 46 min-height: 100vh; 47 } 48 a { color: var(--accent); text-decoration: none; } 49 a:hover { text-decoration: underline; } 50 51 .page { 52 max-width: 1040px; 53 margin: 0 auto; 54 padding: 40px 32px 80px; 55 } 56 57 /* ââ top bar âââââââââââââââââââââââââââââââââââââââ */ 58 .topbar { 59 display: flex; 60 justify-content: space-between; 61 align-items: center; 62 margin-bottom: 32px; 63 } 64 .topbar .path { font-size: 12px; letter-spacing: .03em; } 65 .topbar .path .slash { color: var(--muted); opacity: .5; } 66 .topbar .path .seg { color: var(--green); } 67 68 .top-right { display: flex; gap: 8px; align-items: center; } 69 70 .icon-btn { 71 background: none; 72 border: 1px solid var(--border); 73 color: var(--muted); 74 font-family: var(--font); 75 font-size: 11px; 76 padding: 3px 9px; 77 border-radius: 6px; 78 cursor: pointer; 79 transition: border-color .15s, color .15s; 80 text-decoration: none; 81 display: inline-block; 82 } 83 .icon-btn:hover { border-color: var(--accent); color: var(--accent); text-decoration: none; } 84 85 /* ââ section label âââââââââââââââââââââââââââââââââ */ 86 .sec-label { 87 font-size: 11px; 88 color: var(--muted); 89 letter-spacing: .08em; 90 margin-bottom: 10px; 91 display: flex; 92 align-items: center; 93 gap: 8px; 94 } 95 .sec-label::before { content: '##'; color: var(--green); font-weight: 700; } 96 .sec-label::after { content: ''; flex: 1; height: 1px; background: var(--border); } 97 98 /* ââ hero ââââââââââââââââââââââââââââââââââââââââââ */ 99 .hero { 100 display: grid; 101 grid-template-columns: 148px 1fr; 102 gap: 28px; 103 align-items: flex-start; 104 margin-bottom: 40px; 105 } 106 107 .portrait-wrap { 108 position: relative; 109 width: 148px; 110 height: 148px; 111 cursor: pointer; 112 user-select: none; 113 flex-shrink: 0; 114 } 115 .portrait-wrap img { 116 position: absolute; 117 inset: 0; 118 width: 100%; 119 height: 100%; 120 object-fit: cover; 121 border-radius: 10px; 122 transition: opacity .35s ease; 123 border: 1px solid var(--border); 124 } 125 .portrait-wrap .main { opacity: 1; z-index: 1; } 126 .portrait-wrap .cat { opacity: 0; z-index: 2; } 127 .portrait-wrap.revealed .main { opacity: 0; } 128 .portrait-wrap.revealed .cat { opacity: 1; } 129 .cat-badge { 130 position: absolute; 131 bottom: -10px; right: -10px; 132 z-index: 10; 133 background: var(--surface); 134 border: 1px solid var(--border); 135 border-radius: 6px; 136 padding: 2px 7px; 137 font-size: 10px; 138 color: var(--muted); 139 cursor: pointer; 140 white-space: nowrap; 141 transition: border-color .15s, color .15s; 142 } 143 .cat-badge:hover { border-color: var(--green); color: var(--green); } 144 145 .cat-hint { 146 position: absolute; 147 top: calc(100% + 8px); left: 50%; 148 transform: translateX(-50%); 149 display: flex; flex-direction: column; align-items: center; gap: 2px; 150 pointer-events: none; 151 animation: hintBob 1.6s ease-in-out infinite; 152 transition: opacity .4s ease; 153 white-space: nowrap; 154 z-index: 50; 155 } 156 .cat-hint.hidden { opacity: 0; pointer-events: none; } 157 .cat-hint-arrow { color: var(--green); font-size: 13px; line-height: 1; } 158 .cat-hint-label { 159 font-size: 10px; color: var(--green); 160 background: var(--surface); border: 1px solid var(--border); 161 border-radius: 5px; padding: 2px 7px; 162 }
163 @keyframes hintBob { 164 0%, 100% { transform: translateX(-50%) translateY(0); } 165 50% { transform: translateX(-50%) translateY(-4px); } 166 } 167 168 .bio h1 { font-size: 22px; font-weight: 700; letter-spacing: -.01em; margin-bottom: 2px; } 169 .bio .pron { font-size: 11px; color: var(--muted); margin-bottom: 10px; } 170 .bio .tagline { font-size: 13px; color: var(--muted); margin-bottom: 14px; line-height: 1.5; } 171 .bio .tagline a { color: var(--accent); } 172 173 .links-row { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; } 174 .links-row a { 175 display: inline-flex; align-items: center; gap: 5px; 176 font-size: 12px; color: var(--muted); 177 border: 1px solid var(--border); border-radius: 6px; padding: 3px 10px; 178 transition: border-color .15s, color .15s; 179 } 180 .links-row a:hover { border-color: var(--accent); color: var(--accent); text-decoration: none; } 181 .email { font-size: 12px; color: var(--muted); } 182 .email span { color: var(--green); } 183 184 /* ââ terminal window âââââââââââââââââââââââââââââââ */ 185 .term { 186 background: var(--surface); 187 border: 1px solid var(--border); 188 border-radius: var(--radius); 189 overflow: hidden; 190 margin-bottom: 32px; 191 } 192 .term-bar { 193 background: color-mix(in oklab, var(--border) 60%, var(--surface)); 194 padding: 7px 12px; 195 display: flex; 196 align-items: center; 197 gap: 10px; 198 } 199 .term-dots { display: flex; gap: 6px; } 200 .term-dots span { width: 10px; height: 10px; border-radius: 50%; } 201 .term-dots .r { background: #ff5f57; } 202 .term-dots .y { background: #febc2e; } 203 .term-dots .g { background: #28c840; } 204 .term-title { flex: 1; text-align: center; font-size: 11px; color: var(--muted); letter-spacing: .05em; } 205 206 .term-body { padding: 14px 18px; font-size: 13px; line-height: 1.8; } 207 .prompt { color: var(--green); } 208 .cmd { color: var(--yellow); } 209 .key { color: var(--cyan); } 210 .val { color: var(--muted); } 211 .cursor { 212 display: inline-block; width: 8px; height: 14px; 213 background: var(--green); vertical-align: text-bottom; 214 animation: blink 1.1s step-end infinite; 215 } 216 @keyframes blink { 50% { opacity: 0; } } 217 218 /* ââ news log ââââââââââââââââââââââââââââââââââââââ */ 219 .news-log { 220 list-style: none; 221 font-size: 12px; 222 line-height: 1.7; 223 overflow-y: auto; 224 max-height: 210px; 225 padding: 12px 18px; 226 } 227 .news-log::-webkit-scrollbar { width: 4px; } 228 .news-log::-webkit-scrollbar-track { background: transparent; } 229 .news-log::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; } 230 231 .news-log li { display: flex; gap: 10px; padding: 3px 0; border-bottom: 1px dashed color-mix(in oklab, var(--border) 50%, transparent); } 232 .news-log li:last-child { border-bottom: none; } 233 .news-log .ts { color: var(--green); flex-shrink: 0; min-width: 60px; } 234 .news-log .msg { color: var(--muted); } 235 .news-log .msg a { color: var(--cyan); } 236 .news-log .msg strong { color: var(--text); } 237 238 /* ââ publications ââââââââââââââââââââââââââââââââââ */ 239 .pub-list { list-style: none; } 240 .pub-list > li { 241 padding: 16px 0; 242 border-bottom: 1px solid var(--border); 243 } 244 .pub-list > li:last-child { border-bottom: none; } 245 246 .pub-item { display: block; } 247 /* interactive terminal input */ 248 .term-input-row { 249 display: flex; align-items: center; gap: 6px; 250 border-top: 1px solid var(--border); 251 padding: 10px 18px; 252 } 253 .term-input-row .prompt { color: var(--green); flex-shrink: 0; } 254 .term-input { 255 flex: 1; background: none; border: none; outline: none; 256 color: var(--text); font-family: var(--font); font-size: 13px; 257 caret-color: var(--green); 258 } 259 .term-output-area { 260 padding: 0 18px; 261 font-size: 13px; 262 line-height: 1.75; 263 } 264 .term-output-area .out-line { 265 display: flex; align-items: flex-start; gap: 8px; 266 padding: 2px 0; 267 animation: fadeIn .15s ease; 268 }
269 @keyframes fadeIn { from { opacity: 0; transform: translateY(2px); } to { opacity: 1; transform: none; } } 270 .out-line .cc-logo { 271 height: 16px; width: 16px; border-radius: 3px; flex-shrink: 0; margin-top: 3px; 272 background: #d97706; 273 display: flex; align-items: center; justify-content: center; 274 font-size: 9px; font-weight: 900; color: #fff; letter-spacing: -.5px; 275 } 276 .out-line .out-text { color: var(--muted); } 277 .out-line .echo-cmd { color: var(--muted); opacity: .55; } 278 279 /* company logos */ 280 .intern-logos { 281 display: flex; flex-wrap: wrap; gap: 10px; align-items: center; 282 padding: 12px 18px 14px; 283 } 284 .intern-logos .co { 285 display: flex; align-items: center; gap: 6px; 286 font-size: 11px; color: var(--muted); 287 border: 1px solid var(--border); border-radius: 7px; 288 padding: 4px 10px 4px 6px; 289 } 290 .intern-logos .co img { 291 height: 18px; width: auto; object-fit: contain; 292 filter: grayscale(30%); opacity: .85; 293 } 294 html[data-theme="dark"] .intern-logos .co img { filter: grayscale(20%) brightness(1.1); } 295 296 .pub-meta { flex: 1; min-width: 0; } 297 .pub-title { font-size: 13px; font-weight: 600; color: var(--text); line-height: 1.45; margin-bottom: 3px; } 298 .pub-title a { color: var(--text); } 299 .pub-title a:hover { color: var(--accent); text-decoration: none; } 300 .pub-authors { font-size: 11px; color: var(--muted); margin-bottom: 4px; } 301 .pub-authors .me { color: var(--text); text-decoration: underline; } 302 .pub-venue { 303 font-size: 10px; font-weight: 700; letter-spacing: .04em; 304 display: inline-block; padding: 1px 7px; border-radius: 5px; 305 background: color-mix(in oklab, var(--accent) 12%, transparent); 306 color: var(--accent); margin-bottom: 5px; 307 } 308 .pub-venue.neurips { background: color-mix(in oklab, var(--purple) 12%, transparent); color: var(--purple); } 309 .pub-venue.iclr { background: color-mix(in oklab, var(--green) 12%, transparent); color: var(--green); } 310 .pub-venue.emnlp { background: color-mix(in oklab, var(--yellow) 12%, transparent); color: var(--yellow); } 311 .pub-venue.workshop{ background: color-mix(in oklab, var(--muted) 20%, transparent); color: var(--muted); } 312 313 .pub-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 6px; } 314 .ptag { 315 font-size: 10px; font-weight: 500; padding: 1px 6px; border-radius: 4px; 316 border: 1px solid var(--border); background: transparent; color: var(--muted); 317 } 318 319 .pub-links { font-size: 12px; } 320 .pub-links a { color: var(--muted); margin-right: 10px; } 321 322 /* highlight */ 323 .pub-item.highlight { 324 background: color-mix(in oklab, var(--yellow) 5%, var(--surface)); 325 border-left: 3px solid var(--yellow); 326 border-radius: 6px; 327 padding: 10px 10px 10px 12px; 328 margin-left: -15px; 329 } 330 .highlight-badge { 331 font-size: 10px; font-weight: 600; letter-spacing: .04em; 332 color: var(--yellow); margin-left: 8px; 333 opacity: .85; 334 } 335 .pub-links a:hover { color: var(--accent); text-decoration: none; } 336 337 /* ââ reviewer grid âââââââââââââââââââââââââââââââââ */ 338 .review-grid { 339 display: flex; 340 gap: 8px; 341 flex-wrap: wrap; 342 padding: 14px 18px; 343 } 344 .review-grid .rv { 345 font-size: 11px; 346 padding: 3px 10px; 347 border: 1px solid var(--border); 348 border-radius: 6px; 349 color: var(--muted); 350 } 351 352 /* ââ cat modal âââââââââââââââââââââââââââââââââââââ */ 353 .cat-modal { 354 position: fixed; inset: 0; 355 background: rgba(0,0,0,.65); 356 backdrop-filter: blur(4px); 357 display: flex; align-items: center; justify-content: center; 358 z-index: 100; 359 opacity: 0; pointer-events: none; transition: opacity .2s; 360 } 361 .cat-modal.open { opacity: 1; pointer-events: all; } 362 .cat-window { 363 background: var(--surface); 364 border: 1px solid var(--border); 365 border-radius: var(--radius); 366 width: min(400px, 90vw); 367 overflow: hidden; 368 transform: scale(.95); transition: transform .2s; 369 } 370 .cat-modal.open .cat-window { transform: scale(1); } 371 .cat-term-body { padding: 10px 16px 4px; font-size: 12px; color: var(--muted); } 372 .cat-term-body .typed { color: var(--text); } 373 .cat-img-wrap { 374 padding: 0 16px; 375 overflow: hidden; 376 max-height: 0; transition: max-height .4s ease, padding .3s ease; 377 position: relative; 378 } 379 .cat-img-wrap.show { max-height: 340px; padding: 0 16px 14px; } 380 .cat-img-wrap img { 381 width: 100%; border-radius: 8px; border: 1px solid var(--border); display: block; 382 transition: opacity .25s ease; 383 } 384 .cat-img-wrap img.fade { opacity: 0; } 385 .cat-footer { 386 padding: 8px 16px 12px; 387 font-size: 11px; color: var(--muted); 388 display: flex; justify-content: space-between; align-items: center; 389 gap: 8px; 390 } 391 .cat-nav { display: flex; align-items: center; gap: 6px; } 392 .cat-nav-btn { 393 background: none; border: 1px solid var(--border); color: var(--muted); 394 font-family: var(--font); font-size: 12px; padding: 2px 8px; 395 border-radius: 5px; cursor: pointer; line-height: 1.4; 396 } 397 .cat-nav-btn:hover { border-color: var(--accent); color: var(--accent); } 398 .cat-nav-btn:disabled { opacity: .3; cursor: default; } 399 .cat-counter { font-size: 11px; color: var(--muted); min-width: 32px; text-align: center; } 400 .cat-close { 401 background: none; border: 1px solid var(--border); color: var(--muted); 402 font-family: var(--font); font-size: 11px; padding: 3px 10px; 403 border-radius: 5px; cursor: pointer; 404 } 405 .cat-close:hover { border-color: var(--red); color: var(--red); } 406 407 /* ââ aim trainer game ââââââââââââââââââââââââââââââ */ 408 .game-modal { 409 position: fixed; inset: 0; 410 background: rgba(0,0,0,.75); 411 backdrop-filter: blur(6px); 412 display: flex; align-items: center; justify-content: center; 413 z-index: 200; 414 opacity: 0; pointer-events: none; transition: opacity .2s; 415 } 416 .game-modal.open { opacity: 1; pointer-events: all; } 417 .game-window { 418 background: var(--surface); 419 border: 1px solid var(--border); 420 border-radius: var(--radius); 421 overflow: hidden; 422 transform: scale(.95); transition: transform .2s; 423 display: flex; flex-direction: column; 424 width: min(900px, 96vw); 425 } 426 #gameCanvas { width: 100%; height: auto; } 427 .game-modal.open .game-window { transform: scale(1); } 428 #gameCanvas { 429 display: block;
430 cursor: none; 431 background: #0a0e14; 432 } 433 .game-footer { 434 padding: 8px 16px; 435 font-size: 11px; color: var(--muted); 436 display: flex; justify-content: space-between; align-items: center; 437 border-top: 1px solid var(--border); 438 } 439 .game-close { 440 background: none; border: 1px solid var(--border); color: var(--muted); 441 font-family: var(--font); font-size: 11px; padding: 3px 10px; 442 border-radius: 5px; cursor: pointer; 443 } 444 .game-close:hover { border-color: var(--red); color: var(--red); } 445 446 /* ââ footer ââââââââââââââââââââââââââââââââââââââââ */ 447 footer { 448 margin-top: 48px; padding-top: 16px; 449 border-top: 1px solid var(--border); 450 font-size: 11px; color: var(--muted); 451 display: flex; justify-content: space-between; 452 } 453 454 @media (max-width: 520px) { 455 .hero { grid-template-columns: 1fr; } 456 .portrait-wrap { width: 88px; height: 88px; } 457 } 458 </style> 459</head> 460<body> 461<div class="page"> 462 463 <!-- top bar --> 464 <div class="topbar"> 465 <div class="path"> 466 <span class="slash">~/</span><span class="seg">haotian-xue</span> 467 </div> 468 <div class="top-right"> 469 <button class="icon-btn" id="themeBtn">light</button> 470 </div> 471 </div> 472 473 <!-- ââ HERO âââââââââââââââââââââââââââââââââââââââââââ --> 474 <div class="hero"> 475 <div style="position:relative; width:148px; height:148px; flex-shrink:0; z-index:1; overflow:visible"> 476 <div class="portrait-wrap" id="portrait" title="click to meet my cat"> 477 <img class="main" src="static/image/photos/haotian_2026.png" alt="Haotian Xue" /> 478 <img class="cat" src="static/image/photos/pudding/pudding1.png" alt="Haotian's cat" /> 479 <div class="cat-badge" id="catBadge">$ cat cat.jpg</div> 480 </div> 481 <div class="cat-hint" id="catHint"> 482 <span class="cat-hint-arrow">â</span> 483 <span class="cat-hint-label">meet my cat ð±</span> 484 </div> 485 </div> 486 <div class="bio"> 487 <h1>Haotian Xue</h1> 488 <div class="pron">/haÊtiËæn Êweɪ/ · èæå¤©</div> 489 <p class="tagline"> 490 4th-year PhD · Machine Learning<br> 491 <a href="https://ml.gatech.edu/">Georgia Tech</a> · 492 advised by <a href="https://yongxin.ae.gatech.edu/">Yongxin Chen</a> 493 </p> 494 <div class="links-row"> 495 <a href="https://scholar.google.com/citations?hl=en&user=wnweG9UAAAAJ"> 496 <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><path d="M12 24a7 7 0 1 1 0-14 7 7 0 0 1 0 14zm0-24L0 9.5h4.5C5 14.7 8.1 19 12 19c.9 0 1.8-.2 2.5-.5V24l3.5-3.5V19c2.7-2 4.5-5.1 4.5-8.5H24z"/></svg> 497 Scholar 498 </a> 499 <a href="https://github.com/xavihart"> 500 <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.37 0 0 5.37 0 12c0 5.3 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577v-2.165c-3.338.726-4.042-1.61-4.042-1.61-.546-1.387-1.333-1.756-1.333-1.756-1.09-.745.083-.73.083-.73 1.205.085 1.84 1.237 1.84 1.237 1.07 1.835 2.807 1.305 3.492.998.108-.776.42-1.305.763-1.605-2.665-.3-5.467-1.332-5.467-5.93 0-1.31.468-2.38 1.235-3.22-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.3 1.23A11.5 11.5 0 0 1 12 6.8a11.5 11.5 0 0 1 3.007.404c2.29-1.552 3.297-1.23 3.297-1.23.653 1.652.242 2.873.12 3.176.77.84 1.232 1.91 1.232 3.22 0 4.61-2.807 5.625-5.48 5.92.43.37.823 1.102.823 2.222v3.293c0 .322.216.694.825.577C20.565 21.796 24 17.298 24 12 24 5.37 18.627 0 12 0z"/></svg> 501 GitHub 502 </a> 503 <a href="https://twitter.com/Haotianxue_GT"> 504 <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg> 505 X 506 </a> 507 <a href="static/docs/cv.pdf"> 508 <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14,2 14,8 20,8"/></svg> 509 CV 510 </a> 511 </div> 512 <div class="email">htxue.ai <span>[at]</span> gatech <span>[dot]</span> edu</div> 513 </div> 514 </div> 515 516 <!-- ââ JOB MARKET BANNER ââââââââââââââââââââââââââââââââââ --> 517 <div style=" 518 border-left: 3px solid var(--red); 519 background: color-mix(in oklab, var(--red) 7%, var(--surface)); 520 border-radius: 6px; 521 padding: 10px 16px; 522 margin-bottom: 20px; 523 font-size: 13px; 524 line-height: 1.6; 525 "> 526 I will be on the <strong>2027 job market</strong>. Open to 527 <span style="color:var(--text)">
527Research Scientist / Research Engineer / MTS</span> 528 positions related to <span style="color:var(--text)">Generative AI</span> and 529 <span style="color:var(--text)">Multimodal LLMs</span>. 530 Feel free to reach out â <a href="mailto:[email protected]">[email protected]</a> 531 </div> 532 533 <!-- ââ ABOUT âââââââââââââââââââââââââââââââââââââââââââ --> 534 <div class="sec-label">about</div> 535 <div class="term" style="margin-bottom:32px"> 536 <div class="term-bar"> 537 <div class="term-dots"><span class="r"></span><span class="y"></span><span class="g"></span></div> 538 <div class="term-title">haotian@gt â zsh</div> 539 </div> 540 <div class="term-body" style="padding-bottom:8px"> 541 <div><span class="prompt">â</span> <span class="cmd">cat research.json</span></div> 542 <div style="margin-top:4px">{</div> 543 <div style="padding-left:20px"><span class="key">"focus"</span><span class="val">: [</span> 544 <span class="ptag diffusion" style="margin:0 3px">video diffusion</span> 545 <span class="ptag diffusion" style="margin:0 3px">world models</span> 546 <span class="ptag robotics" style="margin:0 3px">embodied AI</span> 547 <span class="ptag safety" style="margin:0 3px">safe generative AI</span> 548 <span class="val"> ],</span></div> 549 <div style="padding-left:20px"><span class="key">"edu"</span><span class="val">: </span><span class="val">"B.E. CS (Zhiyuan Honors) · SJTU 2022"</span></div> 550 <div>}</div> 551 <div style="margin-top:10px"><span class="prompt">â</span> <span class="cmd">cat interests.md</span></div> 552 <div style="margin-top:4px; padding-left:4px; line-height:2; font-family: system-ui, -apple-system, sans-serif; font-size: 13px;"> 553 <div><span class="val" style="font-family:var(--font)">â¸</span> Video diffusion and world models <a href="https://xavihart.github.io/mogan/">MoGAN</a><span class="val">[ECCV'26]</span> <a href="https://xavihart.github.io/ACWM-Phys">ACWM-Phys</a><span class="val">[arXiv]</span></div> 554 <div><span class="val" style="font-family:var(--font)">â¸</span> Multi-modal Large Language Models <a href="https://github.com/xavihart/PIO">PIO-Bench</a><span class="val">[TMLR'26]</span> <a href="https://lamawmouk.github.io/SGMRI-VQA">SGMRI-VQA</a><span class="val">[arXiv]</span></div> 555 <div><span class="val" style="font-family:var(--font)">â¸</span> Embodied AI <a href="https://quest-model.github.io/">QueST</a><span class="val">[NeurIPS'24]</span></div> 556 <div><span class="val" style="font-family:var(--font)">â¸</span> Safe generative AI <a href="https://github.com/xavihart/Diff-PGD">Diff-PGD</a><span class="val">[NeurIPS'23]</span> <a href="https://github.com/xavihart/Diff-Protect">SDS-Attack</a><span class="val">[ICLR'24]</span> <a href="https://github.com/xavihart/PDM-Pure">PDM-Pure</a><span class="val">[NeurIPSW]</span> <a href="https://sites.google.com/view/diffusion-policy-attacker">DP-Attacker</a><span class="val">[NeurIPS'24]</span> <a href="https://immune2v.github.io/">Immune2V</a><span class="val">[arXiv]</span></div> 557 </div> 558 <div style="margin-top:10px"><span class="prompt">â</span> <span class="cmd">ls internships/</span></div> 559 </div> 560 <!-- company logos --> 561 <div class="intern-logos"> 562 <div class="co"> 563 <img src="static/image/logos/meta.jpg" alt="Meta" /> 564 Meta MSL · 2026 565 </div> 566 <div class="co"> 567 <img src="static/image/logos/Adobe_Firefly_Logo.svg.png" alt="Adobe" /> 568 Adobe Firefly · 2025 569 </div> 570 <div class="co"> 571 <img src="static/image/logos/235_Nvidia_logo-512.webp" alt="NVIDIA" /> 572 NVIDIA DIR · 2024 573 </div> 574 <div class="co"> 575 <img src="static/image/logos/microsoft.png" alt="MSRA" /> 576 MSRA · 2021 577 </div> 578 <div class="co"> 579 <img src="static/image/logos/mit.png" alt="MIT" /> 580 MIT CSAIL · 2021 581 </div> 582 </div> 583 <!-- interactive input --> 584 <div class="term-output-area" id="termOutput"></div> 585 <div class="term-input-row">
586 <span class="prompt">â</span> 587 <input class="term-input" id="termInput" placeholder="type a commandâ¦" autocomplete="off" spellcheck="false" /> 588 </div> 589 </div> 590 591 <!-- ââ NEWS ââââââââââââââââââââââââââââââââââââââââââââ --> 592 <div class="sec-label">news</div> 593 <div class="term" style="margin-bottom:32px"> 594 <div class="term-bar"> 595 <div class="term-dots"><span class="r"></span><span class="y"></span><span class="g"></span></div> 596 <div class="term-title">tail -f news.log</div> 597 </div> 598 <ul class="news-log" id="newsList"> 599 <li><span class="ts">2026-06</span><span class="msg"><a href="https://xavihart.github.io/mogan/">MoGAN</a> accepted to <strong>ECCV 2026</strong>!</span></li> 600 <li><span class="ts">2026-05</span><span class="msg">We propose <a href="https://xavihart.github.io/ACWM-Phys">ACWM-Phys</a>, a physics-rich benchmark for action-conditioned video world models.</span></li> 601 <li><span class="ts">2026-04</span><span class="msg"><a href="https://github.com/xavihart/PIO">PIO-Bench</a> accepted to <strong>TMLR 2026</strong>!</span></li> 602 <li><span class="ts">2026-04</span><span class="msg">We propose <a href="https://immune2v.github.io/">Immune2V</a>, a protective watermark for Image-to-Video.</span></li> 603 <li><span class="ts">2026-04</span><span class="msg">I will be at <strong>Meta MSL</strong> working on World Model.</span></li> 604 <li><span class="ts">2026-01</span><span class="msg">LapFlow accepted to <strong>ICLR 2026</strong>. Laplacian multi-scale flow matching for generation.</span></li> 605 <li><span class="ts">2025-10</span><span class="msg">We propose <a href="https://xavihart.github.io/mogan/">MoGAN</a>, post-training for motion quality in few-step video diffusion.</span></li> 606 <li><span class="ts">2025-09</span><span class="msg">We propose <a href="https://github.com/xavihart/PIO">PIO-Bench</a>, a visual-grounding-centric benchmark for embodied VLM reasoning.</span></li> 607 <li><span class="ts">2025-04</span><span class="msg">Joining <strong>Adobe Firefly</strong> (Summer+Fall) for post-training on video diffusion.</span></li> 608 <li><span class="ts">2024-10</span><span class="msg"><strong>NeurIPS 2024 Scholar Award</strong> â see you in Vancouver!</span></li> 609 <li><span class="ts">2024-09</span><span class="msg">Three papers @ NeurIPS 2024: <a href="https://sites.google.com/view/diffusion-policy-attacker">DP-Attacker</a>, <a href="https://sbyebss.github.io/refdrop/">RefDrop</a>, <a href="https://quest-model.github.io/">QueST</a>.</span></li> 610 <li><span class="ts">2024-05</span><span class="msg">Summer intern at <a href="https://research.nvidia.com/labs/dir/">NVIDIA DIR Group</a>.</span></li> 611 <li><span class="ts">2024-03</span><span class="msg">ICLR 2024 Travel Award.</span></li> 612 <li><span class="ts">2024-01</span><span class="msg"><a href="https://github.com/xavihart/Diff-Protect">SDS-Attack</a> accepted to <strong>ICLR 2024</strong>.</span></li> 613 <li><span class="ts">2023-10</span><span class="msg">NeurIPS 2023 Scholar Award; invited reviewer for TPAMI.</span></li> 614 <li><span class="ts">2023-09</span><span class="msg"><a href="https://github.com/xavihart/Diff-PGD">Diff-PGD</a> and <a href="https://github.com/xavihart/3D-IntPhys">3D-IntPhys</a> accepted to <strong>NeurIPS 2023</strong>.</span></li> 615 <li><span class="ts">2022-12</span><span class="msg">Top Reviewer · NeurIPS 2022.</span></li> 616 <li><span class="ts">2022-10</span><span class="msg"><a href="https://aclanthology.org/2022.findings-emnlp.173/">Distance-Transformer</a> accepted to <strong>EMNLP 2022</strong> Findings.</span></li> 617 <li><span class="ts">2022-08</span><span class="msg">Started PhD at ML@GT.</span></li> 618 </ul> 619 </div> 620 621 <!-- ââ PUBLICATIONS ââââââââââââââââââââââââââââââââââââ --> 622 <div class="sec-label">selected publications</div> 623 <div class="term" style="margin-bottom:32px"> 624 <div class="term-bar"> 625 <div class="term-dots"><span class="r"></span><span class="y"></span><span class="g"></span></div> 626 <div class="term-title">publications.bib</div> 627 </div> 628 <div style="padding: 4px 18px 0"> 629 <ul class="pub-list"> 630 631 <li> 632 <div class="pub-item highlight"> 633 <div class="pub-meta"> 634 <div class="pub-title"><a href="https://xavihart.github.io/ACWM-Phys">ACWM-Phys: Investigating Generalized Physical Interaction in Action-Conditioned Video World Models</a></div> 635 <div class="pub-authors"><span class="me">
635Haotian Xue</span>, Yipu Chen*, Liqian Ma*, Zelin Zhao, Lama Moukheiber, Yuchen Zhu, Yongxin Chen</div> 636 <div><span class="pub-venue">arXiv 2026</span></div> 637 <div class="pub-tags"> 638 <span class="ptag diffusion">Diffusion</span> 639 <span class="ptag video">Video</span> 640 <span class="ptag robotics">World Model</span> 641 <span class="ptag robotics">Benchmark</span> 642 </div> 643 <div class="pub-links"> 644 <a href="https://arxiv.org/abs/2605.08567">arXiv</a> 645 <a href="https://xavihart.github.io/ACWM-Phys">project</a> 646 <a href="https://github.com/xavihart/ACWM-Phys-dev">code</a> 647 </div> 648 </div> 649 </div> 650 </li> 651 652 <li> 653 <div class="pub-item"> 654 <div class="pub-meta"> 655 <div class="pub-title">Immune2V: Image Immunization Against Dual-Stream Image-to-Video Generation</div> 656 <div class="pub-authors">Zeqian Long*, Ozgur Kara*, <span class="me">Haotian Xue*</span>, Yongxin Chen, James M. Rehg</div> 657 <div><span class="pub-venue">arXiv 2026</span></div> 658 <div class="pub-tags"> 659 <span class="ptag safety">Safety</span> 660 <span class="ptag diffusion">Diffusion</span> 661 <span class="ptag video">Video</span> 662 </div> 663 <div class="pub-links"><a href="https://arxiv.org/abs/2604.10837">arXiv</a> <a href="https://immune2v.github.io/">project</a> <a href="https://github.com/Zeqian-Long/Immune2V">code</a></div> 664 </div> 665 </div> 666 </li> 667 668 <li> 669 <div class="pub-item"> 670 <div class="pub-meta"> 671 <div class="pub-title"><a href="https://lamawmouk.github.io/SGMRI-VQA">Beyond a Single Frame: Multi-Frame Spatially Grounded Reasoning Across Volumetric MRI</a></div> 672 <div class="pub-authors">Lama Moukheiber, Caleb M. Yeung, <span class="me">Haotian Xue</span>, Alec Helbling, Zelin Zhao, Yongxin Chen</div> 673 <div><span class="pub-venue">arXiv 2026</span></div> 674 <div class="pub-tags"> 675 <span class="ptag vlm">VLM</span> 676 <span class="ptag vision">Vision</span> 677 <span class="ptag td">3D</span> 678 </div> 679 <div class="pub-links"><a href="https://arxiv.org/abs/2604.15808">arXiv</a> <a href="https://lamawmouk.github.io/SGMRI-VQA">project</a> <a href="https://github.com/lamawmouk/SGMRI-VQA">code</a></div> 680 </div> 681 </div> 682 </li> 683 684 <li> 685 <div class="pub-item highlight"> 686 <div class="pub-meta"> 687 <div class="pub-title"><a href="https://xavihart.github.io/mogan/">MoGAN: Improving Motion Quality in Video Diffusion via Few-Step Motion Adversarial Post-Training</a></div> 688 <div class="pub-authors"><span class="me">Haotian Xue</span>, Qi Chen, Zhonghao Wang, Xun Huang, Eli Shechtman, Jinrong Xie, Yongxin Chen</div> 689 <div><span class="pub-venue iclr">ECCV 2026</span></div> 690 <div class="pub-tags"> 691 <span class="ptag diffusion">Diffusion</span> 692 <span class="ptag video">Video</span> 693 </div> 694 <div class="pub-links"> 695 <a href="https://arxiv.org/abs/2511.21592">arXiv</a> 696 <a href="https://xavihart.github.io/mogan/">project</a> 697 </div> 698 </div> 699 </div> 700 </li> 701 702 <li> 703 <div class="pub-item"> 704 <div class="pub-meta"> 705 <div class="pub-title">Laplacian Multi-scale Flow Matching for Generative Modeling</div> 706 <div class="pub-authors">Zelin Zhao, Petr Molodyk, <span class="me">Haotian Xue</span>, Yongxin Chen</div> 707 <div><span class="pub-venue iclr">ICLR 2026</span></div> 708 <div class="pub-tags"> 709 <span class="ptag diffusion">Diffusion</span> 710 <span class="ptag vision">Vision</span> 711 </div> 712 <div class="pub-links"> 713 <a href="https://arxiv.org/abs/2511.21592">arXiv</a> 714 </div> 715 </div> 716 </div> 717 </li> 718 719 <li> 720 <div class="pub-item"> 721 <div class="pub-meta"> 722 <div class="pub-title"><a href="https://github.com/xavihart/PIO">Point-It-Out: Benchmarking Embodied Reasoning for VLMs in Multi-Stage Visual Grounding</a></div> 723 <div class="pub-authors"><span class="me">
723Haotian Xue</span>, Yunhao Ge, Yu Zeng, Max Li, Ming-Yu Liu, Yongxin Chen, Jiaojiao Fan</div> 724 <div><span class="pub-venue iclr">TMLR 2026</span></div> 725 <div class="pub-tags"> 726 <span class="ptag vlm">VLM</span> 727 <span class="ptag robotics">Robotics</span> 728 </div> 729 <div class="pub-links"> 730 <a href="https://arxiv.org/abs/2509.25794">arXiv</a> 731 <a href="https://github.com/xavihart/PIO/">code</a> 732 </div> 733 </div> 734 </div> 735 </li> 736 737 <li> 738 <div class="pub-item"> 739 <div class="pub-meta"> 740 <div class="pub-title"><a href="https://sbyebss.github.io/refdrop/">RefDrop: Controllable Consistency in Image or Video Generation via Reference Feature Guidance</a></div> 741 <div class="pub-authors">Jiaojiao Fan, <span class="me">Haotian Xue</span>, Qinsheng Zhang, Yongxin Chen</div> 742 <div><span class="pub-venue neurips">NeurIPS 2024</span></div> 743 <div class="pub-tags"> 744 <span class="ptag diffusion">Diffusion</span> 745 <span class="ptag vision">Vision</span> 746 </div> 747 <div class="pub-links"> 748 <a href="https://arxiv.org/abs/2405.17661">arXiv</a> 749 <a href="https://sbyebss.github.io/refdrop/">project</a> 750 </div> 751 </div> 752 </div> 753 </li> 754 755 <li> 756 <div class="pub-item"> 757 <div class="pub-meta"> 758 <div class="pub-title"><a href="https://quest-model.github.io/">QueST: Self-Supervised Skill Abstractions for Learning Continuous Control</a></div> 759 <div class="pub-authors">Arthava Mete, <span class="me">Haotian Xue</span>, Albert Wilcox, Yongxin Chen, Animesh Garg</div> 760 <div><span class="pub-venue neurips">NeurIPS 2024</span></div> 761 <div class="pub-tags"> 762 <span class="ptag robotics">Robotics</span> 763 <span class="ptag vision">Vision</span> 764 </div> 765 <div class="pub-links"> 766 <a href="https://arxiv.org/abs/2407.15840">arXiv</a> 767 <a href="https://quest-model.github.io/">project</a> 768 <a href="https://github.com/pairlab/QueST">code</a> 769 </div> 770 </div> 771 </div> 772 </li> 773 774 <li> 775 <div class="pub-item"> 776 <div class="pub-meta"> 777 <div class="pub-title"><a href="https://sites.google.com/view/diffusion-policy-attacker">Diffusion Policy Attacker: Crafting Adversarial Attacks for Diffusion-based Policies</a></div> 778 <div class="pub-authors">Yipu Chen*, <span class="me">Haotian Xue*</span>, Yongxin Chen</div> 779 <div><span class="pub-venue neurips">NeurIPS 2024</span></div> 780 <div class="pub-tags"> 781 <span class="ptag diffusion">Diffusion</span> 782 <span class="ptag safety">Safety</span> 783 </div> 784 <div class="pub-links"> 785 <a href="https://arxiv.org/abs/2405.19424">arXiv</a> 786 <a href="https://sites.google.com/view/diffusion-policy-attacker/">project</a> 787 </div> 788 </div> 789 </div> 790 </li> 791 792 <li> 793 <div class="pub-item"> 794 <div class="pub-meta"> 795 <div class="pub-title"><a href="https://github.com/xavihart/Diff-Protect">Towards More Effective Protection Against Diffusion-Based Mimicry with Score Distillation</a></div> 796 <div class="pub-authors"><span class="me">Haotian Xue</span>, Chumeng Liang*, Xiaoyu Wu*, Yongxin Chen</div> 797 <div><span class="pub-venue iclr">ICLR 2024</span></div> 798 <div class="pub-tags"> 799 <span class="ptag diffusion">Diffusion</span> 800 <span class="ptag safety">Safety</span> 801 </div> 802 <div class="pub-links"> 803 <a href="https://arxiv.org/abs/2311.12832">arXiv</a> 804 <a href="https://github.com/xavihart/Diff-Protect">code</a> 805 <a href="https://iclr.cc/media/iclr-2024/Slides/18759.pdf">poster</a> 806 </div> 807 </div> 808 </div> 809 </li> 810 811 <li> 812 <div class="pub-item"> 813 <div class="pub-meta"> 814 <div class="pub-title"><a href="https://github.com/xavihart/PDM-Pure">Pixel is a Barrier: Diffusion Models Are More Adversarially Robust Than We Think</a></div> 815 <div class="pub-authors"><span class="me">
815Haotian Xue</span>, Yongxin Chen</div> 816 <div><span class="pub-venue workshop">NeurIPSW: SafeGenAI 2024</span></div> 817 <div class="pub-tags"> 818 <span class="ptag diffusion">Diffusion</span> 819 <span class="ptag safety">Safety</span> 820 </div> 821 <div class="pub-links"> 822 <a href="https://arxiv.org/abs/2404.13320">arXiv</a> 823 <a href="https://github.com/xavihart/PDM-Pure">code</a> 824 </div> 825 </div> 826 </div> 827 </li> 828 829 <li> 830 <div class="pub-item"> 831 <div class="pub-meta"> 832 <div class="pub-title"><a href="https://github.com/xavihart/Diff-PGD">Diffusion-Based Adversarial Sample Generation for Improved Stealthiness and Controllability</a></div> 833 <div class="pub-authors"><span class="me">Haotian Xue</span>, Alexandre Araujo, Bin Hu, Yongxin Chen</div> 834 <div><span class="pub-venue neurips">NeurIPS 2023</span></div> 835 <div class="pub-tags"> 836 <span class="ptag diffusion">Diffusion</span> 837 <span class="ptag safety">Safety</span> 838 </div> 839 <div class="pub-links"> 840 <a href="https://arxiv.org/abs/2305.16494">arXiv</a> 841 <a href="https://github.com/xavihart/Diff-PGD">code</a> 842 <a href="static/docs/poster_diffpgd.pdf">poster</a> 843 </div> 844 </div> 845 </div> 846 </li> 847 848 <li> 849 <div class="pub-item"> 850 <div class="pub-meta"> 851 <div class="pub-title"><a href="https://arxiv.org/abs/2304.11470">3D-IntPhys: Towards More Generalized 3D-grounded Visual Intuitive Physics</a></div> 852 <div class="pub-authors"><span class="me">Haotian Xue</span>, Antonio Torralba, Joshua B. Tenenbaum, Daniel L. K. Yamins, Yunzhu Li, Hsiao-Yu Tung</div> 853 <div><span class="pub-venue neurips">NeurIPS 2023</span></div> 854 <div class="pub-tags"> 855 <span class="ptag vision">Vision</span> 856 <span class="ptag td">3D</span> 857 </div> 858 <div class="pub-links"> 859 <a href="https://arxiv.org/abs/2304.11470">arXiv</a> 860 <a href="static/docs/poster_3dintphys.pdf">poster</a> 861 </div> 862 </div> 863 </div> 864 </li> 865 866 </ul> 867 <div style="padding: 10px 0 14px; font-size: 11px; color: var(--muted);"> 868 â <a href="https://scholar.google.com/citations?hl=en&user=wnweG9UAAAAJ">full list on Google Scholar</a> 869 </div> 870 </div> 871 </div> 872 873 <!-- ââ REVIEWER ââââââââââââââââââââââââââââââââââââââââ --> 874 <div class="sec-label">service</div> 875 <div class="term" style="margin-bottom:0"> 876 <div class="term-bar"> 877 <div class="term-dots"><span class="r"></span><span class="y"></span><span class="g"></span></div> 878 <div class="term-title">reviewer</div> 879 </div> 880 <div class="review-grid"> 881 <span class="rv">NeurIPS</span> 882 <span class="rv">ICLR</span> 883 <span class="rv">ICML</span> 884 <span class="rv">CVPR</span> 885 <span class="rv">AISTATS</span> 886 <span class="rv">AAAI</span> 887 <span class="rv">TPAMI</span> 888 <span class="rv">TCSVT</span> 889 </div> 890 </div> 891 892 <!-- ââ MISC âââââââââââââââââââââââââââââââââââââââââââ --> 893 <div class="sec-label" style="margin-top:32px">misc</div> 894 <div class="term" style="margin-bottom:0"> 895 <div class="term-bar"> 896 <div class="term-dots"><span class="r"></span><span class="y"></span><span class="g"></span></div> 897 <div class="term-title">misc.txt</div> 898 </div> 899 <div class="term-body" style="line-height:2.1"> 900 <div><span class="val">âï¸ travel</span> ð¨ð³ ðºð¸ ð¸ðª ð¦ð¹ ððº ð«ð· ð§ðª ð¨ð¦</div> 901 <div><span class="val">ð¹ piano & music</span></div> 902 <div><span class="val">â½ football (soccer)</span> · recently into ð basketball & ð¾ tennis</div> 903 <div><span class="val">
903ð± cat</span> Pudding <span style="color:var(--muted);font-size:11px">â click portrait to meet him</span></div> 904 </div> 905 </div> 906 907 <footer> 908 <span>© Haotian Xue · 2025</span> 909 </footer> 910</div> 911 912<!-- ââ CAT MODAL âââââââââââââââââââââââââââââââââââââââââââ --> 913<div class="cat-modal" id="catModal"> 914 <div class="cat-window"> 915 <div class="term-bar"> 916 <div class="term-dots"><span class="r"></span><span class="y"></span><span class="g"></span></div> 917 <div class="term-title">cat.sh</div> 918 </div> 919 <div class="cat-term-body"> 920 <span class="prompt">â</span> <span class="typed" id="typeTarget"></span><span id="typeCursor" style="color:var(--green)">â</span> 921 </div> 922 <div class="cat-img-wrap" id="catImgWrap"> 923 <img id="catImg" src="static/image/photos/pudding/pudding1.png" alt="Pudding" /> 924 </div> 925 <div class="cat-footer"> 926 <span id="catCaption" style="opacity:0;transition:opacity .4s .1s">ð± Pudding</span> 927 <div class="cat-nav"> 928 <button class="cat-nav-btn" id="catPrev">â</button> 929 <span class="cat-counter" id="catCounter">1 / 1</span> 930 <button class="cat-nav-btn" id="catNext">â</button> 931 </div> 932 <button class="cat-close" id="catClose">â close</button> 933 </div> 934 </div> 935</div> 936 937<!-- ââ GAME MODAL âââââââââââââââââââââââââââââââââââââââââââ --> 938<div class="game-modal" id="gameModal"> 939 <div class="game-window"> 940 <div class="term-bar"> 941 <div class="term-dots"><span class="r"></span><span class="y"></span><span class="g"></span></div> 942 <div class="term-title">aim_trainer.exe</div> 943 </div> 944 <canvas id="gameCanvas" width="900" height="560"></canvas> 945 <div class="game-footer"> 946 <span id="gameStatus">type <b>game</b> in the terminal to launch</span> 947 <button class="game-close" id="gameClose">â close</button> 948 </div> 949 </div> 950</div> 951
952<script> 953 // theme 954 const root = document.documentElement; 955 const btn = document.getElementById('themeBtn'); 956 const saved = localStorage.getItem('theme') || 'dark'; 957 root.setAttribute('data-theme', saved); 958 btn.textContent = saved === 'dark' ? 'light' : 'dark'; 959 btn.addEventListener('click', () => { 960 const next = root.getAttribute('data-theme') === 'dark' ? 'light' : 'dark'; 961 root.setAttribute('data-theme', next); 962 localStorage.setItem('theme', next); 963 btn.textContent = next === 'dark' ? 'light' : 'dark'; 964 }); 965 966 // portrait 967 const portrait = document.getElementById('portrait'); 968 portrait.addEventListener('mouseenter', () => portrait.classList.add('revealed')); 969 portrait.addEventListener('mouseleave', () => portrait.classList.remove('revealed')); 970 const catHint = document.getElementById('catHint'); 971 function dismissHint() { catHint.classList.add('hidden'); } 972 973 portrait.addEventListener('click', () => { dismissHint(); openCat(); }); 974 document.getElementById('catBadge').addEventListener('click', e => { e.stopPropagation(); dismissHint(); openCat(); }); 975 976 // cat modal 977 // ââ Add more photos by dropping files into static/image/photos/pudding/ 978 // ââ then add their filenames to this array: 979 const PUDDING_PHOTOS = [ 980 'static/image/photos/pudding/pudding1.png', 981 'static/image/photos/pudding/Weixin Image_20260414013420_35_17.png', 982 'static/image/photos/pudding/Weixin Image_20260414013423_36_17.png', 983 'static/image/photos/pudding/Weixin Image_20260414013435_37_17.jpg', 984 'static/image/photos/pudding/Weixin Image_20260414013440_38_17.jpg', 985 'static/image/photos/pudding/Weixin Image_20260414013445_39_17.jpg', 986 'static/image/photos/pudding/Weixin Image_20260414013453_40_17.jpg', 987 ]; 988 989 const modal = document.getElementById('catModal'); 990 const imgWrap = document.getElementById('catImgWrap'); 991 const catImg = document.getElementById('catImg'); 992 const typeTarget = document.getElementById('typeTarget'); 993 const typeCursor = document.getElementById('typeCursor'); 994 const caption = document.getElementById('catCaption'); 995 const closeBtn = document.getElementById('catClose'); 996 const prevBtn = document.getElementById('catPrev'); 997 const nextBtn = document.getElementById('catNext'); 998 const counter = document.getElementById('catCounter'); 999 let catIdx = 0; 1000 let typing; 1001 1002 function updateNav() { 1003 counter.textContent = `${catIdx + 1} / ${PUDDING_PHOTOS.length}`; 1004 prevBtn.disabled = catIdx === 0; 1005 nextBtn.disabled = catIdx === PUDDING_PHOTOS.length - 1; 1006 } 1007 1008 function showPhoto(idx) { 1009 catImg.classList.add('fade'); 1010 setTimeout(() => { 1011 catImg.src = PUDDING_PHOTOS[idx]; 1012 catImg.classList.remove('fade'); 1013 updateNav(); 1014 }, 200); 1015 } 1016 1017 prevBtn.addEventListener('click', () => { if (catIdx > 0) showPhoto(--catIdx); }); 1018 nextBtn.addEventListener('click', () => { if (catIdx < PUDDING_PHOTOS.length - 1) showPhoto(++catIdx); }); 1019 1020 function openCat() { 1021 catIdx = 0; 1022 catImg.src = PUDDING_PHOTOS[0]; 1023 updateNav(); 1024 modal.classList.add('open'); 1025 typeTarget.textContent = ''; 1026 imgWrap.classList.remove('show'); 1027 caption.style.opacity = '0'; 1028 typeCursor.style.display = 'inline'; 1029 let i = 0; 1030 clearInterval(typing); 1031 const cmd = `open pudding/${PUDDING_PHOTOS[0].split('/').pop()}`; 1032 typing = setInterval(() => { 1033 if (i < cmd.length) { typeTarget.textContent += cmd[i++]; } 1034 else { 1035 clearInterval(typing); 1036 typeCursor.style.display = 'none'; 1037 setTimeout(() => { 1038 imgWrap.classList.add('show'); 1039 caption.style.opacity = '1'; 1040 }, 180); 1041 } 1042 }, 55); 1043 } 1044 1045 function closeCat() { modal.classList.remove('open'); clearInterval(typing); } 1046 closeBtn.addEventListener('click', closeCat); 1047 modal.addEventListener('click', e => { if (e.target === modal) closeCat(); }); 1048 document.addEventListener('keydown', e => { if (e.key === 'Escape') closeCat(); }); 1049 1050 // ââ aim trainer game âââââââââââââââââââââââââââââââââââââ 1051 (function () { 1052 const gameModal = document.getElementById('gameModal'); 1053 const canvas = document.getElementById('gameCanvas'); 1054 const ctx = canvas.getContext('2d'); 1055 const statusEl = document.getElementById('gameStatus'); 1056 const closeBtn = document.getElementById('gameClose'); 1057 1058 const TOTAL = 20; 1059 const R_MIN = 18, R_MAX = 36; 1060 const PAD = 50; 1061 1062 let state = 'idle'; // idle | running | done 1063 let hardMode = false;
1064 let targets = [], cur = 0; 1065 let startTime, elapsed; 1066 let mouse = { x: canvas.width / 2, y: canvas.height / 2 }; 1067 let flash = null; 1068 let misses = 0; 1069 let raf; 1070 1071 function randTarget() { 1072 const r = hardMode 1073 ? R_MIN * 0.7 + Math.random() * (R_MAX * 0.7 - R_MIN * 0.7) 1074 : R_MIN + Math.random() * (R_MAX - R_MIN); 1075 const speed = hardMode ? 1.8 + Math.random() * 2.2 : 0; 1076 const angle = Math.random() * Math.PI * 2; 1077 return { 1078 x: PAD + r + Math.random() * (canvas.width - 2 * PAD - 2 * r), 1079 y: PAD + r + Math.random() * (canvas.height - 2 * PAD - 2 * r), 1080 r, 1081 vx: Math.cos(angle) * speed, 1082 vy: Math.sin(angle) * speed, 1083 born: performance.now(), 1084 }; 1085 } 1086 1087 function startGame() { 1088 targets = Array.from({ length: TOTAL }, randTarget); 1089 cur = 0; misses = 0; flash = null; 1090 startTime = performance.now(); 1091 state = 'running'; 1092 const mode = hardMode ? ' [HARD â moving targets]' : ' · click!'; 1093 statusEl.textContent = `target 1 / ${TOTAL}${mode}`; 1094 loop(); 1095 } 1096 1097 function drawCrosshair(x, y) { 1098 const len = 14, gap = 5; 1099 ctx.save(); 1100 ctx.strokeStyle = '#39d353'; 1101 ctx.lineWidth = 1.5; 1102 ctx.shadowColor = '#39d353'; 1103 ctx.shadowBlur = 6; 1104 // horizontal 1105 ctx.beginPath(); ctx.moveTo(x - len - gap, y); ctx.lineTo(x - gap, y); ctx.stroke(); 1106 ctx.beginPath(); ctx.moveTo(x + gap, y); ctx.lineTo(x + len + gap, y); ctx.stroke(); 1107 // vertical 1108 ctx.beginPath(); ctx.moveTo(x, y - len - gap); ctx.lineTo(x, y - gap); ctx.stroke(); 1109 ctx.beginPath(); ctx.moveTo(x, y + gap); ctx.lineTo(x, y + len + gap); ctx.stroke(); 1110 // center dot 1111 ctx.beginPath(); ctx.arc(x, y, 2, 0, Math.PI * 2); 1112 ctx.fillStyle = '#39d353'; ctx.shadowBlur = 4; ctx.fill(); 1113 ctx.restore(); 1114 } 1115 1116 function drawTarget(t) { 1117 const age = (performance.now() - t.born) / 1000; 1118 // pulse scale 1119 const scale = 1 + 0.06 * Math.sin(age * 6); 1120 const r = t.r * scale; 1121 1122 ctx.save(); 1123 // outer ring 1124 ctx.beginPath(); ctx.arc(t.x, t.y, r, 0, Math.PI * 2); 1125 ctx.strokeStyle = '#ff5f57'; ctx.lineWidth = 2; 1126 ctx.shadowColor = '#ff5f57'; ctx.shadowBlur = 12; ctx.stroke(); 1127 // inner fill 1128 ctx.beginPath(); ctx.arc(t.x, t.y, r * 0.55, 0, Math.PI * 2); 1129 ctx.fillStyle = 'rgba(255,95,87,0.18)'; ctx.shadowBlur = 0; ctx.fill(); 1130 // center dot 1131 ctx.beginPath(); ctx.arc(t.x, t.y, 4, 0, Math.PI * 2); 1132 ctx.fillStyle = '#ff5f57'; ctx.fill(); 1133 ctx.restore(); 1134 } 1135 1136 function drawHUD() { 1137 if (state === 'idle') return; 1138 const now = performance.now(); 1139 const secs = ((state === 'done' ? elapsed : now - startTime) / 1000).toFixed(2); 1140 ctx.save(); 1141 ctx.font = '12px monospace'; 1142 ctx.fillStyle = '#8b949e'; 1143 ctx.textAlign = 'left'; 1144 ctx.fillText(`time: ${secs}s`, 12, 20); 1145 ctx.textAlign = 'right'; 1146 ctx.fillText(`targets: ${Math.min(cur, TOTAL)} / ${TOTAL}`, canvas.width - 12, 20); 1147 if (misses > 0) { 1148 ctx.textAlign = 'left'; 1149 ctx.fillStyle = '#ff7b72'; 1150 ctx.fillText(`miss: ${misses}`, 12, 36); 1151 } 1152 ctx.restore(); 1153 } 1154 1155 function drawFlash() { 1156 if (!flash) return; 1157 const age = performance.now() - flash.t; 1158 if (age > 220) { flash = null; return; } 1159 const alpha = 1 - age / 220; 1160 const radius = 8 + age * 0.12; 1161 ctx.save(); 1162 ctx.beginPath(); ctx.arc(flash.x, flash.y, radius, 0, Math.PI * 2); 1163 ctx.strokeStyle = `rgba(57,211,83,${alpha})`; 1164 ctx.lineWidth = 1.5; ctx.stroke(); 1165 ctx.restore(); 1166 } 1167 1168 function drawIdle() { 1169 ctx.clearRect(0, 0, canvas.width, canvas.height); 1170 ctx.save(); 1171 ctx.fillStyle = '#30363d'; 1172 ctx.font = '13px monospace'; 1173 ctx.textAlign = 'center'; 1174 ctx.fillText('type game in the terminal below', canvas.width / 2, canvas.height / 2 - 10); 1175 ctx.fillStyle = '#39d353'; 1176 ctx.fillText('then click here to start', canvas.width / 2, canvas.height / 2 + 14);
1177 ctx.restore(); 1178 drawCrosshair(mouse.x, mouse.y); 1179 } 1180 1181 function drawDone() { 1182 const secs = (elapsed / 1000).toFixed(2); 1183 const avg = (elapsed / TOTAL / 1000).toFixed(2); 1184 ctx.clearRect(0, 0, canvas.width, canvas.height); 1185 ctx.save(); 1186 ctx.textAlign = 'center'; 1187 ctx.fillStyle = '#39d353'; 1188 ctx.font = 'bold 18px monospace'; 1189 ctx.fillText(`â completed${hardMode ? ' [HARD]' : ''}`, canvas.width / 2, canvas.height / 2 - 36); 1190 ctx.font = '13px monospace'; 1191 ctx.fillStyle = '#e6edf3'; 1192 ctx.fillText(`time: ${secs}s · avg per target: ${avg}s · misses: ${misses}`, canvas.width / 2, canvas.height / 2); 1193 ctx.fillStyle = '#8b949e'; 1194 ctx.fillText('click to play again', canvas.width / 2, canvas.height / 2 + 28); 1195 ctx.restore(); 1196 drawCrosshair(mouse.x, mouse.y); 1197 } 1198 1199 function moveTarget(t) { 1200 t.x += t.vx; t.y += t.vy; 1201 if (t.x - t.r < 0) { t.x = t.r; t.vx *= -1; } 1202 if (t.x + t.r > canvas.width) { t.x = canvas.width - t.r; t.vx *= -1; } 1203 if (t.y - t.r < 0) { t.y = t.r; t.vy *= -1; } 1204 if (t.y + t.r > canvas.height){ t.y = canvas.height - t.r; t.vy *= -1; } 1205 } 1206 1207 function loop() { 1208 if (state !== 'running') return; 1209 raf = requestAnimationFrame(loop); 1210 if (hardMode) moveTarget(targets[cur]); 1211 ctx.clearRect(0, 0, canvas.width, canvas.height); 1212 if (hardMode) { 1213 // faint trail hint 1214 ctx.save(); 1215 ctx.strokeStyle = 'rgba(255,95,87,0.12)'; 1216 ctx.lineWidth = 1; 1217 ctx.setLineDash([3, 6]); 1218 ctx.beginPath(); 1219 ctx.arc(targets[cur].x, targets[cur].y, targets[cur].r + 8, 0, Math.PI * 2); 1220 ctx.stroke(); 1221 ctx.restore(); 1222 } 1223 drawTarget(targets[cur]); 1224 drawFlash(); 1225 drawHUD(); 1226 drawCrosshair(mouse.x, mouse.y); 1227 } 1228 1229 canvas.addEventListener('mousemove', e => { 1230 const rect = canvas.getBoundingClientRect(); 1231 mouse.x = e.clientX - rect.left; 1232 mouse.y = e.clientY - rect.top; 1233 if (state === 'idle') drawIdle(); 1234 }); 1235 1236 canvas.addEventListener('click', e => { 1237 const rect = canvas.getBoundingClientRect(); 1238 const mx = e.clientX - rect.left; 1239 const my = e.clientY - rect.top; 1240 1241 if (state === 'idle' || state === 'done') { startGame(); return; } 1242 if (state !== 'running') return; 1243 1244 const t = targets[cur]; 1245 const dist = Math.hypot(mx - t.x, my - t.y); 1246 if (dist <= t.r) { 1247 flash = { x: t.x, y: t.y, t: performance.now() }; 1248 cur++; 1249 if (cur >= TOTAL) { 1250 elapsed = performance.now() - startTime; 1251 state = 'done'; 1252 cancelAnimationFrame(raf); 1253 statusEl.textContent = `done! ${(elapsed/1000).toFixed(2)}s for ${TOTAL} targets · click canvas to retry`; 1254 drawDone(); 1255 } else { 1256 statusEl.textContent = `target ${cur + 1} / ${TOTAL}`; 1257 } 1258 } else { 1259 misses++; 1260 } 1261 }); 1262 1263 closeBtn.addEventListener('click', () => { 1264 gameModal.classList.remove('open'); 1265 state = 'idle'; 1266 cancelAnimationFrame(raf); 1267 }); 1268 gameModal.addEventListener('click', e => { 1269 if (e.target === gameModal) { gameModal.classList.remove('open'); state = 'idle'; cancelAnimationFrame(raf); } 1270 }); 1271 document.addEventListener('keydown', e => { 1272 if (e.key === 'Escape' && gameModal.classList.contains('open')) { 1273 gameModal.classList.remove('open'); state = 'idle'; cancelAnimationFrame(raf); 1274 } 1275 }); 1276 1277 // draw initial idle frame when modal opens 1278 window._openGame = function (hard) { 1279 hardMode = !!hard; 1280 gameModal.classList.add('open'); 1281 document.getElementById('gameModal').querySelector('.term-title').textContent = 1282 hard ? 'aim_trainer.exe --hard' : 'aim_trainer.exe'; 1283 state = 'idle'; 1284 cancelAnimationFrame(raf); 1285 drawIdle(); 1286 }; 1287 })(); 1288 1289 // interactive terminal 1290 (function () { 1291 const input = document.getElementById('termInput'); 1292 const output = document.getElementById('termOutput'); 1293 if (!input || !output) return; 1294 1295 const CC_LOGO = `<span class="cc-logo" title="Claude Code">C</span>`;
1296 const CC_MSG = 'Claude Code has not implemented it for Me :('; 1297 1298 function pushLine(html) { 1299 const div = document.createElement('div'); 1300 div.className = 'out-line'; 1301 div.innerHTML = html; 1302 output.appendChild(div); 1303 output.scrollTop = output.scrollHeight; 1304 } 1305 1306 input.addEventListener('keydown', e => { 1307 if (e.key !== 'Enter') return; 1308 const cmd = input.value.trim().toLowerCase(); 1309 input.value = ''; 1310 if (!cmd) return; 1311 pushLine(`<span class="echo-cmd">$ ${cmd}</span>`); 1312 if (cmd === 'game' || cmd === 'game --hard') { 1313 const hard = cmd.includes('--hard'); 1314 setTimeout(() => { 1315 pushLine(`<span class="out-text" style="color:var(--green)">launching aim_trainer.exe${hard ? ' --hard' : ''}â¦</span>`); 1316 setTimeout(() => window._openGame(hard), 400); 1317 }, 80); 1318 } else { 1319 setTimeout(() => { 1320 pushLine(`${CC_LOGO}<span class="out-text">${CC_MSG}</span>`); 1321 }, 120); 1322 } 1323 }); 1324 })(); 1325 1326 // news scroll â show first 5 rows then scroll 1327 (function () { 1328 const list = document.getElementById('newsList'); 1329 if (!list) return; 1330 const items = Array.from(list.children); 1331 const h = items.slice(0, 5).reduce((acc, li) => acc + li.offsetHeight, 0); 1332 list.style.maxHeight = Math.ceil(h) + 'px'; 1333 })(); 1334</script>
1334 1335</body> 1336</html>
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.