PageSourceSearch

https://www.gooood.cn/category/news

html gooood.cn collected 2026-10-02 06:04:37 UTC 385,533 bytes, 4,688 lines download raw bytes

1<!doctype html>
2<html lang="zh-CN" data-v10-runtime-source="nuxt-v10-runtime:archive-full-page:categories:news" data-v10-runtime-fetched-at="2026-10-02T06:04:32.299Z" data-v10-posts-cache-status="fresh" data-content-surface="taxonomy" data-content-source="https://dashboard.gooood.cn/wp-json/wp/v2/posts?categories=36119" data-content-cache-status="refreshed" data-content-source-fetched-at="2026-10-02T06:04:36.660Z" data-content-served-at="2026-10-02T06:04:36.660Z" data-content-fingerprint="8f60dfacbc872470" data-content-degraded-sources="">
3<head>
3<script type="module" src="/assets/navigation/20260914/navigation.mjs" data-gooood-managed-navigation="1"></script>
3<base href="/candidates/v10-home-20260709/">
4  <meta charset="utf-8">
5  <meta name="viewport" content="width=device-width, initial-scale=1"><link rel="dns-prefetch" href="https://oss.gooood.cn"><link rel="preconnect" href="https://oss.gooood.cn"><link rel="preload" as="image" href="https://oss.gooood.cn/uploads/2026/09/library-%E6%8B%B7%E8%B4%9Dppt.jpg" media="(min-width: 768px)" fetchpriority="high"><link rel="preload" as="image" href="https://oss.gooood.cn/uploads/2026/09/library-%E6%8B%B7%E8%B4%9Dppt-768x230.jpg" media="(max-width: 767px)" fetchpriority="high"><link rel="preload" as="image" href="https://oss.gooood.cn/uploads/2026/09/%E5%B0%81%E9%9D%A2%E7%94%A8-472x303.png" imagesrcset="https://oss.gooood.cn/uploads/2026/09/%E5%B0%81%E9%9D%A2%E7%94%A8-472x303.png 472w, https://oss.gooood.cn/uploads/2026/09/%E5%B0%81%E9%9D%A2%E7%94%A8-650x417.png 650w" imagesizes="(max-width: 767px) calc(100vw - 52px), 472px" media="(max-width: 767px)" fetchpriority="high">
5<script data-gooood-v10-analytics>(function(){
6    var id="G-CH5FSBW2P3";
7    var production=location.hostname==='www.gooood.cn'||location.hostname==='gooood.cn';
8    var debug=false;
9    try{debug=localStorage.getItem('gooood:analytics:debug')==='1';}catch(e){}
10    if(!production&&!debug){window.__GOOOOD_ANALYTICS_STATUS__={provider:'ga4',enabled:false,measurementId:id,reason:'non-production-host'};return;}
11    window.dataLayer=window.dataLayer||[];
12    window.gtag=window.gtag||function(){window.dataLayer.push(arguments);};
13    if(!document.querySelector('script[data-gooood-ga4="'+id+'"]')){var s=document.createElement('script');s.async=true;s.src='https://www.googletagmanager.com/gtag/js?id='+encodeURIComponent(id);s.dataset.goooodGa4=id;document.head.appendChild(s);}
14    gtag('js',new Date());gtag('config',id,{send_page_view:false});
15    gtag('event','page_view',{page_location:location.href,page_path:location.pathname+location.search+location.hash,page_title:document.title});
16    window.__GOOOOD_ANALYTICS_STATUS__={provider:'ga4',enabled:true,measurementId:id,pageViewMode:'v10-full-page',rum:true,adVisibility:true};
17    var sent={};
18    function metric(name,value){if(sent[name]||!isFinite(value))return;sent[name]=true;gtag('event','web_vital',{metric_name:name,metric_value:Math.round(value),non_interaction:true});}
19    try{var nav=performance.getEntriesByType('navigation')[0];if(nav)metric('TTFB',nav.responseStart);}catch(e){}
20    var lcp=0,cls=0,inp=0;
21    try{new PerformanceObserver(function(list){var entries=list.getEntries();if(entries.length)lcp=entries[entries.length-1].startTime;}).observe({type:'largest-contentful-paint',buffered:true});}catch(e){}
22    try{new PerformanceObserver(function(list){list.getEntries().forEach(function(entry){if(!entry.hadRecentInput)cls+=entry.value;});}).observe({type:'layout-shift',buffered:true});}catch(e){}
23    try{new PerformanceObserver(function(list){list.getEntries().forEach(function(entry){if(entry.interactionId&&entry.duration>inp)inp=entry.duration;});}).observe({type:'event',buffered:true,durationThreshold:40});}catch(e){}
24    function flush(){metric('LCP',lcp);metric('CLS',cls*1000);metric('INP',inp);}
25    addEventListener('pagehide',flush,{once:true});document.addEventListener('visibilitychange',function(){if(document.visibilityState==='hidden')flush();});
26    addEventListener('error',function(event){gtag('event','frontend_error',{error_type:'error',error_message:String(event.message||'unknown').slice(0,120),non_interaction:true});});
27    addEventListener('unhandledrejection',function(event){gtag('event','frontend_error',{error_type:'unhandledrejection',error_message:String(event.reason?.message||event.reason||'unknown').slice(0,120),non_interaction:true});});
28    function observeAds(){if(!('IntersectionObserver'in window))return;var seen=new WeakSet();var observer=new IntersectionObserver(function(entries){entries.forEach(function(entry){if(entry.isIntersecting&&entry.intersectionRatio>=.5&&!seen.has(entry.target)){seen.add(entry.target);gtag('event','ad_view',{ad_position:entry.target.getAttribute('data-ad-position')||entry.target.getAttribute('aria-label')||'unknown',non_interaction:true});observer.unobserve(entry.target);}});},{threshold:[.5]});document.querySelectorAll('[data-ad-position]').forEach(function(node){observer.observe(node);});}
29    function bindAdvertisementClicks(){if(window.__GOOOOD_AD_CLICK_COUNTER_BOUND__)return;window.__GOOOOD_AD_CLICK_COUNTER_BOUND__=true;var endpoint='https://dashboard.gooood.cn/wp-json/wp/v2/shows';window.__GOOOOD_AD_CLICK_COUNTER__={bound:true,endpoint:endpoint};document.addEventListener('click',function(event){if(event.defaultPrevented)return;var target=event.target&&event.target.closest?event.target:null;var link=target&&target.closest('a[href]');var wordlink=link&&link.closest('[data-legacy-ad-wordlink]');if(!link||(wordlink&&!wordlink.hasAttribute('data-wordlink-click-tracking')))return;var href=link.getAttribute('href')||'';if(!href||href==='#'||/^javascript:/i.test(href))return;var ad=link.closest('[data-ad-record-id],[data-ad-id]');if(!ad)return;var id=ad.getAttribute('data-ad-record-id')||ad.getAttribute('data-ad-id')||'';if(!/^[1-9]\d*$/.test(id))return;fetch(endpoint,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({post_ids:[id]}),credentials:'omit',keepalive:true,mode:'cors'}).catch(function(){});},true);}
30    bindAdvertisementClicks();
31    if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',observeAds,{once:true});else observeAds();
32  })();</script>
32<script data-gooood-v10-pagination-jump>(function(){
33    document.addEventListener('submit',function(event){
34      var form=event.target&&event.target.closest?event.target.closest('form.page-jump'):null;
35      if(!form)return;
36      event.preventDefault();
37      var input=form.querySelector('input[type="number"]');
38      var nav=form.closest('nav.pagination');
39      if(!input||!nav)return;
40      var page=Math.floor(Number(input.value));
41      var total=Math.max(1,Number(nav.dataset.totalPages||input.max||1));
42      if(!Number.isFinite(page)||page<1||page>total){input.focus();return;}
43      var target=page===1?nav.dataset.pageOneUrl:String(nav.dataset.pageUrlTemplate||'').replace('__PAGE__',String(page));
44      if(target)location.assign(target);
45    });
46  })();</script>
46<script>window.__GOOOOD_V10_CRITICAL_IMAGES__={"https://oss.gooood.cn/uploads/2026/04/odd-ppt-拷贝.jpg":"/assets/v10-lcp/carousel-d3dab1b69f.webp","https://oss.gooood.cn/uploads/2026/07/00-gooood-interview-Yang-Dingliang的副本_副本-ykt-472x303.png":"/assets/v10-lcp/article-1ff2f16a78.webp"};</script>
46
47  <title>资讯 - gooood</title>
48  
48<script>
49    const v10Embed = new URLSearchParams(window.location.search).get('embed');
50    if (v10Embed === 'body' || v10Embed === 'header') {
51      document.documentElement.dataset.v10Embed = v10Embed;
52    }
53  </script>
53
54  
54<script data-v10-legacy-cache-cleanup="1">
55    (() => {
56      const legacyWorkerPath = '/dist/public/sw.js';
57      const legacyCachePrefixes = ['cache_v1'];
58
59      window.addEventListener('pageshow', (event) => {
60        if (!event.persisted) return;
61        window.location.reload();
62      });
63
64      const clearLegacyHomepageCache = async () => {
65        try {
66          if ('serviceWorker' in navigator) {
67            const registrations = await navigator.serviceWorker.getRegistrations();
68            await Promise.all(registrations.map((registration) => {
69              const worker = registration.active || registration.waiting || registration.installing;
70              const scriptUrl = worker?.scriptURL || '';
71              return scriptUrl.endsWith(legacyWorkerPath) ? registration.unregister() : false;
72            }));
73          }
74        } catch (_) {}
75
76        try {
77          if ('caches' in window) {
78            const keys = await caches.keys();
79            await Promise.all(keys
80              .filter((key) => legacyCachePrefixes.some((prefix) => key === prefix || key.startsWith(`${prefix}-`)))
81              .map((key) => caches.delete(key)));
82          }
83        } catch (_) {}
84      };
85
86      void clearLegacyHomepageCache();
87    })();
88  </script>
88
89  <style>
90    :root {
91      --bg: #ffffff;
92      --paper: #ffffff;
93      --soft: #ffffff;
94      --ink: #080b0f;
95      --muted: #5f6f7d;
96      --meta-light: #aeb7bf;
97      --line: #d2dee8;
98      --line2: #e7edf2;
99      --accent: #006cad;
100      --blue: #075d93;
101      --deep-blue: #07324f;
102      --pale-blue: #e6f2fa;
103      --ice: #f3f8fc;
104      --steel: #8ba1b2;
105      --gap: 20px;
106      --article-column-gap: 0px;
107      --main-pad-left: 15px;
108      --main-pad-right: 15px;
109      --article-flow-max: 936px;
110      --sidebar-flow-width: 390px;
111    }
112    * { box-sizing: border-box; min-width: 0; }
113    body {
114      margin: 0;
115      background: var(--bg);
116      color: var(--ink);
117      font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;
118      line-height: 1.52;
119      letter-spacing: 0;
120      overflow-x: hidden;
121    }
122    a { color: inherit; text-decoration: none; }
123    a:hover,
124    a:focus-visible {
125      text-decoration: underline;
126      text-decoration-thickness: 2px;
127      text-underline-offset: 4px;
128    }
129    .site img { display: block; width: 100%; height: 100%; object-fit: cover; background: #dfe6ed; }
130    .site .gooood-account-avatar { width: 32px; height: 32px; }
131    .site {
132      max-width: 1280px;
133      margin: 0 auto;
134      padding-top: 64px;
135      background: var(--paper);
136      min-height: 100vh;
137    }
138    html[data-v10-embed="body"] .site {
139      padding-top: 0;
140    }
141    html[data-v10-embed="body"] .site-header {
142      display: none;
143    }
144    html[data-v10-embed="header"],
145    html[data-v10-embed="header"] body {
146      background: transparent;
147      overflow: hidden;
148    }
149    html[data-v10-embed="header"] .site {
150      min-height: 0;
151      padding-top: 0;
152    }
153    html[data-v10-embed="header"] .site > :not(.site-header) {
154      display: none !important;
155    }
156    .site-header {
157      position: fixed;
158      top: 0;
159      left: 0;
160      right: 0;
161      z-index: 80;
162      width: 100%;
163      max-width: none;
164      margin: 0 auto;
165      background: rgba(255,255,255,.97);
166      border-bottom: 1px solid var(--line);
167      backdrop-filter: blur(10px);
168    }
169    .header-row {
170      min-height: 64px;
171      display: grid;
172      grid-template-columns: 178px minmax(0, 1fr) auto;
173      gap: 16px;
174      align-items: center;
175      width: 100%;
176      max-width: 1280px;
177      margin: 0 auto;
178      padding: 0 34px;
179    }
180    .mobile-menu-toggle,
181    .mobile-menu {
182      display: none;
183    }
184    .mobile-menu-toggle {
185      border: 0;
186      background: transparent;
187      padding: 0;
188      cursor: pointer;
189    }
190    .mobile-menu-toggle span {
191      display: block;
192      width: 22px;
193      height: 2px;
194      margin: 0 0 6px;
195      background: #333;
196    }
197    .mobile-menu-toggle span:last-child {
198      margin-bottom: 0;
199    }
200    .header-actions {
201      display: flex;
202      align-items: center;
203      justify-content: end;
204      gap: 8px;
205      color: var(--muted);
206      font-size: 14px;
207      font-weight: 400;
208      white-space: nowrap;
209    }
210    .header-actions > a,
211    .header-actions > button,
212    .action-menu > a {
213      min-height: 28px;
214      display: inline-flex;
215      align-items: center;
216      color: var(--muted);
217    }
218    .header-actions > button {
219      border: 0;
220      background: transparent;
221      font: inherit;
222      cursor: pointer;
223      padding: 0;
224    }
225    .visually-hidden {
226      position: absolute;
227      width: 1px;
228      height: 1px;
229      padding: 0;
230      margin: -1px;
231      overflow: hidden;
232      clip: rect(0, 0, 0, 0);
233      white-space: nowrap;
234      border: 0;
235    }
236    .header-search {
237      position: relative;
238      display: inline-flex;
239      align-items: center;
240    }
241    .header-search-toggle {
242      min-height: 28px;
243      display: inline-flex;
244      align-items: center;
245      gap: 6px;
246      justify-content: center;
247      border: 0;
248      background: transparent;
249      color: var(--muted);
250      font: inherit;
251      cursor: pointer;
252      padding: 0;
253    }
254    .header-search-icon {
255      width: 14px;
256      height: 14px;
257      position: relative;
258      display: inline-block;
259      box-sizing: border-box;
260      border: 2px solid currentColor;
261      border-radius: 50%;
262    }
263    .header-search-icon::after {
264      content: "";
265      position: absolute;
266      right: -6px;
267      bottom: -4px;
268      width: 7px;
269      height: 2px;
270      background: currentColor;
271      transform: rotate(45deg);
272      transform-origin: left center;
273    }
274    .header-search-panel {
275      position: fixed;
276      inset: 0;
277      z-index: 180;
278    }
279    .header-search-panel[hidden] {
280      display: none;
281    }
282    .header-search-backdrop {
283      position: absolute;
284      inset: 0;
285      border: 0;
286      background: rgba(255,255,255,.72);
287      cursor: default;
288    }
289    .header-search-modal {
290      position: absolute;
291      top: 94px;
292      left: 50%;
293      width: min(860px, calc(100vw - 48px));
294      transform: translateX(-50%);
295      box-sizing: border-box;
296      padding: 34px 38px 30px;
297      border: 1px solid var(--line);
298      background: rgba(255,255,255,.99);
299      box-shadow: 0 18px 48px rgba(7,50,79,.18);
300      color: var(--ink);
301    }
302    .header-search-close {
303      position: absolute;
304      top: 10px;
305      right: 14px;
306      width: 28px;
307      height: 28px;
308      border: 0;
309      background: transparent;
310      color: var(--muted);
311      font-size: 24px;
312      line-height: 1;
313      cursor: pointer;
314    }
315    .header-search-form {
316      display: flex;
317      align-items: center;
318      gap: 12px;
319      margin: 0;
320    }
321    .header-search-form input {
322      min-width: 0;
323      flex: 1 1 auto;
324      height: 48px;
325      border: 0;
326      border-bottom: 1px solid var(--line);
327      outline: none;
328      color: var(--ink);
329      font-size: 20px;
330      line-height: 48px;
331      background: transparent;
332    }
333    .header-search-form button {
334      width: 42px;
335      height: 42px;
336      display: inline-flex;
337      align-items: center;
338      justify-content: center;
339      border: 0;
340      background: transparent;
341      color: var(--muted);
342      cursor: pointer;
343    }
344    .header-search-tags {
345      margin-top: 24px;
346      padding-top: 20px;
347      border-top: 1px solid var(--line2);
348      color: var(--muted);
349      text-align: left;
350      white-space: normal;
351    }
352    .header-search-tags h2 {
353      margin: 0 0 14px;
354      color: var(--ink);
355      font-size: 16px;
356      font-weight: 400;
357    }
358    .header-search-tags .tags-group {
359      display: flex;
360      flex-wrap: wrap;
361      gap: 8px 12px;
362      align-items: center;
363      margin-top: 8px;
364    }
365    .header-search-tags .tags-group span {
366      min-width: 44px;
367      color: var(--ink);
368      font-size: 13px;
369    }
370    .header-search-tags .tags-group a {
371      color: var(--muted);
372      font-size: 13px;
373    }
374    .action-menu {
375      position: relative;
376      display: inline-flex;
377      align-items: center;
378    }
379    .action-dropdown,
380    .nav-dropdown {
381      position: absolute;
382      top: calc(100% + 12px);
383      z-index: 120;
384      min-width: 168px;
385      padding: 8px 0;
386      background: rgba(255,255,255,.98);
387      border: 1px solid var(--line);
388      box-shadow: 0 12px 28px rgba(7,50,79,.12);
389      opacity: 0;
390      visibility: hidden;
391      transform: translateY(-4px);
392      transition: opacity .16s ease, transform .16s ease, visibility .16s ease;
393    }
394    .action-dropdown { right: 0; }
395    .nav-dropdown { left: 0; }
396    .action-menu:hover .action-dropdown,
397    .action-menu:focus-within .action-dropdown,
398    .nav-item:hover .nav-dropdown,
399    .nav-item:focus-within .nav-dropdown {
400      opacity: 1;
401      visibility: visible;
402      transform: translateY(0);
403    }
404    .action-dropdown a,
405    .nav-dropdown a,
406    .action-dropdown span {
407      display: block;
408      padding: 7px 12px;
409      color: var(--ink);
410      font-size: 14px;
411      line-height: 1.35;
412      font-weight: 400;
413      text-transform: none;
414    }
415    .action-dropdown span {
416      max-width: 220px;
417      color: var(--muted);
418      white-space: normal;
419    }
420    .action-dropdown a:hover,
421    .nav-dropdown a:hover {
422      color: var(--accent);
423      background: var(--ice);
424    }
425    .header-actions .post-job {
426      min-height: 34px;
427      display: inline-flex;
428      align-items: center;
429      justify-content: center;
430      padding: 0 13px;
431      background: var(--ink);
432      color: #fff;
433    }
434    .topbar {
435      min-height: 34px;
436      display: flex;
437      align-items: center;
438      justify-content: space-between;
439      gap: 18px;
440      padding: 0 34px;
441      background: var(--deep-blue);
442      color: rgba(255,255,255,.78);
443      font-size: 12px;
444      font-weight: 760;
445    }
446    .topbar nav { display: flex; gap: 18px; flex-wrap: wrap; }
447    .masthead {
448      display: grid;
449      grid-template-columns: 196px minmax(260px, 1fr) auto;
450      gap: 24px;
451      align-items: center;
452      padding: 24px 34px 20px;
453      border-bottom: 1px solid var(--line);
454      background:
455        linear-gradient(90deg, rgba(0,108,173,.08), rgba(255,255,255,0) 34%),
456        var(--paper);
457    }
458    .logo {
459      display: block;
460      width: 176px;
461      height: 56px;
462      background: url("gooood-logo-online.jpg") left center / contain no-repeat;
463      overflow: hidden;
464      text-indent: -9999px;
465    }
466    .mast-copy {
467      max-width: 560px;
468      color: var(--muted);
469      font-size: 13px;
470    }
471    .mast-actions {
472      display: flex;
473      align-items: center;
474      gap: 10px;
475      justify-content: end;
476    }
477    .search-pill {
478      width: 190px;
479      min-height: 40px;
480      display: inline-flex;
481      align-items: center;
482      gap: 8px;
483      padding: 0 12px;
484      border: 1px solid var(--line);
485      background: #fff;
486      color: var(--muted);
487      font-size: 12px;
488      font-weight: 760;
489      white-space: nowrap;
490    }
491    .search-pill::before {
492      content: "";
493      width: 10px;
494      height: 10px;
495      border: 2px solid var(--accent);
496      border-radius: 50%;
497      box-shadow: 6px 6px 0 -4px var(--accent);
498    }
499    .mast-button {
500      min-height: 40px;
501      display: inline-flex;
502      align-items: center;
503      justify-content: center;
504      padding: 0 16px;
505      border: 1px solid var(--ink);
506      background: var(--ink);
507      color: #fff;
508      font-size: 12px;
509      font-weight: 900;
510      white-space: nowrap;
511    }
512    .nav {
513      display: flex;
514      gap: 3px;
515      flex-wrap: nowrap;
516      align-items: center;
517      min-width: 0;
518      overflow: visible;
519      padding: 0;
520      border-bottom: 0;
521      background: transparent;
522      font-size: 14px;
523      font-weight: 400;
524      text-transform: none;
525      white-space: nowrap;
526    }
527    .nav-item {
528      position: relative;
529      flex: 0 0 auto;
530    }
531    .nav-link {
532      min-height: 36px;
533      display: inline-flex;
534      align-items: center;
535      padding: 0 5px;
536    }
537    .nav-item.has-dropdown .nav-link::after,
538    .action-menu.has-dropdown > a::after {
539      content: "";
540      width: 0;
541      height: 0;
542      margin-left: 5px;
543      border-left: 3px solid transparent;
544      border-right: 3px solid transparent;
545      border-top: 4px solid var(--steel);
546    }
547    .nav-item:hover .nav-link,
548    .nav-item:focus-within .nav-link,
549    .header-actions a:hover,
550    .header-actions button:hover {
551      color: var(--accent);
552    }
553    .layout {
554      display: grid;
555      grid-template-columns: minmax(0, var(--article-flow-max)) var(--sidebar-flow-width);
556      align-items: start;
557      justify-content: center;
558    }
559    .main {
560      width: 100%;
561      max-width: var(--article-flow-max);
562      min-width: 0;
563      padding-bottom: 42px;
564    }
565    .side {
566      min-width: 0;
567      border-left: 1px solid var(--line2);
568      background: var(--soft);
569      width: var(--sidebar-flow-width);
570    }
571    .section-label {
572      display: grid;
573      grid-template-columns: auto minmax(30px,1fr) auto;
574      gap: 12px;
575      align-items: center;
576      padding: 26px var(--main-pad-right) 16px var(--main-pad-left);
577      color: var(--muted);
578      font-size: 12px;
579      font-weight: 950;
580      letter-spacing: .09em;
581      text-transform: uppercase;
582    }
583    .quick-board {
584      display: grid;
585      grid-template-columns: repeat(5, minmax(0, 1fr));
586      margin: 0 var(--main-pad-right) 22px var(--main-pad-left);
587      border: 1px solid var(--line);
588      background: var(--ice);
589    }
590    .quick-card {
591      min-height: 82px;
592      display: grid;
593      align-content: center;
594      gap: 5px;
595      padding: 14px 16px;
596      border-right: 1px solid var(--line);
597    }
598    .quick-card:last-child { border-right: 0; }
599    .quick-card strong {
600      color: var(--deep-blue);
601      font-size: 15px;
602      line-height: 1.25;
603    }
604    .quick-card span {
605      color: var(--muted);
606      font-size: 11px;
607      line-height: 1.35;
608    }
609    .quick-card.primary {
610      background: var(--deep-blue);
611      color: #fff;
612    }
613    .quick-card.primary strong { color: #fff; }
614    .quick-card.primary span { color: rgba(255,255,255,.68); }
615    .section-label::before,
616    .section-label::after {
617      content: "";
618      height: 1px;
619      background: currentColor;
620      opacity: .42;
621    }
622    .row {
623      display: grid;
624      grid-template-columns: repeat(2, minmax(0, 1fr));
625      column-gap: var(--article-column-gap);
626      row-gap: var(--gap);
627      padding: 0 var(--main-pad-right) 42px var(--main-pad-left);
628    }
629    .article {
630      min-width: 0;
631      display: grid;
632      grid-template-rows: auto 1fr;
633      padding: 0 10px;
634      background: var(--paper);
635    }
636    .cover {
637      border: 1px solid var(--line);
638      overflow: hidden;
639    }
640    .article-cover-link {
641      display: block;
642      width: 100%;
643      height: auto;
644      text-decoration: none;
645    }
646    .article-cover-link:hover,
647    .article-cover-link:focus-visible {
648      text-decoration: none;
649    }
650    .article-cover-link:focus-visible {
651      outline: 2px solid var(--accent);
652      outline-offset: -2px;
653    }
654    .article .cover {
655      height: auto;
656      aspect-ratio: auto;
657      border: 0;
658    }
659    .article .cover img {
660      height: auto;
661      object-fit: cover;
662    }
663    .article-text {
664      height: 247px;
665      min-height: 247px;
666      display: flex;
667      flex-direction: column;
668      gap: 0;
669      padding: 15px 0 0;
670    }
671    .kicker {
672      margin: 0 0 10px;
673      color: #bbbbbb;
674      font-size: 12px;
675      line-height: 17.1428px;
676      font-weight: 400;
677      letter-spacing: 0;
678      text-transform: none;
679    }
680    h1, h2, h3, h4 {
681      margin: 0;
682      line-height: 1.18;
683      letter-spacing: 0;
684      overflow-wrap: break-word;
685    }
686    .article h3 {
687      display: -webkit-box;
688      margin: 0 0 10px;
689      max-height: 54px;
690      overflow: hidden;
691      font-size: 18px;
692      font-weight: 700;
693      line-height: 27px;
694      text-overflow: ellipsis;
695      -webkit-line-clamp: 2;
696      -webkit-box-orient: vertical;
697    }
698    .article h3 a {
699      display: block;
700      color: #4a4a4a;
701      text-decoration: none;
702    }
703    .article h3 a:hover,
704    .article h3 a:focus-visible {
705      text-decoration: underline;
706      text-decoration-thickness: 2px;
707      text-underline-offset: 4px;
708    }
709    .article-subtitle {
710      display: -webkit-box;
711      color: #666666;
712      height: 63px;
713      overflow: hidden;
714      font-size: 14px;
715      line-height: 21px;
716      font-weight: 400;
717      text-overflow: ellipsis;
718      white-space: normal;
719      -webkit-box-orient: vertical;
720      -webkit-line-clamp: 3;
721    }
722    .article-foot {
723      display: flex;
724      align-items: center;
725      justify-content: space-between;
726      gap: 10px;
727      margin-top: auto;
728      padding-top: 10px;
729      color: #bbbbbb;
730      font-size: 12px;
731      line-height: 17.1428px;
732      font-weight: 400;
733    }
734    .article-actions {
735      display: inline-flex;
736      align-items: center;
737      gap: 10px;
738      white-space: nowrap;
739    }
740    .article-actions a,
741    .article-actions button {
742      color: #bbbbbb;
743      font-weight: 400;
744      text-decoration: none;
745    }
746    .action-item {
747      display: inline-flex;
748      align-items: center;
749      gap: 3px;
750      color: #bbbbbb;
751      font: inherit;
752      cursor: pointer;
753    }
754    .share-action {
755      position: relative;
756    }
757    .share-action button {
758      display: inline-flex;
759      align-items: center;
760      gap: 3px;
761      border: 0;
762      background: transparent;
763      padding: 0;
764      font: inherit;
765    }
766    .share-action button:hover,
767    .share-action button:focus-visible {
768      text-decoration: underline;
769      text-decoration-thickness: 2px;
770      text-underline-offset: 4px;
771    }
772    .share-icons-dropdown {
773      position: absolute;
774      right: 0;
775      bottom: calc(100% + 8px);
776      z-index: 40;
777      display: flex;
778      gap: 5px;
779      padding: 7px;
780      background: rgba(255,255,255,.98);
781      border: 1px solid var(--line2);
782      box-shadow: 0 8px 20px rgba(7,50,79,.12);
783      opacity: 0;
784      visibility: hidden;
785      transform: translateY(4px);
786      transition: opacity .16s ease, transform .16s ease, visibility .16s ease;
787    }
788    .share-action:hover .share-icons-dropdown,
789    .share-action:focus-within .share-icons-dropdown {
790      opacity: 1;
791      visibility: visible;
792      transform: translateY(0);
793    }
794    .share-icons-dropdown a {
795      width: 22px;
796      height: 22px;
797      display: grid;
798      place-items: center;
799      border: 1px solid #aeb7bf;
800      color: #8d98a1;
801      font-size: 10px;
802      line-height: 1;
803    }
804    .meta {
805      color: var(--muted);
806      font-size: 11px;
807      font-weight: 750;
808    }
809    .ad-embed {
810      margin: 0 var(--main-pad-right) 30px var(--main-pad-left);
811    }
812    .ad-embed table {
813      max-width: 100% !important;
814    }
815    .ad-embed.page-bottom {
816      margin-top: 0;
817    }
818    .ad-embed.materials-ad,
819    .ad-embed.project-ad {
820      padding-bottom: 30px;
821    }
822    .ad-strip {
823      margin: 0 var(--main-pad-right) 22px var(--main-pad-left);
824      display: grid;
825      grid-template-columns: 1.1fr minmax(0, 1fr) auto;
826      gap: 16px;
827      align-items: center;
828      min-height: 76px;
829      padding: 15px 18px;
830      background: var(--pale-blue);
831      border: 1px solid #a9c6da;
832      color: var(--deep-blue);
833    }
834    .ad-strip.dark {
835      background: var(--blue);
836      border-color: #486b80;
837      color: #fff;
838    }
839    .ad-strip.green {
840      background: var(--deep-blue);
841      border-color: #355971;
842      color: #fff;
843    }
844    .top-slider {
845      position: relative;
846      margin: 0 var(--main-pad-right) 22px var(--main-pad-left);
847      aspect-ratio: 2000 / 600;
848      overflow: hidden;
849      border: 1px solid #a9c6da;
850      background: var(--deep-blue);
851    }
852    .top-slider .slide {
853      position: absolute;
854      inset: 0;
855      opacity: 0;
856      pointer-events: none;
857      transition: opacity .25s ease;
858    }
859    .top-slider .slide.is-active {
860      opacity: 1;
861      pointer-events: auto;
862    }
863    .top-slider .slide-link {
864      display: block;
865      width: 100%;
866      height: 100%;
867      text-decoration: none;
868    }
869    .top-slider .slide-link:hover,
870    .top-slider .slide-link:focus-visible {
871      text-decoration: none;
872    }
873    .top-slider img {
874      width: 100%;
875      height: 100%;
876      object-fit: cover;
877    }
878    .top-slider-dots {
879      position: absolute;
880      right: 24px;
881      bottom: 24px;
882      z-index: 1;
883      display: flex;
884      gap: 7px;
885    }
886    .top-slider-dots button {
887      width: 9px;
888      height: 9px;
889      padding: 0;
890      border: 0;
891      border-radius: 999px;
892      background: rgba(255,255,255,.58);
893      cursor: pointer;
894    }
895    .top-slider-dots button.is-active {
896      width: 22px;
897      background: #fff;
898    }
899    .slider-controls {
900      position: absolute;
901      inset: 0;
902      z-index: 2;
903      display: flex;
904      align-items: center;
905      justify-content: space-between;
906      padding: 0 14px;
907      pointer-events: none;
908    }
909    .slider-btn {
910      width: 38px;
911      height: 38px;
912      display: grid;
913      place-items: center;
914      border: 1px solid rgba(255,255,255,.62);
915      background: rgba(7,50,79,.48);
916      color: #fff;
917      font-size: 24px;
918      line-height: 1;
919      cursor: pointer;
920      pointer-events: auto;
921      backdrop-filter: blur(6px);
922    }
923    .slider-btn:hover,
924    .slider-btn:focus-visible {
925      background: rgba(255,255,255,.92);
926      color: var(--deep-blue);
927    }
928    .ad-strip .ad-label {
929      color: var(--accent);
930      font-size: 10px;
931      font-weight: 950;
932      letter-spacing: .12em;
933      text-transform: uppercase;
934    }
935    .ad-strip.dark .ad-label,
936    .ad-strip.green .ad-label { color: #b8d4e8; }
937    .ad-strip h2 {
938      margin-top: 2px;
939      font-size: 20px;
940      font-weight: 950;
941    }
942    .ad-strip p {
943      margin: 0;
944      color: #4f6373;
945      font-size: 12px;
946      font-weight: 730;
947    }
948    .ad-strip.dark p,
949    .ad-strip.green p { color: rgba(255,255,255,.66); }
950    .ad-strip a {
951      padding: 9px 12px;
952      border: 1px solid currentColor;
953      font-size: 12px;
954      font-weight: 900;
955      white-space: nowrap;
956    }
957    .job-text {
958      margin: 0 var(--main-pad-right) 56px var(--main-pad-left);
959      border: 0;
960      background: #fff;
961      box-shadow: none;
962    }
963    .job-head {
964      display: flex;
965      gap: 0;
966      align-items: center;
967      padding: 10px 13px;
968      border-bottom: 0;
969      background: #fff;
970      font-size: 12px;
971      font-weight: 950;
972    }
973    .job-head .job-submit {
974      margin-left: 2ch;
975      color: var(--meta-light);
976      font-weight: 400;
977    }
978    .job-head .job-all {
979      margin-left: auto;
980      color: var(--ink);
981      font-weight: 950;
982    }
983    .job-cols {
984      display: grid;
985      grid-template-columns: repeat(3, minmax(0, 1fr));
986    }
987    .job-col {
988      border-right: 1px solid var(--line2);
989    }
990    .job-col:last-child { border-right: 0; }
991    .job-line {
992      display: grid;
993      grid-template-columns: minmax(0, 1fr);
994      gap: 8px;
995      padding: 7px 10px;
996      border-bottom: 1px solid var(--line2);
997      color: var(--muted);
998      font-size: 11px;
999      line-height: 1.32;
1000    }
1001    .job-line:last-child { border-bottom: 0; }
1002    .job-line:hover,
1003    .job-line:focus-visible {
1004      text-decoration: none;
1005    }
1006      .job-line b {
1007        display: block;
1008        min-width: 0;
1009        overflow: hidden;
1010        color: #4a4a4a;
1011        font-size: 11px;
1012        font-weight: 400;
1013        text-overflow: ellipsis;
1014        white-space: nowrap;
1015    }
1016    .job-line:hover b,
1017    .job-line:focus-visible b {
1018      text-decoration: underline;
1019      text-decoration-thickness: 1px;
1020      text-underline-offset: 2px;
1021    }
1022    .job-line em { display: none; }
1023    .ops {
1024      display: grid;
1025      grid-template-columns: repeat(2, minmax(0, 1fr));
1026      gap: var(--gap);
1027      padding: 0 var(--main-pad-right) 30px var(--main-pad-left);
1028    }
1029    .panel {
1030      border: 1px solid var(--line);
1031      background: var(--paper);
1032    }
1033    .side .panel {
1034      margin-bottom: 12px;
1035      background: var(--paper);
1036    }
1037    .panel-head {
1038      display: flex;
1039      justify-content: space-between;
1040      gap: 12px;
1041      padding: 12px 14px;
1042      border-bottom: 2px solid var(--deep-blue);
1043      font-size: 13px;
1044      font-weight: 950;
1045    }
1046    .album {
1047      display: grid;
1048      grid-template-columns: 96px minmax(0, 1fr);
1049      gap: 12px;
1050      padding: 11px 13px;
1051      border-bottom: 1px solid var(--line2);
1052    }
1053    .side .album {
1054      grid-template-columns: 82px minmax(0, 1fr);
1055      gap: 10px;
1056      padding: 10px;
1057    }
1058    .side .album span {
1059      display: none;
1060    }
1061    .album:last-child { border-bottom: 0; }
1062    .album .cover { border: 0; }
1063    .album b,
1064    .hot b {
1065      display: block;
1066      font-size: 13px;
1067      line-height: 1.36;
1068    }
1069    .album span,
1070    .hot span {
1071      display: block;
1072      margin-top: 4px;
1073      color: var(--muted);
1074      font-size: 11px;
1075    }
1076    .hot {
1077      display: grid;
1078      grid-template-columns: 34px minmax(0, 1fr);
1079      gap: 10px;
1080      padding: 11px 13px;
1081      border-bottom: 1px solid var(--line2);
1082    }
1083    .side .hot {
1084      grid-template-columns: 28px minmax(0, 1fr);
1085      gap: 8px;
1086      padding: 10px;
1087    }
1088    .side .hot span {
1089      display: none;
1090    }
1091    .hot:last-child { border-bottom: 0; }
1092    .rank {
1093      color: var(--accent);
1094      font: 950 20px/1 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
1095    }
1096    .ops-ad {
1097      display: grid;
1098      align-content: center;
1099      gap: 10px;
1100      grid-column: 1 / -1;
1101      min-height: 96px;
1102      padding: 18px;
1103      background: var(--blue);
1104      color: white;
1105    }
1106    .ops-ad .kicker { color: #c7e3f5; }
1107    .ops-ad h3 { font-size: 23px; }
1108    .ops-ad p { margin: 0; color: rgba(255,255,255,.7); font-size: 12px; }
1109    .ops-ad a {
1110      justify-self: start;
1111      padding: 8px 10px;
1112      border: 1px solid rgba(255,255,255,.42);
1113      font-size: 12px;
1114      font-weight: 900;
1115    }
1116    .pagination {
1117      display: flex;
1118      justify-content: center;
1119      gap: 7px;
1120      flex-wrap: wrap;
1121      margin: 10px var(--main-pad-right) 0 var(--main-pad-left);
1122      padding-top: 26px;
1123      border-top: 1px solid var(--line);
1124    }
1125    .pagination a,
1126    .pagination .page-item {
1127      min-width: 40px;
1128      height: 40px;
1129      display: grid;
1130      place-items: center;
1131      border: 1px solid var(--line);
1132      font-size: 13px;
1133      font-weight: 900;
1134    }
1135    .pagination .active { background: var(--ink); color: white; }
1136    .pagination .disabled {
1137      color: #c7c7c7;
1138      background: #f8f8f8;
1139      pointer-events: none;
1140    }
1141    .pagination .dots {
1142      border-color: transparent;
1143      color: var(--muted);
1144    }
1145    .pagination .page-count {
1146      display: inline-flex;
1147      align-items: center;
1148      height: 40px;
1149      padding: 0 4px 0 10px;
1150      color: var(--muted);
1151      font-size: 12px;
1152      font-weight: 400;
1153    }
1154    .page-jump {
1155      display: inline-flex;
1156      align-items: center;
1157      gap: 5px;
1158      height: 40px;
1159      color: var(--muted);
1160      font-size: 12px;
1161    }
1162    .page-jump input {
1163      width: 54px;
1164      height: 32px;
1165      border: 1px solid var(--line);
1166      padding: 0 8px;
1167      color: var(--ink);
1168      font: inherit;
1169      font-weight: 400;
1170      text-align: center;
1171    }
1172    .page-jump button {
1173      height: 32px;
1174      border: 1px solid var(--ink);
1175      padding: 0 10px;
1176      background: #fff;
1177      color: var(--ink);
1178      font: inherit;
1179      font-size: 12px;
1180      cursor: pointer;
1181    }
1182    .page-jump button:hover {
1183      background: var(--ink);
1184      color: #fff;
1185    }
1186    .sidebar {
1187      position: sticky;
1188      top: 76px;
1189      padding: 0 20px 18px 35px;
1190    }
1191    .side-head {
1192      display: flex;
1193      justify-content: space-between;
1194      gap: 10px;
1195      align-items: center;
1196      padding: 9px 2px 11px;
1197      font-size: 13px;
1198      font-weight: 950;
1199    }
1200    .side-head a { color: var(--accent); font-size: 10px; }
1201    .side-feature {
1202      display: grid;
1203      gap: 8px;
1204      padding: 12px;
1205      margin-bottom: 10px;
1206      background: var(--deep-blue);
1207      color: #fff;
1208      border: 1px solid #174a6e;
1209    }
1210    .side-feature b {
1211      font-size: 18px;
1212      line-height: 1.15;
1213    }
1214    .side-feature span {
1215      color: rgba(255,255,255,.72);
1216      font-size: 11px;
1217      line-height: 1.42;
1218    }
1219    .side-feature a {
1220      justify-self: start;
1221      padding: 7px 9px;
1222      border: 1px solid rgba(255,255,255,.5);
1223      font-size: 11px;
1224      font-weight: 900;
1225    }
1226    .side-jobs {
1227      display: grid;
1228      grid-template-columns: repeat(2, 150px);
1229      column-gap: 35px;
1230      row-gap: 10px;
1231    }
1232    .side-section {
1233      margin-top: 12px;
1234    }
1235    .side-section:first-of-type {
1236      margin-top: 0;
1237    }
1238    .side-section-title {
1239      display: flex;
1240      align-items: center;
1241      justify-content: space-between;
1242      gap: 8px;
1243      padding: 9px 2px 10px;
1244      color: var(--ink);
1245      font-size: 13px;
1246      font-weight: 950;
1247      border-top: 2px solid var(--deep-blue);
1248    }
1249    .side-section-title .side-title-action {
1250      color: var(--ink);
1251      font-size: 13px;
1252      font-weight: 950;
1253    }
1254    .job-region-filter {
1255      margin: -4px 0 9px;
1256      padding: 0 2px 1px;
1257      color: var(--muted);
1258      font-size: 10px;
1259      font-weight: 760;
1260      line-height: 1.6;
1261    }
1262    .job-region-filter a {
1263      color: var(--accent);
1264      font-weight: 900;
1265    }
1266    .side-jobs.home-pinned {
1267      grid-template-columns: repeat(2, 150px);
1268      column-gap: 35px;
1269      row-gap: 10px;
1270      justify-content: stretch;
1271    }
1272
1273    .side-jobs.home-pinned .side-job {
1274      width: 100%;
1275    }
1276    .side-job {
1277      border: 0;
1278      background: var(--paper);
1279      overflow: hidden;
1280      transition: transform .18s ease;
1281    }
1282    .side-job:hover,
1283    .side-job:focus-visible {
1284      transform: translateY(-1px);
1285      text-decoration: none;
1286    }
1287    .side-job:hover b,
1288    .side-job:focus-visible b {
1289      text-decoration: underline;
1290      text-decoration-thickness: 1px;
1291      text-underline-offset: 2px;
1292    }
1293    .side-job .cover {
1294      width: 150px;
1295      height: 96px;
1296      aspect-ratio: auto;
1297      border: 0;
1298    }
1299    .side-job-text {
1300      padding: 6px 0 7px;
1301    }
1302      .side-job b {
1303        display: -webkit-box;
1304        min-height: 39px;
1305        overflow: hidden;
1306        color: #4a4a4a;
1307        font-size: 12px;
1308        font-weight: 400;
1309        line-height: 17px;
1310      -webkit-box-orient: vertical;
1311      -webkit-line-clamp: 3;
1312    }
1313    .side-job span {
1314      display: none;
1315      margin-top: 2px;
1316      color: var(--muted);
1317      font-size: 9px;
1318      line-height: 1.25;
1319    }
1320    .footer-nav {
1321      width: 100vw;
1322      margin-left: calc(50% - 50vw);
1323      padding: 0;
1324      background: #333333;
1325      color: rgba(255,255,255,.62);
1326      border-top: 1px solid rgba(255,255,255,.08);
1327    }
1328    .footer-nav-inner {
1329      width: min(var(--article-flow-max), calc(100vw - 32px));
1330      display: grid;
1331      grid-template-columns: repeat(5, minmax(0, 1fr));
1332      gap: 28px;
1333      margin-left: max(16px, calc((100vw - (var(--article-flow-max) + var(--sidebar-flow-width))) / 2));
1334      padding: 34px 0 30px;
1335    }
1336    .footer-col h4 {
1337      margin-bottom: 13px;
1338      color: #fff;
1339      font-size: 12px;
1340      font-weight: 950;
1341    }
1342    .footer-col a,
1343    .footer-col span {
1344      display: block;
1345      margin-bottom: 7px;
1346      color: rgba(255,255,255,.58);
1347      font-size: 11px;
1348      line-height: 1.35;
1349    }
1350    .footer-social {
1351      display: flex;
1352      gap: 8px;
1353      margin-top: 2px;
1354    }
1355    .footer-social a {
1356      width: 24px;
1357      height: 24px;
1358      display: grid;
1359      place-items: center;
1360      border: 1px solid rgba(255,255,255,.28);
1361      color: rgba(255,255,255,.8);
1362      font-size: 11px;
1363    }
1364    .footer {
1365      width: 100vw;
1366      margin-left: calc(50% - 50vw);
1367      padding: 18px 34px 28px;
1368      background: #333333;
1369      color: rgba(255,255,255,.45);
1370      text-align: center;
1371      font-size: 10px;
1372    }
1373    .footer a {
1374      color: rgba(255,255,255,.6);
1375      text-decoration: none;
1376    }
1377    @media (max-width: 960px) {
1378      .layout { grid-template-columns: 1fr; }
1379      .main { max-width: none; }
1380      .side { display: none; }
1381      .sidebar { position: static; padding: 16px; }
1382      .side-jobs { grid-template-columns: repeat(3, minmax(0, 1fr)); }
1383      .masthead, .ad-strip, .ops { grid-template-columns: 1fr; }
1384      .row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
1385      .quick-board { grid-template-columns: repeat(2, minmax(0, 1fr)); }
1386      .quick-card:nth-child(2) { border-right: 0; }
1387      .quick-card { border-bottom: 1px solid var(--line); }
1388      .quick-card:nth-child(3),
1389      .quick-card:nth-child(4) { border-bottom: 0; }
1390    }
1391    @media (max-width: 640px) {
1392      html,
1393      body,
1394      .site {
1395        width: 100%;
1396        max-width: 100%;
1397        overflow-x: hidden;
1398      }
1399      .layout,
1400      .main {
1401        width: 100%;
1402        max-width: 100vw;
1403      }
1404      .site {
1405        padding-top: 60px;
1406      }
1407      .topbar > span { display: none; }
1408      .topbar, .masthead { padding-left: 16px; padding-right: 16px; }
1409      .header-row {
1410        grid-template-columns: 60px minmax(0, 1fr) 60px;
1411        min-height: 60px;
1412        gap: 0;
1413        padding: 0;
1414      }
1415      .mobile-menu-toggle {
1416        grid-column: 1;
1417        display: grid;
1418        justify-self: start;
1419        align-content: center;
1420        justify-content: center;
1421        width: 60px;
1422        height: 60px;
1423      }
1424      .header-actions {
1425        grid-column: 3;
1426        display: flex;
1427        justify-content: end;
1428      }
1429      .header-actions > a,
1430      .header-actions > button,
1431      .header-actions > .action-menu,
1432      .header-actions > .header-search {
1433        display: none;
1434      }
1435      .header-actions > .action-menu:last-of-type {
1436        display: inline-flex;
1437      }
1438      .header-actions > .action-menu:last-of-type > a {
1439        position: relative;
1440        width: 60px;
1441        min-height: 60px;
1442        justify-content: center;
1443        color: #777;
1444        font-size: 14px;
1445        font-weight: 400;
1446        line-height: 1;
1447      }
1448      .header-actions > .action-menu:last-of-type > a::before {
1449        display: none;
1450      }
1451      .header-actions > .action-menu:last-of-type > a::after {
1452        display: none;
1453      }
1454      .nav {
1455        display: none;
1456      }
1457      .mobile-menu {
1458        position: fixed;
1459        top: 0;
1460        left: 0;
1461        z-index: 85;
1462        width: 240px;
1463        height: 100vh;
1464        display: block;
1465        overflow-y: auto;
1466        background: #3a3a3a;
1467        transform: translateX(-100%);
1468        transition: transform .22s ease;
1469        -webkit-overflow-scrolling: touch;
1470      }
1471      .mobile-menu.is-open {
1472        transform: translateX(0);
1473      }
1474      .mobile-search-form {
1475        width: 240px;
1476        height: 60px;
1477        display: flex;
1478        align-items: center;
1479        position: relative;
1480        padding: 10px 30px;
1481        box-sizing: border-box;
1482      }
1483      .mobile-search-form input {
1484        width: 180px;
1485        height: 40px;
1486        border: 0;
1487        border-radius: 22px;
1488        padding: 0 10px;
1489        box-sizing: border-box;
1490        color: #555;
1491        font-size: 16px;
1492        line-height: 40px;
1493        outline: none;
1494      }
1495      .mobile-search-form button {
1496        width: 37px;
1497        height: 40px;
1498        border: 0;
1499        border-radius: 0;
1500        background: transparent;
1501        color: #555;
1502        font-size: 28px;
1503        line-height: 40px;
1504        cursor: pointer;
1505      }
1506      .mobile-menu-primary {
1507        margin: 20px 0 0;
1508        padding: 0;
1509        list-style: none;
1510      }
1511      .mobile-menu a,
1512      .mobile-menu button {
1513        width: 100%;
1514        min-height: 50px;
1515        display: block;
1516        padding: 0 18px;
1517        box-sizing: border-box;
1518        border: 0;
1519        background: transparent;
1520        color: #fff;
1521        font-size: 16px;
1522        font-weight: 400;
1523        line-height: 50px;
1524        text-align: left;
1525      }
1526      .mobile-menu button {
1527        cursor: pointer;
1528      }
1529      .mobile-menu a:hover,
1530      .mobile-menu a:focus-visible,
1531      .mobile-menu button:hover,
1532      .mobile-menu button:focus-visible {
1533        color: #fff;
1534        text-decoration: none;
1535        background: #4a4a4a;
1536      }
1537      .mobile-menu .caret {
1538        display: inline-block;
1539        flex: 0 0 auto;
1540        float: none;
1541        width: 0;
1542        height: 0;
1543        margin: 0 0 0 12px;
1544        border-top: 4px solid #fff;
1545        border-right: 4px solid transparent;
1546        border-left: 4px solid transparent;
1547      }
1548      .mobile-submenu {
1549        display: none;
1550        margin: 0;
1551        padding: 0;
1552        list-style: none;
1553        background: #333;
1554      }
1555      .mobile-menu-item.is-open > .mobile-submenu {
1556        display: block;
1557      }
1558      .mobile-submenu a {
1559        min-height: 38px;
1560        padding-left: 32px;
1561        color: #d8d8d8;
1562        font-size: 13px;
1563        line-height: 38px;
1564      }
1565      .mobile-menu-tools {
1566        position: absolute;
1567        left: 0;
1568        bottom: 0;
1569        width: 240px;
1570        margin: 0;
1571        padding: 0;
1572        list-style: none;
1573        background: #333;
1574      }
1575      .mobile-menu-tools a,
1576      .mobile-menu-tools button {
1577        min-height: 72px;
1578        line-height: 50px;
1579        color: #fff;
1580        font-size: 18px;
1581      }
1582      .mobile-menu-tools a {
1583        display: flex;
1584        align-items: center;
1585        gap: 14px;
1586      }
1587      .mobile-user-icon {
1588        width: 34px;
1589        height: 34px;
1590        display: inline-flex;
1591        align-items: center;
1592        justify-content: center;
1593        border: 1px solid #fff;
1594        border-radius: 50%;
1595        font-size: 17px;
1596        line-height: 1;
1597      }
1598      .mobile-menu-backdrop {
1599        position: fixed;
1600        inset: 0;
1601        z-index: 70;
1602        width: 100vw;
1603        height: 100vh;
1604        display: none;
1605        padding: 0;
1606        border: 0;
1607        background: rgba(255,255,255,.72);
1608      }
1609      .mobile-menu-backdrop.is-open {
1610        display: block;
1611      }
1612      .mobile-menu[hidden],
1613      .mobile-menu-backdrop[hidden] {
1614        display: none;
1615      }
1616      .mobile-menu[hidden] {
1617        transform: translateX(-100%);
1618      }
1619      .mobile-menu-primary,
1620      .mobile-menu-tools {
1621        border: 0;
1622      }
1623      .mobile-menu-primary li,
1624      .mobile-menu-tools li {
1625        min-height: 50px;
1626      }
1627      .mobile-menu-primary li li {
1628        min-height: 38px;
1629      }
1630      .mobile-menu-toggle {
1631        position: relative;
1632        z-index: 90;
1633      }
1634      .mobile-menu-toggle[aria-expanded="true"] {
1635        position: fixed;
1636        top: 0;
1637        left: 240px;
1638        background: transparent;
1639      }
1640      .header-actions.menu-open {
1641        display: none;
1642      }
1643      .mobile-menu-toggle[aria-expanded="true"] span:nth-child(1) {
1644        transform: translateY(8px) rotate(45deg);
1645      }
1646      .mobile-menu-toggle[aria-expanded="true"] span:nth-child(2) {
1647        opacity: 0;
1648      }
1649      .mobile-menu-toggle[aria-expanded="true"] span:nth-child(3) {
1650        transform: translateY(-8px) rotate(-45deg);
1651      }
1652      .mobile-menu-toggle span {
1653        transition: transform .2s ease, opacity .2s ease;
1654      }
1655      .mobile-menu button.mobile-menu-parent {
1656        display: flex;
1657        align-items: center;
1658        justify-content: space-between;
1659        line-height: 1;
1660      }
1661      .mobile-menu .mobile-search-form button {
1662        position: absolute;
1663        top: 10px;
1664        right: 32px;
1665        width: 40px;
1666        height: 40px;
1667        min-height: 40px;
1668        display: flex;
1669        align-items: center;
1670        justify-content: center;
1671        padding: 0;
1672        color: #555;
1673        background: transparent;
1674        font-size: 0;
1675        line-height: 32px;
1676        text-align: center;
1677      }
1678      .mobile-menu .mobile-search-form button::before {
1679        width: 20px;
1680        height: 20px;
1681        border: 3px solid #555;
1682        border-radius: 50%;
1683        box-sizing: border-box;
1684        content: "";
1685        position: absolute;
1686        left: 8px;
1687        top: 7px;
1688      }
1689      .mobile-menu .mobile-search-form button::after {
1690        width: 11px;
1691        height: 3px;
1692        background: #555;
1693        content: "";
1694        position: absolute;
1695        left: 24px;
1696        top: 24px;
1697        transform: rotate(45deg);
1698        transform-origin: left center;
1699      }
1700      .masthead {
1701        grid-template-columns: 1fr;
1702        gap: 14px;
1703        align-items: start;
1704      }
1705      .logo {
1706        grid-column: 2;
1707        justify-self: center;
1708        width: 120px;
1709        height: 34px;
1710        background-position: center;
1711      }
1712      .mast-actions { justify-content: start; flex-wrap: wrap; }
1713      .search-pill { width: min(100%, 220px); }
1714      .section-label, .row { padding-left: 16px; padding-right: 16px; }
1715      .row, .job-cols { grid-template-columns: 1fr; }
1716      .job-col { border-right: 0; border-bottom: 1px solid var(--line2); }
1717      .job-text .job-col:nth-child(n+2) { display: none; }
1718      .job-col:last-child { border-bottom: 0; }
1719      .ad-strip, .top-slider, .job-text, .pagination, .quick-board, .ad-embed { margin-left: 16px; margin-right: 16px; }
1720      .ad-embed {
1721        overflow: hidden;
1722      }
1723      .ad-embed table {
1724        width: 100% !important;
1725        max-width: 100% !important;
1726        table-layout: fixed;
1727      }
1728      .ad-embed td {
1729        max-width: 100% !important;
1730      }
1731      .pagination { gap: 5px; justify-content: flex-start; }
1732      .pagination a,
1733      .pagination .page-item { min-width: 34px; height: 34px; font-size: 12px; }
1734      .pagination .page-count,
1735      .page-jump { height: 34px; }
1736      .page-jump input,
1737      .page-jump button { height: 30px; }
1738      .ops { padding-left: 16px; padding-right: 16px; }
1739      .article-text { height: auto; min-height: 128px; }
1740      .article h3 {
1741        height: auto;
1742        max-height: 46px;
1743        font-size: 16px;
1744        line-height: 1.45;
1745      }
1746      .article-subtitle {
1747        height: 63px;
1748        min-height: 63px;
1749        white-space: normal;
1750      }
1751      .article-foot { padding-top: 22px; }
1752      .mast-copy { max-width: calc(100vw - 32px);
1752 overflow-wrap: anywhere; }
1753      .ad-strip {
1754        gap: 10px;
1755        min-height: 0;
1756        padding: 12px 14px;
1757      }
1758      .ad-strip h2 { font-size: 20px; }
1759      .ad-strip a { justify-self: start; }
1760      .quick-board { grid-template-columns: 1fr; }
1761      .quick-card,
1762      .quick-card:nth-child(2) { border-right: 0; border-bottom: 1px solid var(--line); }
1763      .quick-card:last-child { border-bottom: 0; }
1764      .side-jobs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
1765      .side-feature b { font-size: 17px; }
1766      .footer-nav { display: none; }
1767      .footer {
1768        padding: 16px;
1769        line-height: 1.7;
1770      }
1771    }
1772  </style><style data-gooood-home-auth-favorites>.gooood-auth-modal[hidden], .gooood-auth-toast[hidden], .gooood-auth-panel[hidden], .gooood-auth-social[hidden] { display: none !important; }
1773.gooood-auth-modal { align-items: flex-start; background: rgba(0,0,0,.38); display: flex; inset: 0; justify-content: center; padding: 90px 16px 24px; position: fixed; z-index: 12000; }
1774.gooood-auth-dialog { background: #fff; box-shadow: 0 8px 36px rgba(0,0,0,.2); max-width: 340px; padding: 30px; position: relative; width: 100%; }
1775.gooood-auth-dialog h2 { color: #222; font-size: 18px; font-weight: 400; margin: 0 0 28px; text-align: center; }
1776.gooood-auth-close { background: transparent; border: 0; color: #333; cursor: pointer; font-size: 24px; line-height: 1; opacity: .6; padding: 6px; position: absolute; right: 8px; top: 6px; }
1777.gooood-auth-field { display: block; margin: 0 0 14px; }
1778.gooood-auth-field span { display: none; }
1779.gooood-auth-field input, .gooood-auth-field select { background: #fff; border: 1px solid #dedede; border-radius: 0; box-sizing: border-box; font: inherit; height: 42px; padding: 0 11px; width: 100%; }
1780.gooood-auth-code-row { align-items: flex-start; display: grid; gap: 8px; grid-template-columns: minmax(0, 1fr) 104px; }
1781.gooood-auth-code-row .gooood-auth-field { margin-bottom: 14px; }
1782.gooood-auth-submit, .gooood-auth-wechat, .gooood-auth-code { background: #1268b3; border: 0; color: #fff; cursor: pointer; font: inherit; min-height: 42px; width: 100%; }
1783.gooood-auth-code { background: #555; font-size: 13px; white-space: nowrap; }
1784.gooood-auth-submit:disabled, .gooood-auth-wechat:disabled { cursor: progress; opacity: .65; }
1785.gooood-auth-submit:disabled, .gooood-auth-wechat:disabled, .gooood-auth-code:disabled { cursor: progress; opacity: .65; }
1786.gooood-auth-error, .gooood-auth-feedback { font-size: 13px; line-height: 1.5; margin: 0 0 14px; }
1787.gooood-auth-error { color: #b42318; }
1788.gooood-auth-feedback { color: #1268b3; }
1789.gooood-auth-hint { color: #555; font-size: 13px; line-height: 1.55; margin: 0 0 14px; }
1790.gooood-auth-method-toggle { background: transparent; border: 0; color: #1268b3; cursor: pointer; font: inherit; font-size: 13px; margin: -2px 0 14px; padding: 0; text-align: left; }
1791.gooood-auth-method-toggle:hover { text-decoration: underline; }
1792.gooood-auth-links { align-items: center; display: flex; justify-content: space-between; margin: 13px 0 0; }
1793.gooood-auth-links button { background: transparent; border: 0; color: #1268b3; cursor: pointer; font: inherit; font-size: 13px; padding: 0; text-align: left; }
1794.gooood-auth-links button + button { color: #666; text-align: right; }
1795.gooood-auth-links button:hover { text-decoration: underline; }
1796.gooood-auth-divider { align-items: center; color: #888; display: flex; font-size: 12px; gap: 12px; margin: 22px 0 16px; }
1797.gooood-auth-divider::before, .gooood-auth-divider::after { background: #e8e8e8; content: ''; flex: 1; height: 1px; }
1798.gooood-auth-wechat-mobile-guidance { background: #f5f8fa; border-left: 2px solid #9eb9cf; color: #5d6973; font-size: 13px; line-height: 1.55; margin: 0; padding: 10px 12px; }
1799.gooood-auth-toast { background: rgba(20,20,20,.92); bottom: 28px; color: #fff; font-size: 14px; left: 50%; max-width: calc(100vw - 32px); padding: 11px 18px; position: fixed; transform: translateX(-50%); z-index: 12001; }
1800.favorite-action.is-favorited { color: #1268b3 !important; }
1801.favorite-action.is-pending { opacity: .55; pointer-events: none; }
1802body.gooood-auth-open { overflow: hidden; }
1803
1804.gooood-auth-slot { align-items: center; display: inline-flex; position: relative; }
1805.gooood-auth-slot > a { align-items: center; color: var(--muted, #5f6f7d); cursor: pointer; display: inline-flex; min-height: 32px; }
1806.gooood-account { position: relative; }
1807.gooood-account-toggle { align-items: center; background: transparent; border: 0; color: #4f5c66; cursor: pointer; display: inline-flex; font: inherit; gap: 7px; justify-content: center; padding: 0; }
1808.gooood-account-avatar {
1809  background: #eef3f7;
1810  border: 1px solid rgba(0,0,0,.1);
1811  border-radius: 50%;
1812  display: block;
1813  flex: 0 0 auto;
1814  height: 32px;
1815  object-fit: cover;
1816  width: 32px;
1817}
1818.gooood-account-avatar--placeholder {
1819  background: radial-gradient(circle at 66% 34%, #f3d56b 0 12%, transparent 13%),
1820              radial-gradient(circle at 36% 38%, #78b5d8 0 18%, transparent 19%),
1821              radial-gradient(circle at 56% 68%, #66a96a 0 18%, transparent 19%),
1822              radial-gradient(circle at 70% 72%, #d06969 0 11%, transparent 12%),
1823              #eef6fc;
1824}
1825.gooood-account-name { display: none; }
1826.gooood-account-menu {
1827  background: #fff;
1828  border: 1px solid #e4e7e9;
1829  box-shadow: 0 10px 30px rgba(0,0,0,.14);
1830  display: none;
1831  min-width: 176px;
1832  padding: 7px 0;
1833  position: absolute;
1834  right: 0;
1835  top: calc(100% + 8px);
1836  z-index: 12100;
1837}
1838.gooood-account.is-open .gooood-account-menu { display: block; }
1839.gooood-account-menu a, .gooood-account-menu button {
1840  background: transparent;
1841  border: 0;
1842  box-sizing: border-box;
1843  color: #333;
1844  cursor: pointer;
1845  display: block;
1846  font: inherit;
1847  font-size: 13px;
1848  line-height: 1.4;
1849  padding: 9px 16px;
1850  text-align: left;
1851  text-decoration: none;
1852  white-space: nowrap;
1853  width: 100%;
1854}
1855.gooood-account-menu a:hover, .gooood-account-menu button:hover { background: #f4f6f7; color: #1268b3; }
1856.gooood-account-divider { border-top: 1px solid #e7e9eb; display: block; margin: 5px 0; }
1857.mobile-menu-tools [data-gooood-auth-slot="mobile"] { display: block; position: relative; }
1858.mobile-menu-tools [data-gooood-auth-slot="mobile"] > a { align-items: center; color: #fff; display: flex; gap: 4px; }
1859
1860@media (max-width: 767px) {
1861  .gooood-auth-modal { background: #fff; padding: 35px 16px 20px; }
1862  .gooood-auth-dialog { box-shadow: none; max-width: none; }
1863  .gooood-auth-code-row { grid-template-columns: minmax(0, 1fr) 96px; }
1864  .header-actions > .gooood-auth-slot { display: none !important; }
1865  .gooood-account--mobile { width: 100%; }
1866  .gooood-account--mobile .gooood-account-toggle { color: #fff; gap: 8px; justify-content: flex-start; width: 100%; }
1867  .gooood-account--mobile .gooood-account-avatar { height: 30px; width: 30px; }
1868  .gooood-account--mobile .gooood-account-name { display: inline; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1869  .gooood-account--mobile .gooood-account-menu { bottom: calc(100% + 8px); left: 0; right: auto; top: auto; width: min(240px, calc(100vw - 38px)); }
1870}
1871</style><style data-gooood-home-share>body.gooood-share-open { overflow: hidden; }
1872.header-actions > [data-gooood-page-share] { display: none !important; }
1873.share-action.is-open .share-icons-dropdown,
1874[data-gooood-page-share].is-open .action-dropdown { display: block !important; opacity: 1 !important; visibility: visible !important; transform: translateY(0) !important; }
1875.gooood-share-modal[hidden], .gooood-share-toast[hidden] { display: none !important; }
1876.gooood-share-modal { position: fixed; inset: 0; z-index: 10050; display: grid; place-items: center; padding: 20px; background: rgba(3,24,39,.58); }
1877.gooood-share-dialog { position: relative; width: min(340px, calc(100vw - 40px)); padding: 30px 28px 26px; border: 1px solid #d8d8d8; background: #fff; box-shadow: 0 24px 70px rgba(0,0,0,.22); color: #222; text-align: center; }
1878.gooood-share-dialog h2 { margin: 0 0 18px; font-size: 18px; line-height: 1.4; }
1879.gooood-share-dialog canvas { display: block; width: 200px; height: 200px; margin: 0 auto; }
1880.gooood-share-qr-title { margin: 14px 0; color: #666; font-size: 12px; line-height: 1.55; }
1881.gooood-share-manual-copy { display: block; box-sizing: border-box; width: 100%; min-height: 42px; margin: 0 0 14px; padding: 8px 10px; border: 1px solid #b8c1c8; color: #333; font-size: 12px; }
1882.gooood-share-manual-copy[hidden] { display: none; }
1883.gooood-share-close { position: absolute; top: 8px; right: 10px; border: 0; background: transparent; color: #777; font-size: 26px; cursor: pointer; }
1884.gooood-share-copy { min-height: 38px; padding: 0 18px; border: 1px solid #07344f; background: #07344f; color: #fff; cursor: pointer; }
1885.gooood-share-toast { position: fixed; left: 50%; bottom: 26px; z-index: 10060; transform: translateX(-50%); padding: 10px 16px; background: #07344f; color: #fff; box-shadow: 0 10px 28px rgba(0,0,0,.18); font-size: 13px; white-space: nowrap; }
1886@media (max-width: 767px) {
1887  .v10-candidate-header .site-header,
1888  .site-header[data-v10-fragment="header"] {
1889    z-index: 10030 !important;
1890    overflow: visible !important;
1891  }
1892  .v10-candidate-header .header-row,
1893  .site-header[data-v10-fragment="header"] .header-row,
1894  .v10-candidate-header .header-actions,
1895  .site-header[data-v10-fragment="header"] .header-actions {
1896    overflow: visible !important;
1897  }
1898  .v10-candidate-header .header-actions > [data-gooood-page-share],
1899  .site-header[data-v10-fragment="header"] .header-actions > [data-gooood-page-share],
1900  .header-actions > [data-gooood-page-share] { display: none !important; }
1901  .mobile-share,
1902  .user-field > .share-action {
1903    display: none !important;
1904  }
1905  .header-actions > .gooood-auth-slot {
1906    display: none !important;
1907  }
1908  .v10-candidate-header .header-actions > .header-search,
1909  .site-header[data-v10-fragment="header"] .header-actions > .header-search,
1910  .header-actions > .header-search {
1911    display: inline-flex !important;
1912  }
1913  .header-actions > .header-search .header-search-toggle {
1914    align-items: center !important;
1915    background: #fff !important;
1916    color: #333 !important;
1917    display: inline-flex !important;
1918    font-size: 13px !important;
1919    gap: 5px !important;
1920    height: 60px !important;
1921    justify-content: center !important;
1922    min-height: 60px !important;
1923    width: 76px !important;
1924  }
1925  .header-actions > .header-search .header-search-icon,
1926  .user-field > .search-action .header-search-icon {
1927    height: 15px !important;
1928    width: 15px !important;
1929  }
1930  .header-actions > .header-search .header-search-icon::after,
1931  .user-field > .search-action .header-search-icon::after {
1932    bottom: -3px !important;
1933    right: -5px !important;
1934    width: 7px !important;
1935  }
1936  .user-field {
1937    background: #fff !important;
1938    display: flex !important;
1939    height: 60px !important;
1940    position: fixed !important;
1941    right: 0 !important;
1942    top: 0 !important;
1943    width: 76px !important;
1944    z-index: 2000 !important;
1945  }
1946  .user-field > li:not(.search-action) {
1947    display: none !important;
1948  }
1949  .user-field > .search-action {
1950    display: flex !important;
1951    height: 60px !important;
1952    width: 76px !important;
1953  }
1954  .user-field > .search-action button {
1955    align-items: center !important;
1956    display: inline-flex !important;
1957    flex-direction: row-reverse !important;
1958    font-size: 13px !important;
1959    gap: 5px !important;
1960    height: 60px !important;
1961    justify-content: center !important;
1962    padding: 0 !important;
1963    width: 76px !important;
1964  }
1965  .mobile-menu-item > a,
1966  .mobile-menu-parent,
1967  .mobile-menu-tools a,
1968  .mobile-user-links button { font-size: 16px !important; }
1969  .mobile-submenu a,
1970  .dropdown-menu a { font-size: 14px !important; line-height: 42px !important; padding-left: 46px !important; }
1971  .header-actions > [data-gooood-page-share] {
1972    position: relative;
1973    z-index: 10046;
1974    pointer-events: auto;
1975    overflow: visible;
1976  }
1977  .header-actions > [data-gooood-page-share] > a {
1978    align-items: center;
1979    display: inline-flex;
1980    justify-content: center;
1981    min-height: 60px;
1982    width: 60px;
1983  }
1984  .header-actions > [data-gooood-page-share] > a::after { display: none !important; }
1985  [data-gooood-page-share] .action-dropdown {
1986    min-width: 184px;
1987    position: fixed;
1988    right: 0;
1989    top: 60px;
1990    z-index: 10047 !important;
1991    pointer-events: auto;
1992  }
1993  [data-gooood-page-share].is-open .action-dropdown {
1994    display: block !important;
1995    opacity: 1 !important;
1996    visibility: visible !important;
1997    transform: translateY(0) !important;
1998  }
1999  [data-gooood-share="wechat"],
2000  [data-gooood-share-legacy-wechat],
2001  .share-icon.wechat,
2002  .wechat-share-wrap,
2003  .wechat-control {
2004    display: none !important;
2005  }
2006  .share-action .share-icons-dropdown { gap: 7px; padding: 9px; }
2007  .share-action .share-icons-dropdown a { width: 28px; height: 28px; }
2008  .gooood-share-dialog { padding: 28px 20px 22px; }
2009}
2010/* step-share-g3-header-search-final */
2011@media (max-width: 991px) {
2012  .v10-candidate-header .header-actions > [data-gooood-page-share="1"],
2013  .site-header[data-v10-fragment="header"] .header-actions > [data-gooood-page-share="1"],
2014  [data-v10-fragment="header"] .header-actions > [data-gooood-page-share="1"] {
2015    display: none !important;
2016  }
2017  .v10-candidate-header .header-actions > .header-search,
2018  .site-header[data-v10-fragment="header"] .header-actions > .header-search,
2019  [data-v10-fragment="header"] .header-actions > .header-search {
2020    display: inline-flex !important;
2021  }
2022}
2023</style>
2024<style data-gooood-company-cases-top-ad-b-reservation>[data-gooood-company-cases-top-ad-b]{display:block;min-block-size:112px}@media(max-width:700px){[data-gooood-company-cases-top-ad-b]{min-block-size:301px}}</style>
2024<script data-gooood-company-cases-top-ad-b-widget data-gooood-company-cases-top-ad-b-inline>/* The single client implementation for <!-- gooood-company-cases:top-ad-b -->. */
2025;(function (window, document) {
2026  'use strict'
2027  var markerText = 'gooood-company-cases:top-ad-b'
2028  var hostSelector = '[data-gooood-company-cases-top-ad-b]'
2029  var styleId = 'gooood-company-cases-top-ad-b-style'
2030  var css = '.gooood-company-top-ad-b__featured>a:hover,.gooood-company-top-ad-b__results a:hover{color:#fff;text-decoration-color:#fff}.gooood-company-top-ad-b__company-panel--results .gooood-company-top-ad-b__featured{display:none}.gooood-company-top-ad-b{background:#0f3d68;color:#fff;display:grid;font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",sans-serif;grid-template-columns:66% 34%;height:112px;max-width:1100px;overflow:hidden;width:100%}.gooood-company-top-ad-b--results{height:150px}.gooood-company-top-ad-b__company-panel{background:linear-gradient(100deg,#174a80,#236aaa);display:grid;grid-template-columns:56% 44%;transition:background .2s}.gooood-company-top-ad-b__company-panel:hover{background:#286fad}.gooood-company-top-ad-b__company-panel--results{display:block}.gooood-company-top-ad-b__featured{background:linear-gradient(135deg,#0f3d68,#174a80);border-right:1px solid rgba(255,255,255,.22);padding:13px 15px;transition:background .2s}.gooood-company-top-ad-b__featured:hover{background:#174a80}.gooood-company-top-ad-b__featured h2{color:#fff;font-size:13px;line-height:1.2;margin:0 0 7px}.gooood-company-top-ad-b__loading{color:#d9ebf8;font-size:11px}.gooood-company-top-ad-b__featured>a{align-items:center;color:#fff;display:grid;gap:5px;grid-template-columns:minmax(0,1.05fr) minmax(0,1.45fr);line-height:1.15;text-decoration:none}.gooood-company-top-ad-b__featured>a+a{margin-top:7px}.gooood-company-top-ad-b__featured>a:hover>b{color:#fff;text-decoration-color:#fff;text-decoration-line:underline;text-underline-offset:2px}.gooood-company-top-ad-b__featured b{display:block;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gooood-company-top-ad-b__stats{display:grid;gap:3px;grid-template-columns:1.2fr .7fr .8fr;min-width:0}.gooood-company-top-ad-b__featured small{color:#d7e9f7;display:block;font-size:9px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gooood-company-top-ad-b__featured strong{color:#fff;display:block;font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gooood-company-top-ad-b__search{padding:13px 15px}.gooood-company-top-ad-b__search form{align-items:center;display:flex;height:100%;justify-content:center;margin:0}.gooood-company-top-ad-b__field{border-bottom:1px solid rgba(255,255,255,.92);display:flex;flex-direction:column;height:37px;justify-content:flex-end;max-width:310px;width:65%}.gooood-company-top-ad-b__field span{color:#d5e6f4;font-size:10px;line-height:1;margin-bottom:2px}.gooood-company-top-ad-b__field input{background:transparent;border:0;color:#fff;font:inherit;font-size:12px;height:17px;min-width:0;outline:0;padding:0;width:100%}.gooood-company-top-ad-b__field input::-webkit-search-cancel-button{filter:invert(1)}.gooood-company-top-ad-b__search form button{background:transparent;border:0;color:#fff;cursor:pointer;font:inherit;font-size:12px;font-weight:700;margin-left:14px;padding:5px 0;transition:color .2s}.gooood-company-top-ad-b__search form button:hover{color:#d5e6f4;text-decoration:underline;text-underline-offset:3px}.gooood-company-top-ad-b__result-head{align-items:center;color:#d9ebf8;display:flex;font-size:10px;justify-content:space-between;line-height:1;margin-bottom:8px}.gooood-company-top-ad-b__result-actions{align-items:center;display:flex;gap:8px}.gooood-company-top-ad-b__result-head button{background:transparent;border:0;color:#fff;cursor:pointer;font:inherit;font-size:10px;padding:0;text-decoration:underline;text-decoration-color:#fff}.gooood-company-top-ad-b__results{display:grid;gap:5px 1px;grid-template-columns:repeat(6,minmax(0,1fr))}.gooood-company-top-ad-b__results a{color:#fff;display:block;min-width:0;padding:2px 4px;text-align:center;text-decoration:none}.gooood-company-top-ad-b__results a:hover b{color:#fff;text-decoration-color:#fff;text-decoration-line:underline;text-underline-offset:2px}.gooood-company-top-ad-b__results b,.gooood-company-top-ad-b__results small{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.gooood-company-top-ad-b__results b{font-size:11px;font-weight:400}.gooood-company-top-ad-b__results small{color:#d8eaf6;font-size:10px;margin-top:2px}.gooood-company-top-ad-b__search>p{color:#d9ebf8;font-size:11px;margin:26px 0 0;text-align:center}.gooood-company-top-ad-b__actions{background:#1d5f99;display:grid;grid-template-columns:repeat(2,minmax(0,1fr))}.gooood-company-top-ad-b__actions a{color:#fff;display:block;padding:20px 10px;text-align:center;text-decoration:none;transition:background .2s}.gooood-company-top-ad-b__actions a+a{border-left:1px solid rgba(255,255,255,.22)}.gooood-company-top-ad-b__actions a:hover{background:#174a80}.gooood-company-top-ad-b__actions b,.gooood-company-top-ad-b__actions span,.gooood-company-top-ad-b__actions i{display:block}.gooood-company-top-ad-b__actions b{font-size:18px;line-height:1.2}.gooood-company-top-ad-b__actions span{color:#dcecf8;font-size:11px;margin-top:6px}.gooood-company-top-ad-b__actions i{font-size:11px;font-style:normal;margin-top:4px}@media(max-width:700px){.gooood-company-top-ad-b{display:block;height:auto;max-width:none;overflow:visible}.gooood-company-top-ad-b__company-panel{display:block}.gooood-company-top-ad-b__featured{border-bottom:1px solid rgba(255,255,255,.22);border-right:0;min-height:119px;padding:13px 14px}.gooood-company-top-ad-b__featured h2{font-size:14px;margin-bottom:9px}.gooood-company-top-ad-b__featured>a{gap:8px;grid-template-columns:minmax(105px,1fr) minmax(0,1.55fr)}.gooood-company-top-ad-b__featured>a+a{margin-top:9px}.gooood-company-top-ad-b__featured b{font-size:13px}.gooood-company-top-ad-b__featured small{font-size:10px}.gooood-company-top-ad-b__featured strong{font-size:12px}.gooood-company-top-ad-b__search{min-height:62px;padding:11px 14px}.gooood-company-top-ad-b__search form{justify-content:center}.gooood-company-top-ad-b__field{max-width:none;width:72%}.gooood-company-top-ad-b__search form button{margin-left:13px}.gooood-company-top-ad-b__results{grid-template-columns:repeat(3,minmax(0,1fr))}.gooood-company-top-ad-b__result-head{margin-bottom:9px}.gooood-company-top-ad-b__search:has(.gooood-company-top-ad-b__results){min-height:150px}.gooood-company-top-ad-b__actions{height:76px}.gooood-company-top-ad-b__actions a{padding:15px 6px}.gooood-company-top-ad-b__actions b{font-size:16px}.gooood-company-top-ad-b__actions span{font-size:10px;margin-top:4px}.gooood-company-top-ad-b__actions i{display:none}}'
2031
2032  var priorityCss = '.gooood-company-top-ad-b{background:transparent;column-gap:4px;grid-template-columns:25% calc(75% - 4px)}.gooood-company-top-ad-b--results{height:112px}.gooood-company-top-ad-b__company-panel{grid-template-columns:50% 50%}.gooood-company-top-ad-b__company-panel--results{display:grid}.gooood-company-top-ad-b__company-panel--results .gooood-company-top-ad-b__featured{display:block}.gooood-company-top-ad-b__actions{background:#0f3d68;display:block}.gooood-company-top-ad-b__actions a:first-child{background:#0f3d68;padding:21px 10px}.gooood-company-top-ad-b__actions a:first-child:hover{background:#092844}.gooood-company-top-ad-b__featured{background:#174a80}.gooood-company-top-ad-b__featured:hover{background:#10375f}.gooood-company-top-ad-b__search{background:#1d5f99}.gooood-company-top-ad-b__search:hover{background:#174a80}.gooood-company-top-ad-b__results{grid-template-columns:repeat(3,minmax(0,1fr))}.gooood-company-top-ad-b__company-panel--results .gooood-company-top-ad-b__search{background:#1d5f99}@media(max-width:700px){.gooood-company-top-ad-b--results{height:auto}.gooood-company-top-ad-b__company-panel--results{display:block}.gooood-company-top-ad-b__company-panel--results .gooood-company-top-ad-b__featured{display:block}.gooood-company-top-ad-b__actions{height:98px;margin-bottom:6px}.gooood-company-top-ad-b__actions a:first-child{height:98px;padding:17px 8px}.gooood-company-top-ad-b__actions a:first-child b{font-size:16px}.gooood-company-top-ad-b__actions a:first-child span,.gooood-company-top-ad-b__actions a:first-child i{display:block;font-size:11px}.gooood-company-top-ad-b__actions a:first-child span{margin-top:5px}.gooood-company-top-ad-b__actions a:first-child i{margin-top:2px}}'
2033  // Window media queries do not react when this widget is placed in a narrow
2034  // article side rail on a desktop viewport. This mirrors the existing mobile
2035  // layout whenever the widget host itself is narrow.
2036  var compactCss = '.gooood-company-top-ad-b--compact{display:block;height:auto;max-width:none;overflow:visible}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__company-panel{display:block}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__featured{border-bottom:1px solid rgba(255,255,255,.22);border-right:0;min-height:119px;padding:13px 14px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__featured h2{font-size:14px;margin-bottom:9px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__featured>a{gap:8px;grid-template-columns:minmax(105px,1fr) minmax(0,1.55fr)}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__featured>a+a{margin-top:9px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__featured b{font-size:13px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__featured small{font-size:10px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__featured strong{font-size:12px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__search{min-height:62px;padding:11px 14px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__search form{justify-content:center}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__field{max-width:none;width:72%}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__search form button{margin-left:13px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__results{grid-template-columns:repeat(3,minmax(0,1fr))}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__result-head{margin-bottom:9px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__search:has(.gooood-company-top-ad-b__results){min-height:150px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__actions{height:98px;margin-bottom:6px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__actions a{padding:15px 6px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__actions b{font-size:16px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__actions span{font-size:10px;margin-top:4px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__actions i{display:none}.gooood-company-top-ad-b--compact.gooood-company-top-ad-b--results{height:auto}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__company-panel--results{display:block}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__company-panel--results .gooood-company-top-ad-b__featured{display:block}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__actions a:first-child{height:98px;padding:17px 8px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__actions a:first-child b{font-size:16px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__actions a:first-child span,.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__actions a:first-child i{display:block;font-size:11px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__actions a:first-child span{margin-top:5px}.gooood-company-top-ad-b--compact .gooood-company-top-ad-b__actions a:first-child i{margin-top:2px}'
2037
2038  function ensureStyle () {
2039    if (document.getElementById(styleId)) return
2040    var style = document.createElement('style')
2041    style.id = styleId
2042    style.textContent = css + priorityCss + compactCss
2043    document.head.appendChild(style)
2044  }
2045  function text (value) { return String(value == null ? '' : value) }
2046  function displayName (value) { return text(value).split('|')[0].trim() || text(value) }
2047  function formatViews (value) { value = Number(value); return !isFinite(value) || value <= 0 ? '—' : value >= 10000 ? (value / 10000).toFixed(1) + '万' : String(Math.round(value)) }
2048  function companyUrl (item) { var value = text(item && item.url); return value.indexOf('/') === 0 ? value : '/company/' }
2049  function node (name, className, value) { var element = document.createElement(name); if (className) element.className = className; if (value != null) element.textContent = text(value); return element }
2050  function link (item, compact) {
2051    var a = node('a'); a.href = companyUrl(item); a.target = '_blank'; a.rel = 'noopener noreferrer'
2052    a.appendChild(node('b', '', displayName(item && item.name)))
2053    if (compact) { a.appendChild(node('small', '', formatViews(item && item.totalViews))); return a }
2054    var stats = node('span', 'gooood-company-top-ad-b__stats');
2055    [['网站阅读', formatViews(item && item.totalViews)], ['项目数', item && item.projectCount || '—'], ['均阅读', Number(item && item.projectCount) > 0 ? formatViews(Number(item.totalViews) / Number(item.projectCount)) : '—']].forEac
2055h(function (pair) { var part = node('span'), small = node('small', '', pair[0]), strong = node('strong', '', pair[1]); part.appendChild(small); part.appendChild(strong); stats.appendChild(part) })
2056    a.appendChild(stats); return a
2057  }
2058  function request (host, query) {
2059    // This is the established public component API. Keeping the B placement
2060    // in the query lets the same widget work wherever its WordPress marker is
2061    // rendered, without adding page-specific routes.
2062    var endpoint = host.getAttribute('data-gooood-company-cases-api-endpoint') || '/api/company/embed-cases'
2063    return fetch(endpoint + '?' + query, { credentials: 'same-origin', headers: { accept: 'application/json' } }).then(function (response) { if (!response.ok) throw Error('company-top-ad HTTP ' + response.status); return response.json() })
2064  }
2065  function syncCompactLayout (host, root) {
2066    root.classList.toggle('gooood-company-top-ad-b--compact', host.getBoundingClientRect().width <= 700)
2067  }
2068  function observeCompactLayout (host, root) {
2069    function sync () { syncCompactLayout(host, root) }
2070    sync()
2071    if (window.ResizeObserver) {
2072      var observer = new window.ResizeObserver(sync)
2073      observer.observe(host)
2074    } else window.addEventListener('resize', sync)
2075  }
2076  function mount (host) {
2077    if (host.getAttribute('data-mounted') === '1') return
2078    host.setAttribute('data-mounted', '1')
2079    var root = node('section', 'gooood-company-top-ad-b'), panel = node('section', 'gooood-company-top-ad-b__company-panel'), featured = node('section', 'gooood-company-top-ad-b__featured'), search = node('section', 'gooood-company-top-ad-b__search'), actions = node('nav', 'gooood-company-top-ad-b__actions')
2080    root.setAttribute('aria-label', '人气公司随机案例'); panel.setAttribute('aria-label', '公司案例'); search.setAttribute('aria-label', '公司案例搜索'); actions.setAttribute('aria-label', 'gooood 服务入口')
2081    featured.appendChild(node('h2', '', '人气公司随机案例')); var status = node('span', 'gooood-company-top-ad-b__loading', '正在加载案例…'); featured.appendChild(status)
2082    panel.appendChild(featured); panel.appendChild(search);
2083    [['文章项目推广', '中国与全球传播', '查看推广方案 →', 'https://www.gooood.cn/ad-article']].forEach(function (item) { var a = node('a'); a.href = item[3]; a.target = '_blank'; a.rel = 'noopener noreferrer'; a.appendChild(node('b', '', item[0])); a.appendChild(node('span', '', item[1])); a.appendChild(node('i', '', item[2])); actions.appendChild(a) })
2084    root.appendChild(actions); root.appendChild(panel); syncCompactLayout(host, root); host.appendChild(root); observeCompactLayout(host, root)
2085    var keyword = '', page = 1, hasMore = false
2086    function form () { search.replaceChildren(); var f = node('form'), label = node('label', 'gooood-company-top-ad-b__field'), hint = node('span', '', '输入公司名称'), input = node('input'); label.appendChild(hint); input.maxLength = 20; input.type = 'search'; input.setAttribute('aria-label', '输入公司名称'); input.value = keyword; input.addEventListener('input', function () { keyword = input.value }); var button = node('button', '', '搜索'); button.type = 'submit'; f.appendChild(label); label.appendChild(input); f.appendChild(button); f.addEventListener('submit', function (event) { event.preventDefault(); loadResults(1) }); search.appendChild(f) }
2087    function resultView (items, loading) { search.replaceChildren(); var head = node('div', 'gooood-company-top-ad-b__result-head'), label = node('span', '', loading ? '正在搜索…' : '搜索结果' + (items.length ? ' · 第 ' + page + ' 页' : '')), buttons = node('span', 'gooood-company-top-ad-b__result-actions'); head.appendChild(label); if (page > 1) { var previous = node('button', '', '上一页'); previous.type = 'button'; previous.addEventListener('click', function () { loadResults(page - 1) }); buttons.appendChild(previous) } if (hasMore) { var next = node('button', '', '下一页'); next.type = 'button'; next.addEventListener('click', function () { loadResults(page + 1) }); buttons.appendChild(next) } var restart = node('button', '', '重新搜索 ×'); restart.type = 'button'; restart.addEventListener('click', function () { keyword = ''; page = 1; hasMore = false; root.classList.remove('gooood-company-top-ad-b--results'); panel.classList.remove('gooood-company-top-ad-b__company-panel--results'); form() }); buttons.appendChild(restart); head.appendChild(buttons); search.appendChild(head); if (!loading && items.length) { var results = node('div', 'gooood-company-top-ad-b__results');
2087 items.forEach(function (item) { results.appendChild(link(item, true)) }); search.appendChild(results) } else if (!loading) search.appendChild(node('p', '', '没有找到匹配公司。')) }
2088    function loadResults (targetPage) { if (!text(keyword).trim()) return; page = targetPage; hasMore = false; root.classList.add('gooood-company-top-ad-b--results'); panel.classList.add('gooood-company-top-ad-b__company-panel--results'); resultView([], true); request(host, 'q=' + encodeURIComponent(text(keyword).trim()) + '&page=' + targetPage).then(function (payload) { page = Math.max(1, Number(payload.page) || targetPage); hasMore = Boolean(payload.hasMore); resultView(Array.isArray(payload.items) ? payload.items.slice(0, 6) : [], false) }).catch(function () { resultView([], false) }) }
2089    function loadFeatured (attempt) {
2090      request(host, 'placement=top-ad-b&_=' + Date.now()).then(function (payload) {
2091        var items = Array.isArray(payload.featured) ? payload.featured.slice(0, 2) : []
2092        if (!items.length && attempt < 3) {
2093          setTimeout(function () { loadFeatured(attempt + 1) }, 1200)
2094          return
2095        }
2096        featured.replaceChildren(node('h2', '', '人气公司随机案例'))
2097        items.forEach(function (item) { featured.appendChild(link(item, false)) })
2098        if (!items.length) featured.appendChild(node('span', 'gooood-company-top-ad-b__loading', '案例数据暂时不可用'))
2099      }).catch(function () {
2100        if (attempt < 3) {
2101          setTimeout(function () { loadFeatured(attempt + 1) }, 1200)
2102          return
2103        }
2104        status.textContent = '案例数据暂时不可用'
2105      })
2106    }
2107    form(); loadFeatured(0)
2108  }
2109  function mountAll (scope) { ensureStyle(); var hosts = []; if (scope && scope.nodeType === 1 && scope.matches && scope.matches(hostSelector)) hosts.push(scope); if (scope && scope.querySelectorAll) hosts = hosts.concat(Array.prototype.slice.call(scope.querySelectorAll(hostSelector))); hosts.forEach(mount) }
2110  function mountMarkers (scope) {
2111    if (!scope || !document.createTreeWalker) return
2112    var walker = document.createTreeWalker(scope, NodeFilter.SHOW_COMMENT), markers = [], current
2113    while ((current = walker.nextNode())) if (text(current.nodeValue).trim() === markerText) markers.push(current)
2114    markers.forEach(function (marker) {
2115      var host = document.createElement('div')
2116      host.setAttribute('data-gooood-company-cases-top-ad-b', '')
2117      host.setAttribute('aria-live', 'polite')
2118      marker.replaceWith(host)
2119      mount(host)
2120    })
2121  }
2122  function scan (scope) { mountMarkers(scope); mountAll(scope) }
2123  function observeMarkers () {
2124    if (!document.body || window.__goooodCompanyCasesTopAdBObserver) return
2125    window.__goooodCompanyCasesTopAdBObserver = new MutationObserver(function (records) {
2126      records.forEach(function (record) { Array.prototype.forEach.call(record.addedNodes, function (node) { scan(node) }) })
2127    })
2128    window.__goooodCompanyCasesTopAdBObserver.observe(document.body, { childList: true, subtree: true })
2129  }
2130  function start () { scan(document); observeMarkers() }
2131  window.__goooodCompanyCasesTopAdB = { mount: scan }
2132  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', start); else start()
2133})(window, document)
2134</script>
2134<style data-v10-archive-title>
2135    .v10-taxonomy-title {
2136      align-items: baseline;
2137      border-bottom: 1px solid #d8d8d8;
2138      display: flex;
2139      gap: 12px;
2140      margin: 0 10px 24px;
2141      padding-bottom: 14px;
2142    }
2143    .v10-taxonomy-title h1 {
2144      color: #111;
2145      font-size: 18px;
2146      font-weight: 700;
2147      line-height: 27px;
2148      margin: 0;
2149    }
2150    .v10-taxonomy-title span {
2151      color: #bbb;
2152      font-size: 12px;
2153      line-height: 17.1428px;
2154    }
2155    @media (max-width: 767px) {
2156      .v10-taxonomy-title {
2157        margin-left: 26px;
2158        margin-right: 26px;
2159      }
2160    }
2161  </style><meta name="description" content="gooood 资讯|News页面,整理建筑、景观、室内与设计领域的最新项目、文章、招聘和专题内容。"><meta name="robots" content="index,follow"><meta property="og:site_name" content="谷德设计网 - gooood"><meta property="og:title" content="资讯 - gooood"><meta property="og:description" content="gooood 资讯|News页面,整理建筑、景观、室内与设计领域的最新项目、文章、招聘和专题内容。"><meta property="og:type" content="website"><meta property="og:url" content="https://www.gooood.cn/category/news"><link rel="canonical" href="https://www.gooood.cn/category/news"><link rel="alternate" hreflang="zh-CN" href="https://www.gooood.cn/category/news"><link rel="alternate" hreflang="en" href="https://www.gooood.cn/en/category/news"><link rel="alternate" hreflang="x-default" href="https://www.gooood.cn/category/news"><meta name="gooood-preview-route" content="v10-home-full-page"></head>
2162<body>
2163<div class="site">
2164  <header class="site-header" data-v10-fragment="header">
2165    <div class="header-row">
2166      <button class="mobile-menu-toggle" type="button" aria-label="打开菜单" aria-controls="mobile-menu" aria-expanded="false">
2167        <span></span><span></span><span></span>
2168      </button>
2169      <a class="logo" href="/" aria-label="gooood">gooood</a>
2170      <nav class="nav" aria-label="主导航">
2171        <div class="nav-item"><a class="nav-link" href="/" data-zh="首页" data-en="Home">首页</a></div>
2172        <div class="nav-item has-dropdown">
2173          <a class="nav-link" href="/category/series" data-zh="专辑" data-en="Series">专辑</a>
2174          <div class="nav-dropdown">
2175            <a href="/category/series" data-zh="所有专辑" data-en="All Series">所有专辑</a>
2176            <a href="/category/series/gooood-interview" data-zh="访谈专辑" data-en="Interview">访谈专辑</a>
2177            <a href="/category/series/office-fact" data-zh="办公室真相" data-en="Office Fact">办公室真相</a>
2178            <a href="/category/series/under-35" data-zh="未满35岁创意人记录" data-en="Under 35">未满35岁创意人记录</a>
2179            <a href="/category/type/anniversary" data-zh="大周年" data-en="Anniversary">大周年</a>
2180            <a href="/category/series/everyone" data-zh="每个人" data-en="Everyone">每个人</a>
2181            <a href="/category/series/oversea" data-zh="在海外" data-en="Oversea">在海外</a>
2182            <a href="/category/series/topic" data-zh="日常深度+" data-en="Topic">日常深度+</a>
2183            <a href="/category/type/unbuilt" data-zh="未建成" data-en="Unbuilt">未建成</a>
2184            <a href="/category/series/material-and-detail" data-zh="材料与细部" data-en="Material and Detail">材料与细部</a>
2185            <a href="/category/series/gooood-idea" data-zh="想法专辑" data-en="gooood Idea">想法专辑</a>
2186            <a href="/category/series/ramble" data-zh="信步辑" data-en="Ramble">信步辑</a>
2187            <a href="/category/series/avant-garde" data-zh="先锋专辑" data-en="Avant-garde">先锋专辑</a>
2188            <a href="/category/series/we-work-for-mad" data-zh="We work for MAD" data-en="We work for MAD">We work for MAD</a>
2189            <a href="/category/series/other-series" data-zh="其他专辑" data-en="Other Series">其他专辑</a>
2190          </div>
2191        </div>
2192        <div class="nav-item has-dropdown">
2193          <a class="nav-link" href="/search" data-zh="分类" data-en="Type">分类</a>
2194          <div class="nav-dropdown">
2195            <a href="/category/type/architecture" data-zh="建筑" data-en="Architecture">建筑</a>
2196            <a href="/category/type/landscape" data-zh="景观" data-en="Landscape">景观</a>
2197            <a href="/category/type/design" data-zh="设计" data-en="Design">设计</a>
2198            <a href="/category/type/art" data-zh="艺术" data-en="Art">艺术</a>
2199            <a href="/category/news" data-zh="资讯" data-en="News">资讯</a>
2200            <a href="/category/type/archive" data-zh="合集" data-en="Archive">合集</a>
2201            <a href="/filter/type/all/country/all/material/all/office/all" data-zh="复合检索" data-en="Tag Search">复合检索</a>
2202          </div>
2203        </div>
2204        <div class="nav-item"><a class="nav-link" href="/aboutus" data-zh="关于谷德" data-en="About us">关于谷德</a></div>
2205        <div class="nav-item has-dropdown">
2206          <a class="nav-link" href="/submissions" data-zh="投稿与推广" data-en="Submissions &amp; AD">投稿与推广</a>
2207          <div class="nav-dropdown">
2208            <a href="/submissions" data-zh="投稿谷德" data-en="Submissions">投稿谷德</a>
2209            <a href="/ad-article" data-zh="文章推广" data-en="Article AD">文章推广</a>
2210            <a href="/materials" data-zh="建材推广" data-en="Materials">建材推广</a>
2211          </div>
2212        </div>
2213        <div class="nav-item has-dropdown">
2214          <a class="nav-link" href="/category/jobs" data-zh="工作/招聘" data-en="Jobs">工作/招聘</a>
2215          <div class="nav-dropdown">
2216            <a href="/category/jobs" data-zh="我是求职者!查看所有好工作" data-en="All jobs">我是求职者!查看所有好工作</a>
2217            <a href="/job-service-info" data-zh="我是雇主!如何发布好工作" data-en="Recruitment service">我是雇主!如何发布好工作</a>
2218          </div>
2219        </div>
2220        <div class="nav-item has-dropdown">
2221          <a class="nav-link" href="/find-designer" data-zh="设计师/找项目" data-en="Find designers / Get Projects">设计师/找项目</a>
2222          <div class="nav-dropdown">
2223            <a href="/find-designer" data-zh="业主找设计师" data-en="Find designers">业主找设计师</a>
2224            <a href="/get-project-designer" data-zh="设计师接项目" data-en="Get Projects">设计师接项目</a>
2225          </div>
2226        </div>
2227        <div class="nav-item"><a class="nav-link" href="/talks" data-zh="试听会员" data-en="Talks">试听会员</a></div>
2228      </nav>
2229      <div class="header-actions">
2230        <button type="button" data-lang-toggle data-zh="En" data-en="中">En</button>
2231        <div class="header-search">
2232          <button class="header-search-toggle" type="button" data-header-search-toggle aria-label="搜索" aria-expanded="false" aria-controls="header-search-panel"><span data-zh="搜索" data-en="Search">搜索</span><span class="header-search-icon" aria-hidden="true"></span></button>
2233          <div class="header-search-panel" id="header-search-panel" role="dialog" aria-modal="true" aria-label="搜索" hidden>
2234            <button class="header-search-backdrop" type="button" data-header-search-close aria-label="关闭搜索"></button>
2235            <div class="header-search-modal">
2236              <button class="header-search-close" type="button" data-header-search-close aria-label="关闭搜索">×</button>
2237              <form class="header-search-form" role="search" action="https://www.gooood.cn/search" method="get">
2238                <input type="search" name="q" id="search-on-modal" data-placeholder-zh="输入关键词进行全文搜索" data-placeholder-en="Enter keywords" placeholder="输入关键词进行全文搜索" autocomplete="off">
2239                <button type="submit" aria-label="搜索"><span class="header-search-icon" aria-hidden="true"></span></button>
2240              </form>
2241              <div class="header-search-tags">
2242                <h2 data-zh="您也可以根据标签进行检索" data-en="You can also filter post by featured tags">您也可以根据标签进行检索</h2>
2243                <div class="tags-group"><span data-zh="类型" data-en="Type">类型</span><a href="/category/type/architecture">Architecture</a><a href="/category/type/landscape">Landscape</a><a href="/category/type/design">Design</a><a href="/category/type/art">Art</a></div>
2244                <div class="tags-group"><span data-zh="服务" data-en="Service">服务</span><a href="/submissions">Submissions</a><a href="/ad-article">Article AD</a><a href="/job-service-info">Jobs</a></div>
2245              </div>
2246            </div>
2247          </div>
2248        </div>
2249        <div class="gooood-auth-slot" data-gooood-auth-slot="desktop">
2250          <a data-gooood-auth-member="desktop" data-gooood-login-trigger="1" href="#login" data-zh="会员/登录" data-en="VIP/Login">会员/登录</a>
2251        </div>
2252      </div>
2253    </div>
2254    <button class="mobile-menu-backdrop" type="button" aria-label="关闭菜单" hidden></button>
2255    <div class="mobile-menu" id="mobile-menu" hidden>
2256      <form class="mobile-search-form" role="search" action="https://www.gooood.cn/search" method="get">
2257        <input type="text" name="q" data-placeholder-zh="输入关键字搜索" data-placeholder-en="Enter keywords" placeholder="输入关键字搜索">
2258        <button type="submit" aria-label="搜索">⌕</button>
2259      </form>
2260      <ul class="mobile-menu-primary">
2261        <li class="mobile-menu-item"><a href="/" data-zh="首页" data-en="Home">首页</a></li>
2262        <li class="mobile-menu-item">
2263          <button class="mobile-menu-parent" type="button"><span data-zh="专辑" data-en="Series">
2263专辑</span><span class="caret"></span></button>
2264          <ul class="mobile-submenu">
2265            <li><a href="/category/series" data-zh="所有专辑" data-en="All Series">所有专辑</a></li>
2266            <li><a href="/category/series/gooood-interview" data-zh="访谈专辑" data-en="Interview">访谈专辑</a></li>
2267            <li><a href="/category/series/office-fact" data-zh="办公室真相" data-en="Office Fact">办公室真相</a></li>
2268            <li><a href="/category/series/under-35" data-zh="未满35岁创意人记录" data-en="Under 35">未满35岁创意人记录</a></li>
2269            <li><a href="/category/type/anniversary" data-zh="大周年" data-en="Anniversary">大周年</a></li>
2270            <li><a href="/category/series/everyone" data-zh="每个人" data-en="Everyone">每个人</a></li>
2271            <li><a href="/category/series/oversea" data-zh="在海外" data-en="Oversea">在海外</a></li>
2272            <li><a href="/category/series/topic" data-zh="日常深度+" data-en="Topic">日常深度+</a></li>
2273            <li><a href="/category/type/unbuilt" data-zh="未建成" data-en="Unbuilt">未建成</a></li>
2274            <li><a href="/category/series/material-and-detail" data-zh="材料与细部" data-en="Material and Detail">材料与细部</a></li>
2275            <li><a href="/category/series/gooood-idea" data-zh="想法专辑" data-en="gooood Idea">想法专辑</a></li>
2276            <li><a href="/category/series/ramble" data-zh="信步辑" data-en="Ramble">信步辑</a></li>
2277            <li><a href="/category/series/avant-garde" data-zh="先锋专辑" data-en="Avant-garde">先锋专辑</a></li>
2278            <li><a href="/category/series/we-work-for-mad" data-zh="We work for MAD" data-en="We work for MAD">We work for MAD</a></li>
2279            <li><a href="/category/series/other-series" data-zh="其他专辑" data-en="Other Series">其他专辑</a></li>
2280          </ul>
2281        </li>
2282        <li class="mobile-menu-item">
2283          <button class="mobile-menu-parent" type="button"><span data-zh="分类" data-en="Type">分类</span><span class="caret"></span></button>
2284          <ul class="mobile-submenu">
2285            <li><a href="/category/type/architecture" data-zh="建筑" data-en="Architecture">建筑</a></li>
2286            <li><a href="/category/type/landscape" data-zh="景观" data-en="Landscape">景观</a></li>
2287            <li><a href="/category/type/design" data-zh="设计" data-en="Design">设计</a></li>
2288            <li><a href="/category/type/art" data-zh="艺术" data-en="Art">艺术</a></li>
2289            <li><a href="/category/news" data-zh="资讯" data-en="News">资讯</a></li>
2290            <li><a href="/category/type/archive" data-zh="合集" data-en="Archive">合集</a></li>
2291            <li><a href="/filter/type/all/country/all/material/all/office/all" data-zh="复合检索" data-en="Tag Search">复合检索</a></li>
2292          </ul>
2293        </li>
2294        <li class="mobile-menu-item"><a href="/aboutus" data-zh="关于我们" data-en="About us">关于我们</a></li>
2295        <li class="mobile-menu-item">
2296          <button class="mobile-menu-parent" type="button"><span data-zh="投稿与推广" data-en="Submissions &amp; AD">投稿与推广</span><span class="caret"></span></button>
2297          <ul class="mobile-submenu">
2298            <li><a href="/submissions" data-zh="免费投稿" data-en="Submissions">免费投稿</a></li>
2299            <li><a href="/ad-article" data-zh="文章付费推广" data-en="Article AD">文章付费推广</a></li>
2300            <li><a href="/materials" data-zh="建材推广" data-en="Materials">建材推广</a></li>
2301          </ul>
2302        </li>
2303        <li class="mobile-menu-item">
2304          <button class="mobile-menu-parent" type="button"><span data-zh="工作/招聘" data-en="Jobs">工作/招聘</span><span class="caret"></span></button>
2305          <ul class="mobile-submenu">
2306            <li><a href="/category/jobs" data-zh="所有工作" data-en="All jobs">所有工作</a></li>
2307            <li><a href="/job-service-info" data-zh="发布招聘" data-en="Recruitment service">发布招聘</a></li>
2308          </ul>
2309        </li>
2310        <li class="mobile-menu-item">
2311          <button class="mobile-menu-parent" type="button"><span data-zh="找设计师/找项目" data-en="Find designers / Get Projects">找设计师/找项目</span><span class="caret"></span></button>
2312          <ul class="mobile-submenu">
2313            <li><a href="/find-designer" data-zh="业主找设计师" data-en="Find designers">业主找设计师</a></li>
2314            <li><a href="/get-project-designer" data-zh="设计师接项目" data-en="Get Projects">设计师接项目</a></li>
2315          </ul>
2316        </li>
2317        <li class="mobile-menu-item"><a href="/talks" data-zh="试听会员" data-en="Talks">试听会员</a></li>
2318        <li class="mobile-menu-item"><button type="button" data-lang-toggle data-zh="En" data-en="中">En</button></li>
2319      </ul>
2320      <ul class="mobile-menu-tools">
2321        <li data-gooood-auth-slot="mobile"><a href="#login" data-gooood-auth-member="mobile" data-gooood-login-trigger="1"><span class="mobile-user-icon">●</span><span data-zh="会员/登录" data-en="VIP/Login">会员/登录</span></a></li>
2322      </ul>
2323    </div>
2324  </header>
2324<script data-gooood-v10-lang-switch-fallback>(function(){
2325  if(window.__goooodV10LangSwitchFallback)return;
2326  window.__goooodV10LangSwitchFallback=true;
2327  function saveLanguage(value){
2328    var parts=['language='+encodeURIComponent(value),'Path=/','SameSite=Lax','Max-Age=31536000'];
2329    if(window.location.protocol==='https:')parts.push('Secure');
2330    if(window.location.hostname==='gooood.cn'||window.location.hostname.endsWith('.gooood.cn'))parts.push('Domain=.gooood.cn');
2331    document.cookie=parts.join('; ');
2332  }
2333  function targetPath(path,target){
2334    var normalized=path||'/';
2335    var clean=normalized==='/en'||normalized==='/en/'?'/':normalized.indexOf('/en/')===0?normalized.slice(3)||'/':normalized;
2336    if(target==='zh')return clean||'/';
2337    return clean==='/'?'/en/':'/en'+clean;
2338  }
2339  document.addEventListener('click',function(event){
2340    var trigger=event.target&&event.target.closest&&event.target.closest('[data-lang-toggle]');
2341    if(!trigger)return;
2342    var current=window.location.pathname==='/en'||window.location.pathname.indexOf('/en/')===0?'en':'zh';
2343    var target=current==='en'?'zh':'en';
2344    var url=new URL(window.location.href);
2345    url.pathname=targetPath(url.pathname,target);
2346    url.searchParams.delete('lang');
2347    saveLanguage(target==='en'?'en_US':'zh_CN');
2348    event.preventDefault();
2349    event.stopImmediatePropagation();
2350    window.location.assign(url.pathname+url.search+url.hash);
2351  },true);
2352})();</script>
2352
2353
2354  <div class="layout">
2355    <main class="main">
2356      <section class="top-slider" aria-label="首页轮播图广告" data-v10-fragment="carousel" data-ad-position="首页轮播图广告" data-wp-tag-id="34627" data-wp-term-slug="home_banners" data-ad-ratio="2000:600" data-ad-source="legacy-api:home_banners" data-backend-ad-position="34627" data-backend-ad-source="dashboard.api.api-advert-adposition.php?slugName=home_banners" data-backend-ad-status="connected" data-ad-item-count="6" data-ad-set-fingerprint="ea47907ae0d8dcf6" data-ad-source-fetched-at="2026-10-02T06:04:17.042Z" data-ad-cache-status="stale">
2357        <div class="slide is-active" data-ad-record-id="1725185" data-ad-slug="library-everyone-ppt" data-ad-modified="" data-ad-title="library-everyone" data-ad-fingerprint="fc7c92366ac341aa"><a class="slide-link" href="/everyone-beijing-city-library.htm" target="_blank" rel="noopener"><picture><source media="(max-width: 767px)" srcset="https://oss.gooood.cn/uploads/2026/09/library-%E6%8B%B7%E8%B4%9Dppt-768x230.jpg"><img src="https://oss.gooood.cn/uploads/2026/09/library-%E6%8B%B7%E8%B4%9Dppt.jpg" loading="eager" fetchpriority="high" alt="library-everyone" width="2000" height="600" decoding="async"></picture></a></div>
2358        <div class="slide" data-ad-record-id="1728618" data-ad-slug="office-fact-no-64-atelier-cns-ppt" data-ad-modified="" data-ad-title="OFFICE FACT NO.64 - Atelier cnS-ppt" data-ad-fingerprint="6cc93598fb3eb79c"><a class="slide-link" href="/office-fact-atelier-cns.htm" target="_blank" rel="noopener"><picture><source media="(max-width: 767px)" srcset="https://oss.gooood.cn/uploads/2026/09/cns-ppt-%E6%8B%B7%E8%B4%9D-768x230.jpg"><img data-src="https://oss.gooood.cn/uploads/2026/09/cns-ppt-%E6%8B%B7%E8%B4%9D.jpg" loading="lazy" fetchpriority="low" alt="OFFICE FACT NO.64 - Atelier cnS-ppt" width="2000" height="600" decoding="async"></picture></a></div>
2359        <div class="slide" data-ad-record-id="1721821" data-ad-slug="under-35-zhang-miaojie-ppt" data-ad-modified="" data-ad-title="under-35-zhang-miaojie-ppt" data-ad-fingerprint="5ce9a89d6c3c1809"><a class="slide-link" href="/under-35-zhang-miaojie.htm" target="_blank" rel="noopener"><picture><source media="(max-width: 767px)" srcset="https://oss.gooood.cn/uploads/2026/08/odd-ppt-%E6%8B%B7%E8%B4%9D-5j1-768x230.jpg"><img data-src="https://oss.gooood.cn/uploads/2026/08/odd-ppt-%E6%8B%B7%E8%B4%9D-5j1.jpg" loading="lazy" fetchpriority="low" alt="under-35-zhang-miaojie-ppt" width="2000" height="600" decoding="async"></picture></a></div>
2360        <div class="slide" data-ad-record-id="1681888" data-ad-slug="everyone-x-shenzhen-bay-cultural-square-mayansong-ppt" data-ad-modified="" data-ad-title="everyone-x-shenzhen-bay-cultural-square" data-ad-fingerprint="1a35e30b42d20d1f"><a class="slide-link" href="/everyone-x-shenzhen-bay-cultural-square.htm" target="_blank" rel="noopener"><picture><source media="(max-width: 767px)" srcset="https://oss.gooood.cn/uploads/2026/04/maysongmad-768x230.jpg"><img data-src="https://oss.gooood.cn/uploads/2026/04/maysongmad.jpg" loading="lazy" fetchpriority="low" alt="everyone-x-shenzhen-bay-cultural-square" width="2000" height="600" decoding="async"></picture></a></div>
2361        <div class="slide" data-ad-record-id="1714060" data-ad-slug="gooood-is-16-years-old-ppt" data-ad-modified="" data-ad-title="gooood is 16 years old!" data-ad-fingerprint="8203a6d353bc4e6f"><a class="slide-link" href="/gooood-happy-bday-16.htm" target="_blank" rel="noopener"><picture><source media="(max-width: 767px)" srcset="https://oss.gooood.cn/uploads/2026/07/happybirthday-ppt-768x230.jpg"><img data-src="https://oss.gooood.cn/uploads/2026/07/happybirthday-ppt.jpg" loading="lazy" fetchpriority="low" alt="gooood is 16 years old!" width="2000" height="600" decoding="async"></picture></a></div>
2362        <div class="slide" data-ad-record-id="1308764" data-ad-slug="preserving-twilight-shanghai-midnight-swim-craft-beer-bar-ppt" data-ad-modified="" data-ad-title="项目对接案例No.22:留住黄昏 - 上海夜游精酿店" data-ad-fingerprint="7da6fae4e2530878"><a class="slide-link" href="/get-project-case-preserving-twilight-midnight-swim-craft
2362-beer-bar-by-ka-design-lab.htm" target="_blank" rel="noopener"><picture><source media="(max-width: 767px)" srcset="https://oss.gooood.cn/uploads/2026/03/%E5%A4%9C%E6%B8%B8-KA-08-%E6%8B%B7%E8%B4%9D-3-768x230.jpg"><img data-src="https://oss.gooood.cn/uploads/2026/03/%E5%A4%9C%E6%B8%B8-KA-08-%E6%8B%B7%E8%B4%9D-3.jpg" loading="lazy" fetchpriority="low" alt="项目对接案例No.22:留住黄昏 - 上海夜游精酿店" width="2000" height="600" decoding="async"></picture></a></div>
2363        <div class="slider-controls"><button class="slider-btn" type="button" data-slide-prev aria-label="上一张">‹</button><button class="slider-btn" type="button" data-slide-next aria-label="下一张">›</button></div>
2364        <div class="top-slider-dots"><button class="is-active" type="button" data-slide-dot="0" aria-label="第 1 张"></button><button class="" type="button" data-slide-dot="1" aria-label="第 2 张"></button><button class="" type="button" data-slide-dot="2" aria-label="第 3 张"></button><button class="" type="button" data-slide-dot="3" aria-label="第 4 张"></button><button class="" type="button" data-slide-dot="4" aria-label="第 5 张"></button><button class="" type="button" data-slide-dot="5" aria-label="第 6 张"></button></div>
2365      </section>
2366
2367      <section class="ad-embed hero-below" aria-label="首页轮播图下方广告" data-v10-fragment="ad-34628" data-ad-position="首页轮播图下方广告" data-wp-tag-id="34628" data-wp-term-slug="home_list_0" data-backend-ad-position="34628" data-backend-ad-source="dashboard.api.api-advert-adposition.php?slugName=home_list_0" data-backend-ad-status="connected" data-ad-item-count="2" data-ad-record-id="1699563" data-ad-record-ids="1699563,346280001" data-ad-slug="top-ads" data-ad-modified="2026-08-21T14:08:20" data-ad-title="top ads ·" data-ad-href="#" data-ad-source="legacy-api:home_list_0" data-ad-fingerprint="343e3697f5d989c3" data-ad-set-fingerprint="dbff819325088d7f" data-ad-source-fetched-at="2026-10-02T06:04:17.285Z" data-ad-cache-status="stale" data-backend-ad-content="acf.ad_content"><div data-ad-record-id="1699563" style="display:contents"><p><span data-gooood-company-cases-top-ad-b aria-live="polite"></span></p></div><div data-ad-record-id="346280001" style="display:contents"><div class="job-text legacy-wordlink-jobs" data-legacy-ad-wordlink="1" data-wordlink-source="https://dashboard.gooood.cn/api/api-jobs-param.php?page=1&amp;pageSize=12" data-admin-setting="options_column_count" data-configured-count="4" data-rendered-count="12" style="margin:0 auto 30px;max-width:1100px"><div class="job-head"><b>最新工作</b><a class="job-submit" href="/job-service-info" target="_blank" rel="noopener">+提交新工作</a><a class="job-all" href="/category/jobs" target="_blank" rel="noopener">所有工作 →</a></div><div class="job-cols"><div class="job-col" data-admin-setting="options_column_count" data-configured-count="4"><a class="job-line" href="https://www.gooood.cn/jobs/job-mengarchitects" target="_blank" rel="noopener" data-backend-job-id="1731355" data-backend-job-slug="job-mengarchitects"><b>(深圳)MENG ARCHITECTS 孟建民团队 – 建筑设计师 / 助理研究员 / 商务经理</b><em></em></a><a class="job-line" href="https://www.gooood.cn/jobs/job-plat-asia" target="_blank" rel="noopener" data-backend-job-id="940077" data-backend-job-slug="job-plat-asia"><b>(北京)PLAT ASIA - 资深建筑师 / 中级建筑师 / 助理建筑师 / 建筑/景观实习生 / 景观设计师</b><em></em></a><a class="job-line" href="https://www.gooood.cn/jobs/job-cloud-seven" target="_blank" rel="noopener" data-backend-job-id="1730871" data-backend-job-slug="job-cloud-seven"><b>(上海)CLOUD7 云七建筑 - AI 设计师 / 中级建筑设计师 / 初级建筑设计师 / 室内设计师</b><em></em></a><a class="job-line" href="https://www.gooood.cn/jobs/job-bai-design-international" target="_blank" rel="noopener" data-backend-job-id="1500188" data-backend-job-slug="job-bai-design-international"><b>(北京)英国杰典国际建筑 - 资深建筑师 / 建筑师 / 助理建筑师&amp;应届毕业生 / 实习生 / 室内建筑师 / 媒体专员</b><em></em></a></div><div class="job-col" data-admin-setting="options_column_count" data-configured-count="4"><a class="job-line" href="https://www.gooood.cn/jobs/latest-20-companies-recruit-information-10" target="_blank" rel="noopener" data-backend-job-id="1636057" data-backend-job-slug="latest-20-companies-recruit-information-10"><b>最近有哪些好工作?谷德最新20家招聘信息汇总</b><em></em></a><a class="job-line" href="https://www.gooood.cn/jobs/job-youngdesign" target="_blank" rel="noopener" data-backend-job-id="1729522" data-backend-job-slug="job-youngdesign"><b>
2367(武汉)本样设计 YOUNGDESIGN - 设计总监 / 主案设计师 / 空间助理设计师</b><em></em></a><a class="job-line" href="https://www.gooood.cn/jobs/job-airwall-architecture-office" target="_blank" rel="noopener" data-backend-job-id="1617081" data-backend-job-slug="job-airwall-architecture-office"><b>(重庆)空气墙建筑工作室 AIRWALL ARCHITECTURE OFFICE - 方案设计师 / 助理设计师 / 设计实习生</b><em></em></a><a class="job-line" href="https://www.gooood.cn/jobs/job-voice-architecture-lab" target="_blank" rel="noopener" data-backend-job-id="1610416" data-backend-job-slug="job-voice-architecture-lab"><b>(上海)Voice Architecture Lab -  AI 设计师 / 中级建筑设计师 / 初级建筑设计师 / 室內设计师</b><em></em></a></div><div class="job-col" data-admin-setting="options_column_count" data-configured-count="4"><a class="job-line" href="https://www.gooood.cn/jobs/job-jz-lab" target="_blank" rel="noopener" data-backend-job-id="1408038" data-backend-job-slug="job-jz-lab"><b>(成都)介止商业设计 - 商业负责人 / 项目负责人 / 设计师 / 助理设计师 / 实习生</b><em></em></a><a class="job-line" href="https://www.gooood.cn/jobs/job-euv" target="_blank" rel="noopener" data-backend-job-id="1618237" data-backend-job-slug="job-euv"><b>(深圳)深圳易加设计(E+UV 工作室)- 建筑师 / 助理建筑师 / 实习生</b><em></em></a><a class="job-line" href="https://www.gooood.cn/jobs/job-pha" target="_blank" rel="noopener" data-backend-job-id="1154247" data-backend-job-slug="job-pha"><b>(深圳)PH Alpha Design 湃昂国际建筑设计顾问有限公司 – 高级建筑设计师 / 建筑设计师 / 主案设计师 / 室内设计师 / 商务经理</b><em></em></a><a class="job-line" href="https://www.gooood.cn/jobs/job-shiji" target="_blank" rel="noopener" data-backend-job-id="1558304" data-backend-job-slug="job-shiji"><b>(上海)拾集建筑 - 项目设计师 / 商务与媒体专员 / 商业软装设计师 / 助理设计师 / 实习生</b><em></em></a></div></div></div></div></section>
2368
2369      <section class="archive-title-row v10-taxonomy-title" aria-label="当前页面"><h1 data-zh="资讯" data-en="News">资讯</h1><span data-zh="最新文章" data-en="Latest Articles">最新文章</span></section><section class="row">
2370        <article class="article" data-v10-fragment="article" data-backend-post-id="1730182" data-backend-post-slug="goodone-future-timber-architecture-design-competition" data-backend-post-modified="" data-backend-post-fingerprint="06018ab02864a95c" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/goodone-future-timber-architecture-design-competition.htm" target="_blank" rel="noopener" aria-label="竞赛|“未来木构建筑设计竞赛”再起,刘家琨、董功、罗宇杰担任评委"><img src="https://oss.gooood.cn/uploads/2026/09/%E5%B0%81%E9%9D%A2%E7%94%A8-472x303.png" srcset="https://oss.gooood.cn/uploads/2026/09/%E5%B0%81%E9%9D%A2%E7%94%A8-472x303.png 472w, https://oss.gooood.cn/uploads/2026/09/%E5%B0%81%E9%9D%A2%E7%94%A8-650x417.png 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="竞赛|“未来木构建筑设计竞赛”再起,刘家琨、董功、罗宇杰担任评委" width="650" height="417" decoding="async" loading="eager" fetchpriority="high"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/goodone-future-timber-architecture-design-competition.htm" target="_blank" rel="noopener" data-zh="竞赛|“未来木构建筑设计竞赛”再起,刘家琨、董功、罗宇杰担任评委" data-en="竞赛|“未来木构建筑设计竞赛”再起,刘家琨、董功、罗宇杰担任评委">竞赛|“未来木构建筑设计竞赛”再起,刘家琨、董功、罗宇杰担任评委</a></h3><div class="article-subtitle" data-zh="" data-en=""></div><div class="article-foot"><time datetime="2026-09-29T08:30:37">2026.09.29</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2371        <article class="article" data-v10-fragment="article" data-backend-p
2371ost-id="1730153" data-backend-post-slug="the-seventh-half-stage-exhibition-structuring-fragments-opens" data-backend-post-modified="" data-backend-post-fingerprint="71fa6f5b6737c817" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/the-seventh-half-stage-exhibition-structuring-fragments-opens.htm" target="_blank" rel="noopener" aria-label="半场第七场展览《片段与结构之间》开幕"><img src="https://oss.gooood.cn/uploads/2026/09/0-the-seventh-half-stage-exhibition-structuring-fragments-opens-472x303.jpg" srcset="https://oss.gooood.cn/uploads/2026/09/0-the-seventh-half-stage-exhibition-structuring-fragments-opens-472x303.jpg 472w, https://oss.gooood.cn/uploads/2026/09/0-the-seventh-half-stage-exhibition-structuring-fragments-opens-650x417.jpg 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="半场第七场展览《片段与结构之间》开幕" width="650" height="417" decoding="async" loading="lazy" fetchpriority="low"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/the-seventh-half-stage-exhibition-structuring-fragments-opens.htm" target="_blank" rel="noopener" data-zh="半场第七场展览《片段与结构之间》开幕" data-en="The Seventh “HALF STAGE” Exhibition, Structuring Fragments, Opens">半场第七场展览《片段与结构之间》开幕</a></h3><div class="article-subtitle" data-zh="“关系的结构”与 “物质的结构”" data-en="“关系的结构”与 “物质的结构”">“关系的结构”与 “物质的结构”</div><div class="article-foot"><time datetime="2026-09-24T11:49:34">2026.09.24</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2372      </section>
2373      <section class="row">
2374        <article class="article" data-v10-fragment="article" data-backend-post-id="1724037" data-backend-post-slug="grand-opening-suzhou-contemporary-art-museum-officially-open-to-the-public" data-backend-post-modified="" data-backend-post-fingerprint="67b2a5a579808251" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/grand-opening-suzhou-contemporary-art-museum-officially-open-to-the-public.htm" target="_blank" rel="noopener" aria-label="盛大启幕:苏州当代美术馆正式向公众开放"><img src="https://oss.gooood.cn/uploads/2026/09/01-grand-opening-suzhou-contemporary-art-museum-officially-open-to-the-public-472x303.jpg" srcset="https://oss.gooood.cn/uploads/2026/09/01-grand-opening-suzhou-contemporary-art-museum-officially-open-to-the-public-472x303.jpg 472w, https://oss.gooood.cn/uploads/2026/09/01-grand-opening-suzhou-contemporary-art-museum-officially-open-to-the-public-650x417.jpg 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="盛大启幕:苏州当代美术馆正式向公众开放" width="650" height="417" decoding="async" loading="lazy" fetchpriority="low"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/grand-opening-suzhou-contemporary-art-museum-officially-open-to-the-public.htm" target="_blank" rel="noopener" data-zh="盛大启幕:苏州当代美术馆正式向公众开放" data-en="Grand Opening: Suzhou Contemporary Art Museum Officially Opens to the Public">盛大启幕:苏州当代美术馆正式向公众开放</a></h3><div class="article-subtitle" data-zh="成为连接城市与湖泊的纽带" data-en="成为连接城市与湖泊的纽带">成为连接城市与湖泊的纽带</div><div class="article-foot"><time datetime="2026-09-04T10:21:19">2026.09.04</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2375        <article class="article" data-v10-fragment="article" data-backend-post-id="1715537" data-backend-p
2375ost-slug="bihailou-art-village-by-mvrdv" data-backend-post-modified="" data-backend-post-fingerprint="0bb0bbcdc3009b59" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/bihailou-art-village-by-mvrdv.htm" target="_blank" rel="noopener" aria-label="由MVRDV设计的深圳碧海楼艺术村正式开工"><img src="https://oss.gooood.cn/uploads/2026/08/02-bihailou-art-village-by-mvrdv-472x303.jpg" srcset="https://oss.gooood.cn/uploads/2026/08/02-bihailou-art-village-by-mvrdv-472x303.jpg 472w, https://oss.gooood.cn/uploads/2026/08/02-bihailou-art-village-by-mvrdv-650x417.jpg 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="由MVRDV设计的深圳碧海楼艺术村正式开工" width="650" height="417" decoding="async" loading="lazy" fetchpriority="low"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/bihailou-art-village-by-mvrdv.htm" target="_blank" rel="noopener" data-zh="由MVRDV设计的深圳碧海楼艺术村正式开工" data-en="Bihailou Art Village by MVRDV">由MVRDV设计的深圳碧海楼艺术村正式开工</a></h3><div class="article-subtitle" data-zh="属于艺术家的“垂直村落”" data-en="属于艺术家的“垂直村落”">属于艺术家的“垂直村落”</div><div class="article-foot"><time datetime="2026-08-06T11:20:45">2026.08.06</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2376      </section>
2377
2378      <section class="ad-embed home-list-4-ad" data-v10-fragment="ad-34629" data-ad-position="首页第 4 篇文章后广告" data-wp-tag-id="34629" data-wp-term-slug="home_list_4" data-backend-ad-position="34629" data-backend-ad-source="dashboard.api.api-advert-adposition.php?slugName=home_list_4" data-backend-ad-status="connected" data-ad-item-count="1" data-ad-record-id="1719764" data-ad-record-ids="1719764" data-ad-slug="homepage-top-3-buttor" data-ad-modified="" data-ad-title="首页上部3按钮广告" data-ad-href="/advertisement/homepage-top-3-buttor" data-ad-source="legacy-api:home_list_4" data-ad-fingerprint="c2c5a37f7816dccb" data-ad-set-fingerprint="e93244b40c4bf2e8" data-ad-source-fetched-at="2026-10-02T06:04:17.067Z" data-ad-cache-status="stale" data-backend-ad-content="acf.ad_content"><div data-ad-record-id="1719764" style="display:contents">&nbsp;
2379<style>._eOwner,._eDesigner,._eMaterial{transition:all 0.2s ease;line-height:1.2!important}._eOwner:hover{background:#092844!important}._eDesigner:hover{background:#10375f!important}._eMaterial:hover{background:#174a80!important}._eRow td{vertical-align:top!important}._eTitle,._eDesc,._eAction{display:block!important;line-height:1.22!important}._eBtn{display:flex!important;width:100%!important;height:auto!important;min-height:0!important;aspect-ratio:700/449;padding:24px 12px!important;box-sizing:border-box!important;flex-direction:column!important;align-items:center!important;justify-content:center!important}@media(max-width:600px){._eRow td{display:block!important;width:100%!important;padding:0 0 6px!important;box-sizing:border-box!important}._eBtn{height:98px!important;min-height:98px!important;aspect-ratio:auto!important;padding:17px 8px!important}._eTitle{font-size:15px!important}._eDesc,._eAction{font-size:11px!important}}</style>
2380<table style="max-width: 1100px; margin: 0 auto 30px; table-layout: fixed;" border="0" width="100%" cellspacing="0" cellpadding="0">
2381<tbody>
2382<tr class="_eRow">
2383<td style="padding-right: 12.667px;" width="33.333%"><a class="_eOwner _eBtn" style="display: flex; width: 100%; height: auto; aspect-ratio: 700 / 449; padding: 24px 12px; background: #0f3d68; color: #fff; text-align: center; text-decoration: none; font-weight: bold; box-sizing: border-box; line-height: 1.2!important; flex-direction: column; align-items: center; justify-content: center;" href="https://gooood.mike-x.com/22mtJ" target="_blank" rel="noopener noreferrer"><span class="_eTitle" style="display: block; color: #fff; font-size: 19px; font-weight: bold; line-height: 1.22!important;">业 主 找 设 计 师</span><span class="_eDesc" style="display: block; padding-top: 6px; color: #dce8f2; font-size: 13px; font-weight: 400; line-height: 1.22!important;">真实项目需求</span><span class="_eAction" style="display: block; padding-top: 2px; color: #fff; font-size: 13px; font-weight: 400; line-height: 1.22!important;">提交项目 →</span></a></td>
2384<td style="padding: 0 6.333px;" width="33.333%"><a class="_eDesigner _eBtn" style="display: flex; width: 100%; height: auto; aspect-ratio: 700 / 449; padding: 24px 12px; background: #174a80; color: #fff; text-align: center; text-decoration: none; font-weight: bold; box-sizing: border-box; line-height: 1.2!important; flex-direction: column; align-items: center; justify-content: center;" href="https://gooood.mike-x.com/i5usj" target="_blank" rel="noopener noreferrer"><span class="_eTitle" style="display: block; color: #fff; font-size: 19px; font-weight: bold; line-height: 1.22!important;">设 计 师 接 项 目</span><span class="_eDesc" style="display: block; padding-top: 6px; color: #dce8f2; font-size: 13px; font-weight: 400; line-height: 1.22!important;">在线项目</span><span class="_eAction" style="display: block; padding-top: 2px; color: #dce8f2; font-size: 13px; font-weight: 400; line-height: 1.22!important;">查看机会 →</span></a></td>
2385<td style="padding-left: 12.667px;" width="33.333%"><a class="_eMaterial _eBtn" style="display: flex; width: 100%; height: auto; aspect-ratio: 700 / 449; padding: 24px 12px; background: #1d5f99; color: #fff; text-align: center; text-decoration: none; font-weight: bold; box-sizing: border-box; line-height: 1.2!important; flex-direction: column; align-items: center; justify-content: center;" href="/materials" target="_blank" rel="noopener noreferrer"><span class="_eTitle" style="display: block; color: #fff; font-size: 19px; font-weight: bold; line-height: 1.22!important;">建 材 品 牌 推 广</span><span class="_eDesc" style="display: block; padding-top: 6px; color: #dce8f2; font-size: 13px; font-weight: 400; line-height: 1.22!important;">品牌展示 · 项目选材</span><span class="_eAction" style="display: block; padding-top: 2px; color: #dce8f2; font-size: 13px; font-weight: 400; line-height: 1.22!important;">进入材料库 →</span></a></td>
2386</tr>
2387</tbody>
2388</table>
2389&nbsp;</div></section>
2390
2391      
2392
2393      <section class="row">
2394        <article class="article" data-v10-fragment="article" data-backend-p
2394ost-id="1713780" data-backend-post-slug="half-stage-opens-its-sixth-exhibition-investigate-things-anew-the-use-and-being-of-industrial-objects" data-backend-post-modified="" data-backend-post-fingerprint="cedcd51c86cf67c0" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/half-stage-opens-its-sixth-exhibition-investigate-things-anew-the-use-and-being-of-industrial-objects.htm" target="_blank" rel="noopener" aria-label="“半场”第六场展览《格物新议:工业物的用与在》开幕"><img src="https://oss.gooood.cn/uploads/2026/07/0-vaj-472x303.jpg" srcset="https://oss.gooood.cn/uploads/2026/07/0-vaj-472x303.jpg 472w, https://oss.gooood.cn/uploads/2026/07/0-vaj-650x417.jpg 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="“半场”第六场展览《格物新议:工业物的用与在》开幕" width="472" height="303" decoding="async" loading="lazy" fetchpriority="low"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/half-stage-opens-its-sixth-exhibition-investigate-things-anew-the-use-and-being-of-industrial-objects.htm" target="_blank" rel="noopener" data-zh="“半场”第六场展览《格物新议:工业物的用与在》开幕" data-en="“HALF STAGE” Opens Its Sixth Exhibition, Investigate Things Anew: The Use and Being of Industrial Objects">“半场”第六场展览《格物新议:工业物的用与在》开幕</a></h3><div class="article-subtitle" data-zh="工业物的“用”与“在”" data-en="工业物的“用”与“在”">工业物的“用”与“在”</div><div class="article-foot"><time datetime="2026-07-30T17:06:39">2026.07.30</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2395        <article class="article" data-v10-fragment="article" data-backend-post-id="1713021" data-backend-post-slug="z8-tower-construction-to-begin-by-zaha-hadid-architects" data-backend-post-modified="" data-backend-post-fingerprint="98511214ba1b6940" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/z8-tower-construction-to-begin-by-zaha-hadid-architects.htm" target="_blank" rel="noopener" aria-label="ZHA建筑事务所设计的Z8地块项目即将开工"><img src="https://oss.gooood.cn/uploads/2026/07/00-Z8-Tower-construction-to-begin-472x303.jpg" srcset="https://oss.gooood.cn/uploads/2026/07/00-Z8-Tower-construction-to-begin-472x303.jpg 472w, https://oss.gooood.cn/uploads/2026/07/00-Z8-Tower-construction-to-begin-650x417.jpg 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="ZHA建筑事务所设计的Z8地块项目即将开工" width="472" height="303" decoding="async" loading="lazy" fetchpriority="low"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/z8-tower-construction-to-begin-by-zaha-hadid-architects.htm" target="_blank" rel="noopener" data-zh="ZHA建筑事务所设计的Z8地块项目即将开工" data-en="Z8 Tower construction to begin by Zaha Hadid Architects">ZHA建筑事务所设计的Z8地块项目即将开工</a></h3><div class="article-subtitle" data-zh="高效互联的 “垂直都会”" data-en="高效互联的 “垂直都会”">高效互联的 “垂直都会”</div><div class="article-foot"><time datetime="2026-07-29T09:18:37">2026.07.29</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2396      </section>
2397
2398      <section class="row">
2399        <article class="article" data-v10-fragment="article" data-backend-post-id="1712748" data-backend-post-slug="tashkent-s-modernist-architecture-uzbekistan" data-backend-post-modified="" data-backend-post-fingerprint="eab323956d6c5731" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/tashkent-s-modernist-architecture-uzbekistan.htm" target="_blank" rel="noopener" aria-label="塔什干现代主义建筑列入《世界遗产名录》"><img src="https://oss.gooood.cn/uploads/2026/07/00-Tashkent-s-Modernist-Architecture-Uzbekistan-472x303.jpg" srcset="https://oss.gooood.cn/uploads/2026/07/00-Tashkent-s-Modernist-Architecture-Uzbekistan-472x303.jpg 472w, https://oss.gooood.cn/uploads/2026/07/00-Tashkent-s-Modernist-Architecture-Uzbekistan-650x417.jpg 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="塔什干现代主义建筑列入《世界遗产名录》" width="472" height="303" decoding="async" loading="lazy" fetchpriority="low"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/tashkent-s-modernist-architecture-uzbekistan.htm" target="_blank" rel="noopener" data-zh="塔什干现代主义建筑列入《世界遗产名录》" data-en="Tashkent's Modernist Architecture, Uzbekistan">塔什干现代主义建筑列入《世界遗产名录》</a></h3><div class="article-subtitle" data-zh="十座列入联合国教科文组织世界遗产名录的地标性建筑" data-en="十座列入联合国教科文组织世界遗产名录的地标性建筑">十座列入联合国教科文组织世界遗产名录的地标性建筑</div><div class="article-foot"><time datetime="2026-07-28T15:02:04">2026.07.28</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2400        <article class="article" data-v10-fragment="article" data-backend-p
2400ost-id="1709762" data-backend-post-slug="vital-architecture-atelier-li-xinggang-in-barcelona" data-backend-post-modified="" data-backend-post-fingerprint="d1a0683bcc6597bf" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/vital-architecture-atelier-li-xinggang-in-barcelona.htm" target="_blank" rel="noopener" aria-label="“生境建筑Vital Architecture: Atelier Li Xinggang”巴塞罗那展及开幕学术活动成功举办"><img src="https://oss.gooood.cn/uploads/2026/07/02-vital-architecture-atelier-li-xinggang-in-barcelona-472x303.jpg" srcset="https://oss.gooood.cn/uploads/2026/07/02-vital-architecture-atelier-li-xinggang-in-barcelona-472x303.jpg 472w, https://oss.gooood.cn/uploads/2026/07/02-vital-architecture-atelier-li-xinggang-in-barcelona-650x417.jpg 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="“生境建筑Vital Architecture: Atelier Li Xinggang”巴塞罗那展及开幕学术活动成功举办" width="472" height="303" decoding="async" loading="lazy" fetchpriority="low"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/vital-architecture-atelier-li-xinggang-in-barcelona.htm" target="_blank" rel="noopener" data-zh="“生境建筑Vital Architecture: Atelier Li Xinggang”巴塞罗那展及开幕学术活动成功举办" data-en="“Vital Architecture: Atelier Li Xinggang” Barcelona Exhibition and Opening Event Successfully Held">“生境建筑Vital Architecture: Atelier Li Xinggang”巴塞罗那展及开幕学术活动成功举办</a></h3><div class="article-subtitle" data-zh="以当代性的设计回应当下全球化的生存与生活挑战" data-en="以当代性的设计回应当下全球化的生存与生活挑战">以当代性的设计回应当下全球化的生存与生活挑战</div><div class="article-foot"><time datetime="2026-07-20T11:24:51">2026.07.20</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2401      </section>
2402      <section class="ad-embed materials-ad" data-v10-fragment="ad-34630" data-ad-position="首页第 8 篇文章后" data-wp-tag-id="34630" data-wp-term-slug="home_list_8" data-backend-ad-position="34630" data-backend-ad-source="dashboard.api.api-advert-adposition.php?slugName=home_list_8" data-backend-ad-status="empty" data-ad-item-count="0" data-ad-source="legacy-api:home_list_8" data-ad-set-fingerprint="811c9dc59e3779b9" data-ad-source-fetched-at="2026-10-02T06:04:17.052Z" data-ad-cache-status="stale" hidden aria-hidden="true"></section>
2403      <section class="row">
2404        <article class="article" data-v10-fragment="article" data-backend-post-id="1707711" data-backend-post-slug="architectures-inscriptions-exhibition-opens-at-tank-shanghai" data-backend-post-modified="" data-backend-post-fingerprint="60a631cf5f766053" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/architectures-inscriptions-exhibition-opens-at-tank-shanghai.htm" target="_blank" rel="noopener" aria-label="展览“建筑的铭写”于上海油罐艺术中心开幕"><img src="https://oss.gooood.cn/uploads/2026/07/00-Architectures-Inscriptions-Exhibition-Opens-at-Tank-Shanghai-472x303.jpg" srcset="https://oss.gooood.cn/uploads/2026/07/00-Architectures-Inscriptions-Exhibition-Opens-at-Tank-Shanghai-472x303.jpg 472w, https://oss.gooood.cn/uploads/2026/07/00-Architectures-Inscriptions-Exhibition-Opens-at-Tank-Shanghai-650x417.jpg 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="展览“建筑的铭写”于上海油罐艺术中心开幕" width="472" height="303" decoding="async" loading="lazy" fetchpriority="low"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/architectures-inscriptions-exhibition-opens-at-tank-shanghai.htm" target="_blank" rel="noopener" data-zh="展览“建筑的铭写”于上海油罐艺术中心开幕" data-en="Architecture's Inscriptions Exhibition Opens at Tank Shanghai">展览“建筑的铭写”于上海油罐艺术中心开幕</a></h3><div class="article-subtitle" data-zh="在“铭写”中重构过去与未æ
2404¥" data-en="在“铭写”中重构过去与未来">在“铭写”中重构过去与未来</div><div class="article-foot"><time datetime="2026-07-14T14:25:41">2026.07.14</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2405        <article class="article" data-v10-fragment="article" data-backend-post-id="1707158" data-backend-post-slug="the-2026-european-prize-for-urban-public-space-announces-the-25-shortlisted-projects" data-backend-post-modified="" data-backend-post-fingerprint="f777d908f49e249c" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/the-2026-european-prize-for-urban-public-space-announces-the-25-shortlisted-projects.htm" target="_blank" rel="noopener" aria-label="2026欧洲城市公共空间奖公布25个入围项目"><img src="https://oss.gooood.cn/uploads/2026/07/%E8%B5%84%E8%AE%AF%E7%B1%BB%E6%96%87%E7%AB%A0%E5%B0%81%E9%9D%A2-472x303.png" srcset="https://oss.gooood.cn/uploads/2026/07/%E8%B5%84%E8%AE%AF%E7%B1%BB%E6%96%87%E7%AB%A0%E5%B0%81%E9%9D%A2-472x303.png 472w, https://oss.gooood.cn/uploads/2026/07/%E8%B5%84%E8%AE%AF%E7%B1%BB%E6%96%87%E7%AB%A0%E5%B0%81%E9%9D%A2-650x417.png 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="2026欧洲城市公共空间奖公布25个入围项目" width="472" height="303" decoding="async" loading="lazy" fetchpriority="low"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/the-2026-european-prize-for-urban-public-space-announces-the-25-shortlisted-projects.htm" target="_blank" rel="noopener" data-zh="2026欧洲城市公共空间奖公布25个入围项目" data-en="The 2026 European Prize for Urban Public Space Announces the 25 Shortlisted Projects">2026欧洲城市公共空间奖公布25个入围项目</a></h3><div class="article-subtitle" data-zh="以公共空间回应气候、生态与社会挑战" data-en="以公共空间回应气候、生态与社会挑战">以公共空间回应气候、生态与社会挑战</div><div class="article-foot"><time datetime="2026-07-13T12:20:29">2026.07.13</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2406      </section>
2407      <section class="row">
2408        <article class="article" data-v10-fragment="article" data-backend-post-id="1679499" data-backend-post-slug="materials-information" data-backend-post-modified="" data-backend-post-fingerprint="c0a3ac6f3715e523" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/materials-information.htm" target="_blank" rel="noopener" aria-label="聚优质建材,赋设计灵感|找建材,来谷德!"><img src="https://oss.gooood.cn/uploads/2026/04/%E6%9D%90%E6%96%99%E5%B0%81%E9%9D%A2--472x303.jpg" srcset="https://oss.gooood.cn/uploads/2026/04/%E6%9D%90%E6%96%99%E5%B0%81%E9%9D%A2--472x303.jpg 472w, https://oss.gooood.cn/uploads/2026/04/%E6%9D%90%E6%96%99%E5%B0%81%E9%9D%A2--650x417.jpg 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="聚优质建材,赋设计灵感|找建材,来谷德!" width="472" height="303" decoding="async" loading="lazy" fetchpriority="low"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/materials-information.htm" target="_blank" rel="noopener" data-zh="聚优质建材,赋设计灵感|找建材,来谷德!" data-en="Materials information">聚优质建材,赋设计灵感|找建材,来谷德!</a></h3><div class="article-subtitle" data-zh="" data-en=""></div><div class="article-foot"><time datetime="2026-07-06T16:00:23">2026.07.06</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2409        <article class="article" data-v10-fragment="article" data-backend-p
2409ost-id="1703682" data-backend-post-slug="uia-world-congress-of-architects-2026-barcelona" data-backend-post-modified="" data-backend-post-fingerprint="92a94bf8e5b649b4" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/uia-world-congress-of-architects-2026-barcelona.htm" target="_blank" rel="noopener" aria-label="2026巴塞罗那UIA世界建筑师大会"><img src="https://oss.gooood.cn/uploads/2026/07/UIA-World-Congress-of-Architects-2026-Barcelona-472x303.jpg" srcset="https://oss.gooood.cn/uploads/2026/07/UIA-World-Congress-of-Architects-2026-Barcelona-472x303.jpg 472w, https://oss.gooood.cn/uploads/2026/07/UIA-World-Congress-of-Architects-2026-Barcelona-650x417.jpg 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="2026巴塞罗那UIA世界建筑师大会" width="472" height="303" decoding="async" loading="lazy" fetchpriority="low"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/uia-world-congress-of-architects-2026-barcelona.htm" target="_blank" rel="noopener" data-zh="2026巴塞罗那UIA世界建筑师大会" data-en="UIA World Congress of Architects 2026 Barcelona">2026巴塞罗那UIA世界建筑师大会</a></h3><div class="article-subtitle" data-zh="巴塞罗那汇聚全球一万名建筑师,共同应对住房危机、气候紧急状态与城市挑战" data-en="巴塞罗那汇聚全球一万名建筑师,共同应对住房危机、气候紧急状态与城市挑战">巴塞罗那汇聚全球一万名建筑师,共同应对住房危机、气候紧急状态与城市挑战</div><div class="article-foot"><time datetime="2026-07-02T12:04:17">2026.07.02</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2410      </section>
2411
2412      <section class="ad-embed project-ad" data-v10-fragment="ad-34632" data-ad-position="首页第 12 篇文章后" data-wp-tag-id="34632" data-wp-term-slug="home_list_12" data-backend-ad-position="34632" data-backend-ad-source="dashboard.api.api-advert-adposition.php?slugName=home_list_12" data-backend-ad-status="empty" data-ad-item-count="0" data-ad-source="legacy-api:home_list_12" data-ad-set-fingerprint="811c9dc59e3779b9" data-ad-source-fetched-at="2026-10-02T06:04:17.059Z" data-ad-cache-status="stale" hidden aria-hidden="true"></section>
2413
2414      <section class="row">
2415        <article class="article" data-v10-fragment="article" data-backend-post-id="1703658" data-backend-post-slug="mvrdv-wins-competition-to-renovate-turins-civic-gallery-of-modern-and-contemporary-art" data-backend-post-modified="" data-backend-post-fingerprint="1524597d724756b9" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/mvrdv-wins-competition-to-renovate-turins-civic-gallery-of-modern-and-contemporary-art.htm" target="_blank" rel="noopener" aria-label="MVRDV赢得都灵市立现代与当代艺术馆改造竞赛">
2415<img src="https://oss.gooood.cn/uploads/2026/07/Turins-Civic-Gallery-472x303.jpg" srcset="https://oss.gooood.cn/uploads/2026/07/Turins-Civic-Gallery-472x303.jpg 472w, https://oss.gooood.cn/uploads/2026/07/Turins-Civic-Gallery-650x417.jpg 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="MVRDV赢得都灵市立现代与当代艺术馆改造竞赛" width="472" height="303" decoding="async" loading="lazy" fetchpriority="low"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/mvrdv-wins-competition-to-renovate-turins-civic-gallery-of-modern-and-contemporary-art.htm" target="_blank" rel="noopener" data-zh="MVRDV赢得都灵市立现代与当代艺术馆改造竞赛" data-en="MVRDV wins competition to renovate Turin's Civic Gallery of Modern and Contemporary Art">MVRDV赢得都灵市立现代与当代艺术馆改造竞赛</a></h3><div class="article-subtitle" data-zh="以开放式藏品库和可灵活调整的展示系统重塑博物馆" data-en="以开放式藏品库和可灵活调整的展示系统重塑博物馆">以开放式藏品库和可灵活调整的展示系统重塑博物馆</div><div class="article-foot"><time datetime="2026-07-02T10:14:48">2026.07.02</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2416        <article class="article" data-v10-fragment="article" data-backend-post-id="1692671" data-backend-post-slug="solar-architectural-design-competition" data-backend-post-modified="" data-backend-post-fingerprint="8e32fc6199b82afd" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/solar-architectural-design-competition.htm" target="_blank" rel="noopener" aria-label="聚焦BIPV未来趋势,华宝新能光伏建筑设计大赛正式启动"><img src="https://oss.gooood.cn/uploads/2026/05/%E6%96%B0%E5%B0%81%E9%9D%A2%E5%B0%8F-472x303.png" srcset="https://oss.gooood.cn/uploads/2026/05/%E6%96%B0%E5%B0%81%E9%9D%A2%E5%B0%8F-472x303.png 472w, https://oss.gooood.cn/uploads/2026/05/%E6%96%B0%E5%B0%81%E9%9D%A2%E5%B0%8F-650x417.png 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="聚焦BIPV未来趋势,华宝新能光伏建筑设计大赛正式启动" width="472" height="303" decoding="async" loading="lazy" fetchpriority="low"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/solar-architectural-design-competition.htm" target="_blank" rel="noopener" data-zh="聚焦BIPV未来趋势,华宝新能光伏建筑设计大赛正式启动" data-en="Solar Architectural Design Competition">聚焦BIPV未来趋势,华宝新能光伏建筑设计大赛正式启动</a></h3><div class="article-subtitle" data-zh="重金招募全球设计力量!重新定义未来建筑屋顶" data-en="重金招募全球设计力量!重新定义未来建筑屋顶">重金招募全球设计力量!重新定义未来建筑屋顶</div><div class="article-foot"><time datetime="2026-05-29T18:30:39">2026.05.29</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2417      </section>
2418      <section class="row">
2419        <article class="article" data-v10-fragment="article" data-backend-post-id="1689306" data-backend-post-slug="architecture-drawing-prize-exhibition-by-soane-museum" data-backend-post-modified="" data-backend-post-fingerprint="db34da7e9c9f2a5a" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/architecture-drawing-prize-exhibition-by-soane-museum.htm" target="_blank" rel="noopener" aria-label="2025年建筑绘图奖获奖作品名单公布"><img src="https://oss.gooood.cn/uploads/2026/05/02-architecture-drawing-prize-exhibition-by-soane-museum-472x303.jpg" srcset="https://oss.gooood.cn/uploads/2026/05/02-architecture-drawing-prize-exhibition-by-soane-museum-472x303.jpg 472w, https://oss.gooood.cn/uploads/2026/05/02-architecture-drawing-prize-exhibition-by-soane-museum-650x417.jpg 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="2025年建筑绘图奖获奖作品名单公布" width="472" height="303" decoding="async" loading="lazy" fetchpriority="low"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/architecture-drawing-prize-exhibition-by-soane-museum.htm" target="_blank" rel="noopener" data-zh="2025年建筑绘图奖获奖作品名单公布" data-en="2025 Architecture Drawing Prize Exhibition by Soane Museum">2025年建筑绘图奖获奖作品名单公布</a></h3><div class="article-subtitle" data-zh="英国建筑系学生Sanjidah Chowdhur
2419y获得总冠军(含完整获奖名单)" data-en="英国建筑系学生Sanjidah Chowdhury获得总冠军(含完整获奖名单)">英国建筑系学生Sanjidah Chowdhury获得总冠军(含完整获奖名单)</div><div class="article-foot"><time datetime="2026-05-14T15:34:29">2026.05.14</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2420        <article class="article" data-v10-fragment="article" data-backend-post-id="1688911" data-backend-post-slug="the-eumies-awards-days-2026-celebrate-the-best-of-european-architecture-in-barcelona-with-a-programme-focused-on-reuse-and-transformation" data-backend-post-modified="" data-backend-post-fingerprint="65c6841d6eee9d79" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/the-eumies-awards-days-2026-celebrate-the-best-of-european-architecture-in-barcelona-with-a-programme-focused-on-reuse-and-transformation.htm" target="_blank" rel="noopener" aria-label="2026年密斯奖日亮相巴塞罗那"><img src="https://oss.gooood.cn/uploads/2026/05/02-the-eumies-awards-days-2026-celebrate-the-best-of-european-architecture-in-barcelona-with-a-programme-focused-on-reuse-and-transformation-472x303.jpg" srcset="https://oss.gooood.cn/uploads/2026/05/02-the-eumies-awards-days-2026-celebrate-the-best-of-european-architecture-in-barcelona-with-a-programme-focused-on-reuse-and-transformation-472x303.jpg 472w, https://oss.gooood.cn/uploads/2026/05/02-the-eumies-awards-days-2026-celebrate-the-best-of-european-architecture-in-barcelona-with-a-programme-focused-on-reuse-and-transformation-650x417.jpg 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="2026年密斯奖日亮相巴塞罗那" width="472" height="303" decoding="async" loading="lazy" fetchpriority="low"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/the-eumies-awards-days-2026-celebrate-the-best-of-european-architecture-in-barcelona-with-a-programme-focused-on-reuse-and-transformation.htm" target="_blank" rel="noopener" data-zh="2026年密斯奖日亮相巴塞罗那" data-en="The EUmies Awards Days 2026 celebrate the best of European architecture in Barcelona with a programme focused on reuse and transformation">2026年密斯奖日亮相巴塞罗那</a></h3><div class="article-subtitle" data-zh="聚焦再利用与转化" data-en="聚焦再利用与转化">聚焦再利用与转化</div><div class="article-foot"><time datetime="2026-05-13T11:53:44">2026.05.13</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2421      </section>
2422      <section class="row">
2423        <article class="article" data-v10-fragment="article" data-backend-post-id="1682894" data-backend-post-slug="from-green-enjoyment-to-built-reality-built-projects-from-the-2024-subtropical-sustainable-design-competition" data-backend-post-modified="" data-backend-post-fingerprint="e1562889f17a92a5" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/from-green-enjoyment-to-built-reality-built-projects-from-the-2024-subtropical-sustainable-design-competition.htm" target="_blank" rel="noopener" aria-label="叹绿成真——2024亚热带可持续设计竞赛获奖作品落成发布"><img src="https://oss.gooood.cn/uploads/2026/04/2-bal-472x303.jpg" srcset="https://oss.gooood.cn/uploads/2026/04/2-bal-472x303.jpg 472w, https://oss.gooood.cn/uploads/2026/04/2-bal-650x417.jpg 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="叹绿成真——2024亚热带可持续设计竞赛获奖作品落成发布" width="472" height="303" decoding="async" loading="lazy" fetchpriority="low"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/from-green-enjoyment-to-built-reality-built-projects-from-the-2024-subtropical-sustainable-design-competition.htm" target="_blank" rel="noopener" data-zh="叹绿成真——2024亚热带可持续设计竞赛获奖作品落成发布" data-en="From Green Enjoyment to Built Reality—Built Projects from the 2024 Subtropical Sustainable Design Competition">叹绿成真——2024亚热带可持续设计竞赛获奖作品落成发布</a></h3><div class="article-subtitle" data-zh="在真实场地中生长的零碳实验" data-en="在真实场地中生长的零碳实验">在真实场地中生长的零碳实验</div><div class="article-foot"><time datetime="2026-04-21T16:21:46">2026.04.21</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2424        <article class="article" data-v10-fragment="article" data-backend-p
2424ost-id="1682278" data-backend-post-slug="winners-announcement-of-european-union-prize-for-the-2026-eumies-awards" data-backend-post-modified="" data-backend-post-fingerprint="887c7440aaa8e044" data-backend-primary-type-id=""><div class="cover"><a class="article-cover-link" href="/winners-announcement-of-european-union-prize-for-the-2026-eumies-awards.htm" target="_blank" rel="noopener" aria-label="2026年密斯奖最终获奖名单公布"><img src="https://oss.gooood.cn/uploads/2026/04/01-winners-announcement-of-european-union-prize-for-the-2026-eumies-awards-472x303.jpg" srcset="https://oss.gooood.cn/uploads/2026/04/01-winners-announcement-of-european-union-prize-for-the-2026-eumies-awards-472x303.jpg 472w, https://oss.gooood.cn/uploads/2026/04/01-winners-announcement-of-european-union-prize-for-the-2026-eumies-awards-650x417.jpg 650w" sizes="(max-width: 767px) calc(100vw - 52px), 472px" alt="2026年密斯奖最终获奖名单公布" width="472" height="303" decoding="async" loading="lazy" fetchpriority="low"></a></div><div class="article-text"><div class="kicker" data-zh="资讯" data-en="News">资讯</div><h3><a href="/winners-announcement-of-european-union-prize-for-the-2026-eumies-awards.htm" target="_blank" rel="noopener" data-zh="2026年密斯奖最终获奖名单公布" data-en="WINNERS ANNOUNCEMENT OF EUROPEAN UNION PRIZE FOR THE 2026 EUMIES AWARDS">2026年密斯奖最终获奖名单公布</a></h3><div class="article-subtitle" data-zh="沙勒罗瓦展览宫获得2026年建筑大奖" data-en="沙勒罗瓦展览宫获得2026年建筑大奖">沙勒罗瓦展览宫获得2026年建筑大奖</div><div class="article-foot"><time datetime="2026-04-20T12:34:43">2026.04.20</time><span class="article-actions"><a href="#login" data-gooood-favorite-trigger="1" data-zh="收藏" data-en="Favorites">收藏</a><a href="#" data-zh="分享" data-en="Share">分享</a></span></div></div></article>
2425      </section>
2426
2427      <nav class="pagination" aria-label="分页导航" data-v10-fragment="pagination" data-current-page="1" data-total-pages="21" data-page-one-url="/category/news" data-page-url-template="/category/news/page/__PAGE__" data-total-items="367"><span class="page-item disabled" aria-disabled="true">←</span><a class="active" href="/category/news">1</a><a href="/category/news/page/2">2</a><a href="/category/news/page/3">3</a><span class="page-item dots">...</span><a href="/category/news/page/21">21</a><a href="/category/news/page/2" aria-label="下一页">→</a><span class="page-count">1/21</span><form class="page-jump"><input type="number" min="1" max="21" placeholder="5" aria-label="跳转页码"><button type="submit" data-zh="跳页" data-en="Go">跳页</button></form></nav>
2428      <section class="ad-embed page-bottom" data-v10-fragment="ad-34642" data-ad-position="页码下方广告" data-wp-tag-id="34642" data-wp-term-slug="list_pagination_bottom" data-backend-ad-position="34642" data-backend-ad-source="dashboard.api.api-advert-adposition.php?slugName=list_pagination_bottom" data-backend-ad-status="connected" data-ad-item-count="1" data-ad-record-id="1485604" data-ad-record-ids="1485604" data-ad-slug="%e9%a1%b5%e7%a0%81%e4%b8%8b%e6%96%b9%e6%96%87%e5%ad%97%e5%b9%bf%e5%91%8a" data-ad-modified="" data-ad-title="页码区域文字广告" data-ad-href="/advertisement/%e9%a1%b5%e7%a0%81%e4%b8%8b%e6%96%b9%e6%96%87%e5%ad%97%e5%b9%bf%e5%91%8a" data-ad-source="legacy-api:list_pagination_bottom" data-ad-fingerprint="455c5dd4d0e41eb0" data-ad-set-fingerprint="674fcfc4d1839700" data-ad-source-fetched-at="2026-10-02T06:04:17.100Z" data-ad-cache-status="stale" data-backend-ad-content="acf.ad_content"><div data-ad-record-id="1485604" style="display:contents"><style>._b1{transition:all 0.2s ease}._b1:hover{background:#3584cc!important}._b2{transition:all 0.2s ease}._b2:hover{background:#0e3460!important}@media(max-width:600px){._br td{display:block!important;width:100%!important;padding:0 0 18px 0!important;box-sizing:border-box!important}._br td:last-child{padding-bottom:0!important}}</style>
2429<table class="_br" style="width: 100%; max-width: 1100px; margin: 56px auto 0 auto; border-collapse: collapse; border-spacing: 0;" border="0" width="100%" cellspacing="0" cellpadding="0">
2430<tbody>
2431<tr>
2432<td style="padding: 0 0 0 0; box-sizing: border-box;" valign="middle" width="50%"><a class="_b1" style="display: block; width: 100%; padding: 56px 36px; background: #256eb8; color: #fff; text-align: center; text-decoration: none; border-radius: 0; box-sizing: border-box; font-size: 24px; font-weight: bold;" href="/category/jobs" target="_blank">
2433<span style="font-size: 32px; display: block; line-height: 1.2;">→</span><span style="font-size: 24px; display: block; line-height: 1.4;">求职与招人</span><span style="font-size: 24px; display: block; line-height: 1.4;">上谷德招聘</span>
2434</a></td>
2435<td style="padding: 0 0 0 0; box-sizing: border-box;" valign="middle" width="50%"><a class="_b2" style="display: block; width: 100%; padding: 56px 36px; background: #174a80; color: #fff; text-align: center; text-decoration: none; border-radius: 0; box-sizing: border-box; font-size: 24px; font-weight: bold;" href="/ad-article" target="_blank">
2436<span style="font-size: 32px; display: block; line-height: 1.2;">→</span><span style="font-size: 24px; display: block; line-height: 1.4;">世界级传播</span><span style="font-size: 24px; display: block; line-height: 1.4;">选谷德推广</span>
2437</a></td>
2438</tr>
2439</tbody>
2440</table></div></section>
2441    </main>
2442
2443    <aside class="side">
2444      <div class="sidebar">
2445        <div class="panel" data-v10-fragment="sidebar-series"><div class="panel-head"><span data-zh="最新专辑" data-en="Latest Series">
2445最新专辑</span><a href="/category/series" data-zh="全部 →" data-en="All →">全部 →</a></div><a class="album" href="/everyone-beijing-city-library.htm" target="_blank" rel="noopener"><div class="cover"><img src="https://oss.gooood.cn/uploads/2026/09/everyonelibrary-%E6%8B%B7%E8%B4%9D-472x303.jpg" alt="每个人 × 北京城市图书馆" width="310" height="200" decoding="async" loading="lazy" fetchpriority="low"></div><div><b data-zh="每个人 × 北京城市图书馆" data-en="everyone × Beijing City Library">每个人 × 北京城市图书馆</b><span data-zh="(有视频!)在“世界最大阅览空间”里,他们这样说" data-en="In the “world’s largest reading space”, they say……">(有视频!)在“世界最大阅览空间”里,他们这样说</span></div></a><a class="album" href="/office-fact-atelier-cns.htm" target="_blank" rel="noopener"><div class="cover"><img src="https://oss.gooood.cn/uploads/2026/09/00-office-fact-cns-%E6%8B%B7%E8%B4%9D-472x303.jpg" alt="OFFICE真相专辑 NO.64 - 竖梁社" width="310" height="200" decoding="async" loading="lazy" fetchpriority="low"></div><div><b data-zh="OFFICE真相专辑 NO.64 - 竖梁社" data-en="OFFICE FACT NO.64 - Atelier cnS">OFFICE真相专辑 NO.64 - 竖梁社</b><span data-zh="建筑师要进入具体问题。" data-en="Architects must engage with specific issues.">建筑师要进入具体问题。</span></div></a><a class="album" href="/everyone-sanlitun.htm" target="_blank" rel="noopener"><div class="cover"><img src="https://oss.gooood.cn/uploads/2026/08/everyonesanliitun-472x303.jpg" alt="每个人 × 三里屯" width="310" height="200" decoding="async" loading="lazy" fetchpriority="low"></div><div><b data-zh="每个人 × 三里屯" data-en="everyone × Sanlitun">每个人 × 三里屯</b><span data-zh="(有视频!)当“潮流地标”遇上“日常渴望”" data-en="When “trendy landmarks” meet “daily desires”">(有视频!)当“潮流地标”遇上“日常渴望”</span></div></a></div>
2446        <div class="panel" data-v10-fragment="sidebar-week-hot"><div class="panel-head"><span data-zh="7 天最热" data-en="Most Popular in 7 Days">7 天最热</span></div><a class="hot" href="/the-long-necked-house-dream-home-makeover-2026-dragon-tv-by-not-a-studio.htm" target="_blank" rel="noopener"><div class="rank">01</div><div><b data-zh="东方卫视《梦想改造家2026》长脖子的家,福建泉州 / 无设建筑" data-en="The Long-Necked House, Dream Home Makeover 2026 (Dragon TV) by Not A Studio">东方卫视《梦想改造家2026》长脖子的家,福建泉州 / 无设建筑</b><span></span></div></a><a class="hot" href="/everyone-beijing-city-library.htm" target="_blank" rel="noopener"><div class="rank">02</div><div><b data-zh="每个人 × 北京城市图书馆" data-en="everyone × Beijing City Library">每个人 × 北京城市图书馆</b><span></span></div></a><a class="hot" href="/pavilia-farm-clubhouses-by-snohetta.htm" target="_blank" rel="noopener"><div class="rank">03</div><div><b data-zh="Pavilia Farm会所,香港 / Snøhetta" data-en="Pavilia Farm Clubhouses by Snøhetta">Pavilia Farm会所,香港 / Snøhetta</b><span></span></div></a><a class="hot" href="/xicheng-canal-landscape-opposite-parks-by-brearley-architects-urbanists-bau.htm" target="_blank" rel="noopener"><div class="rank">04</div><div><b data-zh="江阴锡澄运河公园——对景公园,江苏 / Brearley Architects + Urbanists (BAU)" data-en="XICHENG CANAL LANDSCAPE – Opposite Parks by Brearley Architects + Urbanists (BAU)">江阴锡澄运河公园——对景公园,江苏 / Brearley Architects + Urbanists (BAU)</b><span></span></div></a><a class="hot" href="/aranya-youyi-bay-community-regeneration-by-genarchitects.htm" target="_blank" rel="noopener"><div class="rank">05</div><div><b data-zh="阿那亚友谊湾社区更新,秦皇岛 / 亘建筑" data-en="Aranya Youyi Bay Community Regeneration by genarchitects">阿那亚友谊湾社区更新,秦皇岛 / 亘建筑</b><span></span></div></a></div>
2447        <div class="side-section pinned-jobs-section" hidden data-empty-state="no-pinned-jobs" data-v10-fragment="sidebar-pinned-jobs" data-rendered-count="0" data-source="wp/v2/jobs?categories=sidebar-top"><div class="side-section-title"><span class="side-title-main" data-zh="招聘置顶" data-en="Featured Jobs">招聘置顶</span> <a class="side-title-action" href="/job-service-info" target="_blank" rel="noopener" data-zh="购买置顶 →" data-en="Buy Top →">购买置顶 →</a></div><div class="side-jobs pinned"></div></div>
2448        <div class="side-section">
2449          <div class="side-section-title"><span class="side-title-main" data-zh="最新工作" data-en="Latest Jobs">最新工作</span> <a class="side-title-action" href="/job-service-info" target="_blank" rel="noopener" data-zh="购买招聘 →" data-en="Recruitment service →">购买招聘 →</a></div>
2450          <div class="job-region-filter"><span data-zh="按地区查看 :" data-en="Browse by region: ">按地区查看 :</span><a href="/category/jobs" data-zh="全部" data-en="All">全部</a> | <a href="/category/jobs/northern" data-zh="北方" data-en="Northern">北方</a> | <a href="/category/jobs/yangtze-area" data-zh="长江" data-en="Yangtze Area">长江</a> | <a href="/category/jobs/southern" data-zh="华南" data-en="Southern">华南</a></div>
2451          <div class="side-jobs home-pinned" data-admin-setting="homepage_jobs_latest_range" data-default-count="70" data-v10-fragment="side-jobs" data-source="https://dashboard.gooood.cn/wp-json/gooood/v1/dashboard/settings#fresh" data-rendered-count="64" data-backend-count="177" data-configured-start="1" data-configured-end="64" data-configured-count="64"><a class="side-job" data-job-id="1731355" data-job-slug="job-mengarchitects" data-job-date="2026-09-30 14:18:34" data-job-modified="2026-09-30T14:18:34" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="98946f6bf5d40a27" href="/job-mengarchitects.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/09/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2-%E5%AD%9F%E5%BB%BA%E6%B0%91.jpg" alt="(深圳)MENG ARCHITECTS 孟建民团队 – 建筑设计师 / 助理研究员 / 商务经理" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(深圳)MENG ARCHITECTS 孟建民团队 – 建筑设计师 / 助理研究员 / 商务经理" data-en="(深圳)MENG ARCHITECTS 孟建民团队 – 建筑设计师 / 助理研究员 / 商务经理">(深圳)MENG ARCHITECTS 孟建民团队 – 建筑设计师 / 助理研究员 / 商务经理</b><span></span></div></a><a class="side-job" data-job-id="940077" data-job-slug="job-plat-asia" data-job-date="2026-09-30 09:00:07" data-job-modified="2026-09-30T09:18:25" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="6c2923cb798ae757" href="/job-plat-asia.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2023/02/Plat_asia.jpg" alt="(北京)PLAT ASIA - 资深建筑师 / 中级建筑师 / 助理建筑师 / 建筑/景观实习生 / 景观设计师" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(北京)PLAT ASIA - 资深建筑师 / 中级建筑师 / 助理建筑师 / 建筑/景观实习生 / 景观设计师" data-en="(北京)PLAT ASIA - 资深建筑师 / 中级建筑师 / 助理建筑师 / 建筑/景观实习生 / 景观设计师">(北京)PLAT ASIA - 资深建筑师 / 中级建筑师 / 助理建筑师 / 建筑/景观实习生 / 景观设计师</b><span></span></div></a><a class="side-job" data-job-id="1730871" data-job-slug="job-cloud-seven" data-job-date="2026-09-28 18:00:23" data-job-modified="2026-09-29T08:49:41" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="71c0a21741a5b3f3" href="/job-cloud-seven.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/09/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2%E6%A8%A1%E6%9D%BF-wui.jpg" alt="(上海)CLOUD7 云七建筑 - AI 设
2451计师 / 中级建筑设计师 / 初级建筑设计师 / 室内设计师" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)CLOUD7 云七建筑 - AI 设计师 / 中级建筑设计师 / 初级建筑设计师 / 室内设计师" data-en="(上海)CLOUD7 云七建筑 - AI 设计师 / 中级建筑设计师 / 初级建筑设计师 / 室内设计师">(上海)CLOUD7 云七建筑 - AI 设计师 / 中级建筑设计师 / 初级建筑设计师 / 室内设计师</b><span></span></div></a><a class="side-job" data-job-id="1500188" data-job-slug="job-bai-design-international" data-job-date="2026-09-28 09:50:23" data-job-modified="2026-09-29T09:26:42" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="f2a1208046e8df44" href="/job-bai-design-international.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2024/07/%E7%BD%91%E7%AB%99%E6%8B%9B%E8%81%98%E6%96%87%E7%AB%A0%E6%A8%A1%E6%9D%BF-enn.jpg" alt="(北京)英国杰典国际建筑 - 资深建筑师 / 建筑师 / 助理建筑师&amp;应届毕业生 / 实习生 / 室内建筑师 / 媒体专员" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(北京)英国杰典国际建筑 - 资深建筑师 / 建筑师 / 助理建筑师&amp;应届毕业生 / 实习生 / 室内建筑师 / 媒体专员" data-en="(北京)英国杰典国际建筑 - 资深建筑师 / 建筑师 / 助理建筑师&amp;应届毕业生 / 实习生 / 室内建筑师 / 媒体专员">(北京)英国杰典国际建筑 - 资深建筑师 / 建筑师 / 助理建筑师&amp;应届毕业生 / 实习生 / 室内建筑师 / 媒体专员</b><span></span></div></a><a class="side-job" data-job-id="1636057" data-job-slug="latest-20-companies-recruit-information-10" data-job-date="2026-09-27 08:00:22" data-job-modified="2026-09-28T09:33:42" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="5148f183aa7f71cf" href="/latest-20-companies-recruit-information-10.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2025/11/jobs-2-472x303.jpg" alt="最近有哪些好工作?谷德最新20家招聘信息汇总" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="最近有哪些好工作?谷德最新20家招聘信息汇总" data-en="最近有哪些好工作?谷德最新20家招聘信息汇总">最近有哪些好工作?谷德最新20家招聘信息汇总</b><span></span></div></a><a class="side-job" data-job-id="1729522" data-job-slug="job-youngdesign" data-job-date="2026-09-22 17:07:53" data-job-modified="2026-09-22T17:07:53" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="47c2f56eec3cf532" href="/job-youngdesign.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/09/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2%E6%A8%A1%E6%9D%BF-%E6%9C%AC%E6%A0%B7%E8%AE%BE%E8%AE%A1.jpg" alt="(武汉)本样设计 YOUNGDESIGN - 设计总监 / 主案设计师 / 空间助理设计师" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(武汉)本样设计 YOUNGDESIGN - 设计总监 / 主案设计师 / 空间助理设计师" data-en="(武汉)本样设计 YOUNGDESIGN - 设计总监 / 主案设计师 / 空间助理设计师">(武汉)本样设计 YOUNGDESIGN - 设计总监 / 主案设计师 / 空间助理设计师</b><span></span></div></a><a class="side-job" data-job-id="1617081" data-job-slug="job-airwall-architecture-office" data-job-date="2026-09-07 03:30:39" data-job-modified="2026-09-07T16:44:29" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="6e3eb5b0f343c534" href="/job-airwall-architecture-office.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2025/09/2.jpg" alt="(重庆)空气墙建筑工作室 AIRWALL ARCHITECTURE OFFICE - 方案设计师 / 助理设计师 / 设计实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(重庆)空气墙建筑工作室 AIRWALL ARCHITECTURE OFFICE - 方案设计师 / 助理设计师 / 设计实习生" data-en="(重庆)空气墙建筑工作室 AIRWALL ARCHITECTURE OFFICE - 方案设计师 / 助理设计师 / 设计实习生">(重庆)空气墙建筑工作室 AIRWALL ARCHITECTURE OFFICE - 方案设计师 / 助理设计师 / 设计实习生</b><span></span></div></a><a class="side-job" data-job-id="1610416" data-job-slug="job-voice-architecture-lab" data-job-date="2026-09-04 14:35:49" data-job-modified="2026-09-04T14:43:19" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="a2331a8b33061927" href="/job-voice-architecture-lab.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2025/08/VAL-%E7%BD%91%E7%AB%99%E6%8B%9B%E8%81%98%E6%96%87%E7%AB%A0%E5%B0%81%E9%9D%A2.jpg" alt="(上海)Voice Architecture Lab -  AI 设计师 / 中级建筑设计师 / 初级建筑设计师 / 室內设计师" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)Voice Architecture Lab -  AI 设计师 / 中级建筑设计师 / 初级建筑设计师 / 室內设计师" data-en="(上海)Voice Architecture Lab -  AI 设计师 / 中级建筑设计师 / 初级建筑设计师 / 室內设计师">(上海)Voice Architecture Lab -  AI 设计师 / 中级建筑设计师 / 初级建筑设计师 / 室內设计师</b><span></span></div></a><a class="side-job" data-job-id="1408038" data-job-slug="job-jz-lab" data-job-date="2026-09-03 14:00:52" data-job-modified="2026-09-03T14:32:58" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="217caf0f2bd0933b" href="/job-jz-lab.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2024/10/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2%E6%A8%A1%E6%9D%BF-mfr.jpg" alt="(成都)介止商业设计 - 商业负责人 / 项目负责人 / 设计师 / 助理设计师 / 实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(成都)介止商业设计 - 商业负责人 / 项目负责人 / 设计师 / 助理设计师 / 实习生" data-en="(成都)介止商业设计 - 商业负责人 / 项目负责人 / 设计师 / 助理设计师 / 实习生">(成都)介止商业设计 - 商业负责人 / 项目负责人 / 设计师 / 助理设计师 / 实习生</b><span></span></div></a><a class="side-job" data-job-id="1618237" data-job-slug="job-euv" data-job-date="2026-09-02 16:20:44" data-job-modified="2026-09-02T16:17:22" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="f47b1a9d4bf86d79" href="/job-euv.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2025/09/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2%E6%A8%A1%E6%9D%BF-s7v.jpg" alt="(深圳)深圳易加设计(E+UV 工作室)- 建筑师 / 助理建筑师 / 实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(深圳)深圳易加设计(E+UV 工作室)- 建筑师 / 助理建筑师 / 实习生" data-en="(深圳)深圳易加设计(E+UV 工作室)- 建筑师 / 助理建筑师 / 实习生">(深圳)深圳易加设计(E+UV 工作室)- 建筑师 / 助理建筑师 / 实习生</b><span></span></div></a><a class="side-job" data-job-id="1154247" data-job-slug="job-pha" data-job-date="2026-09-02 16:00:41" data-job-modified="2026-09-17T12:02:30" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="4b8473dee3e07622" href="/job-pha.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2025/07/%E6%B9%83%E6%98%82%E5%9B%BD%E9%99%85%E8%AE%BE%E8%AE%A1-%E6%9B%B4%E6%96%B00422.jpg" alt="(深圳)PH Alpha Design 湃昂国际建筑设计顾问有限公司 – 高级建筑设计师 / 建筑设计师 / 主案设计师 / 室内设计师 / 商务经理" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(深圳)PH Alpha Design 湃昂国际建筑设计顾问有限公司 – 高级建筑设计师 / 建筑设计师 / 主案设计师 / 室内设计师 / 商务经理" data-en="(深圳)PH Alpha Design 湃昂国际建筑设计顾问有限公司 – 高级建筑设计师 / 建筑设计师 / 主案设计师 / 室内设计师 / 商务经理">(深圳)PH Alpha Design 湃昂国际建筑设计顾问有限公司 – 高级建筑设计师 / 建筑设计师 / 主案设计师 / 室内设计师 / 商务经理</b><span></span></div></a><a class="side-job" data-job-id="1558304" data-job-slug="job-shiji" data-job-date="2026-09-01 14:34:47" data-job-modified="2026-09-01T15:00:51" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="8e5ebc912a4e1255" href="/job-shiji.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2025/02/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2%E6%A8%A1%E6%9D%BF-%E6%8B%BE%E9%9B%86.jpg" alt="(上海)拾集建筑 - 项目设计师 / 商务与媒体专员 / 商业软装设计师 / 助理设计师 / 实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)拾集建筑 - 项目设计师 / 商务与媒体专员 / 商业软装设计师 / 助理设计师 / 实习生" data-en="(上海)拾集建筑 - 项目设计师 / 商务与媒体专员 / 商业软装设计师 / 助理设计师 / 实习生">(上海)拾集建筑 - 项目设计师 / 商务与媒体专员 / 商业软装设计师 / 助理设计师 / 实习生</b><span></span></div></a><a class="side-job" data-job-id="896685" data-job-slug="job-rlphk" data-job-date="2026-08-31 16:00:36" data-job-modified="2026-08-31T16:39:38" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="a24fba236603002f" href="/job-rlphk.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2025/10/%E5%90%95%E5%85%83%E7%A5%A5-%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2.jpg" alt="(上海/深圳/广州)吕元祥建筑师事务所 Ronald Lu &amp; Partners - 建筑师 / 高级室内设计师 / 助理建筑师 / 实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海/深圳/广州)吕元祥建筑师事务所 Ronald Lu &amp; Partners - 建筑师 / 高级室内设计师 / 助理建筑师 / 实习生" data-en="(上海/深圳/广州)吕元祥建筑师事务所 Ronald Lu &amp; Partners - 建筑师 / 高级室内设计师 / 助理建筑师 / 实习生">(上海/深圳/广州)吕元祥建筑师事务所 Ronald Lu &amp; Partners - 建筑师 / 高级室内设计师 / 助理建筑师 / 实习生</b><span></span></div></a><a class="side-job" data-job-id="1719478" data-job-slug="latest-20-companies-recruit-information-20" data-job-date="2026-08-30 16:00:19" data-job-modified="2026-08-28T18:11:46" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="0ea7945cf5d77360" href="/latest-20-companies-recruit-information-20.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/08/jobs-2-650x417-20%E5%AE%B6%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2.jpg" alt="最近有哪些好工作?谷德最新20家招聘信息汇总" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="最近有哪些好工作?谷德最新20家招聘信息汇总" data-en="最近有哪些好工作?谷德最新20家招聘信息汇总">最近有哪些好工作?谷德最新20家招聘信息汇总</b><span></span></div></a><a class="side-job" data-job-id="1721956" data-job-slug="job-callisonrtkl" data-job-date="2026-08-28 15:20:51" data-job-modified="2026-08-28T15:20:51" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="f7a4e0959de9c409" href="/job-callisonrtkl.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/08/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2%E6%A8%A1%E6%9D%BF-%E5%87%AF%E8%B0%9B%E6%80%9D.jpg" alt="(上海/北京)CallisonRTKL - 初级建筑设计师 / 资深建筑设计师 / 初级室内设计师 / 资深室内设计师" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海/北京)CallisonRTKL - 初级建筑设计师 / 资深建筑设计师 / 初级室内设计师 / 资深室内设计师" data-en="(上海/北京)CallisonRTKL - 初级建筑设计师 / 资深建筑设计师 / 初级室内设计师 / 资深室内设计师">(上海/北京)CallisonRTKL - 初级建筑设计师 / 资深建筑设计师 / 初级室内设计师 / 资深室内设计师</b><span></span></div></a><a class="side-job" data-job-id="980925" data-job-slug="job-dnd" data-job-date="2026-08-25 13:50:24" data-job-modified="2026-08-25T14:38:50" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="17d77fb8b99e04fc" href="/job-dnd.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2023/08/zhijing.jpg" alt="(北京)直径叙事设计 - 设计岗位同时向实习生开放 / 空间设计 / 叙事研究员 / 平面/新媒体设计师 / 项目管理" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(北京)直径叙事设计 - 设计岗位同时向实习生开放 / 空间设计 / 叙事研究员 / 平面/新媒体设计师 / 项目管理" data-en="(北京)直径叙事设计 - 设计岗位同时向实习生开放 / 空间设计 / 叙事研究员 / 平面/新媒体设计师 / 项目管理">(北京)直径叙事设计 - 设计岗位同时向实习生开放 / 空间设计 / 叙事研究员 / 平面/新媒体设计师 / 项目管理</b><span></span></div></a><a class="side-job" data-job-id="714154" data-job-slug="job-oli" data-job-date="2026-08-25 08:50:47" data-job-modified="2026-08-25T09:19:28" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="dc5cacbfc7c5d0cb" href="/job-oli.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2022/11/job-template_350-%E6%8B%B7%E8%B4%9D.jpg" alt="(上海)美国OLI建筑设计事务所 - 项目经理 / 项目建筑师 / 驻场建筑师 / 建筑设计师 / 平面/展陈设计师" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)美国OLI建筑设计事务所 - 项目经理 / 项目建筑师 / 驻场建筑师 / 建筑设计师 / 平面/展陈设计师" data-en="(上海)美国OLI建筑设计事务所 - 项目经理 / 项目建筑师 / 驻场建筑师 / 建筑设计师 / 平面/展陈设计师">(上海)美国OLI建筑设计事务所 - 项目经理 / 项目建筑师 / 驻场建筑师 / 建筑设计师 / 平面/展陈设计师</b><span></span></div></a><a class="side-job" data-job-id="1352914" data-job-slug="job-aura" data-job-date="2026-08-23 10:00:06" data-job-modified="2026-08-18T18:27:52" data-job-modified-source="wp/v2/jobs" data-job-fingerprint="bbe48c732d1da0d7" href="/job-aura.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2023/03
2451/job-template_350-%E6%8B%B7%E8%B4%9D.jpg" alt="(上海)AURA城市规划和景观设计事务所 - 项目组设计总监 / 中级方案设计师 / 初级方案设计师 / 施工图设计师 /景观实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)AURA城市规划和景观设计事务所 - 项目组设计总监 / 中级方案设计师 / 初级方案设计师 / 施工图设计师 /景观实习生" data-en="(上海)AURA城市规划和景观设计事务所 - 项目组设计总监 / 中级方案设计师 / 初级方案设计师 / 施工图设计师 /景观实习生">(上海)AURA城市规划和景观设计事务所 - 项目组设计总监 / 中级方案设计师 / 初级方案设计师 / 施工图设计师 /景观实习生</b><span></span></div></a><a class="side-job" data-job-id="1717988" data-job-slug="job-ai-planetworks" data-job-date="2026-08-21 17:19:57" data-job-modified="" data-job-modified-source="" data-job-fingerprint="b430a14acf99dde6" href="/job-ai-planetworks.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/08/AI-planetworks%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2.jpg" alt="(上海)AI Planetworks上海工作室 -  初级建筑设计师 / 中级建筑师" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)AI Planetworks上海工作室 -  初级建筑设计师 / 中级建筑师" data-en="(上海)AI Planetworks上海工作室 -  初级建筑设计师 / 中级建筑师">(上海)AI Planetworks上海工作室 -  初级建筑设计师 / 中级建筑师</b><span></span></div></a><a class="side-job" data-job-id="1614460" data-job-slug="job-hbaarchitecture" data-job-date="2026-08-17 14:00:53" data-job-modified="" data-job-modified-source="" data-job-fingerprint="36d566e13a29b0ed" href="/job-hbaarchitecture.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2025/08/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2HBA.jpg" alt="(上海)HBA Architecture - 资深项目经理 / 资深建筑规划师 / 资深建筑设计师 / 商务拓展经理 / 实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)HBA Architecture - 资深项目经理 / 资深建筑规划师 / 资深建筑设计师 / 商务拓展经理 / 实习生" data-en="(上海)HBA Architecture - 资深项目经理 / 资深建筑规划师 / 资深建筑设计师 / 商务拓展经理 / 实习生">(上海)HBA Architecture - 资深项目经理 / 资深建筑规划师 / 资深建筑设计师 / 商务拓展经理 / 实习生</b><span></span></div></a><a class="side-job" data-job-id="927974" data-job-slug="job-wonderlabs" data-job-date="2026-08-07 18:00:14" data-job-modified="" data-job-modified-source="" data-job-fingerprint="00a22fbfc92cd763" href="/job-wonderlabs.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2022/10/wonderlabs-472x303.jpg" alt="(上海)Wonderlabs - 3D建模设计师 / 装置&amp;展览展示设计师 / 平面设计师&amp;界面设计方向" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)Wonderlabs - 3D建模设计师 / 装置&amp;展览展示设计师 / 平面设计师&amp;界面设计方向" data-en="(上海)Wonderlabs - 3D建模设计师 / 装置&amp;展览展示设计师 / 平面设计师&amp;界面设计方向">(上海)Wonderlabs - 3D建模设计师 / 装置&amp;展览展示设计师 / 平面设计师&amp;界面设计方向</b><span></span></div></a><a class="side-job" data-job-id="1339105" data-job-slug="job-martha-schwartz-partners" data-job-date="2026-08-07 17:00:44" data-job-modified="" data-job-modified-source="" data-job-fingerprint="5da21036ee8667aa" href="/job-martha-schwartz-partners.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2023/01/martha-472x303.jpg" alt="(上海) 玛
2451莎施瓦茨及合伙人事务所 Martha Schwartz Partners – 高级景观建筑师 Senior Landscape Designer / 景观建筑师 Landscape Designer" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海) 玛莎施瓦茨及合伙人事务所 Martha Schwartz Partners – 高级景观建筑师 Senior Landscape Designer / 景观建筑师 Landscape Designer" data-en="(上海) 玛莎施瓦茨及合伙人事务所 Martha Schwartz Partners – 高级景观建筑师 Senior Landscape Designer / 景观建筑师 Landscape Designer">(上海) 玛莎施瓦茨及合伙人事务所 Martha Schwartz Partners – 高级景观建筑师 Senior Landscape Designer / 景观建筑师 Landscape Designer</b><span></span></div></a><a class="side-job" data-job-id="1716293" data-job-slug="job-hdg-group" data-job-date="2026-08-07 14:01:20" data-job-modified="" data-job-modified-source="" data-job-fingerprint="51067fb3b73ae02f" href="/job-hdg-group.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/08/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2-%E8%89%BE%E6%B4%BE%E6%96%AF.jpg" alt="(北京)北京艾派斯展览展示服务有限公司 - 软装设计师 / 陈列设计师 / 采购员 / 高级室内设计师" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(北京)北京艾派斯展览展示服务有限公司 - 软装设计师 / 陈列设计师 / 采购员 / 高级室内设计师" data-en="(北京)北京艾派斯展览展示服务有限公司 - 软装设计师 / 陈列设计师 / 采购员 / 高级室内设计师">(北京)北京艾派斯展览展示服务有限公司 - 软装设计师 / 陈列设计师 / 采购员 / 高级室内设计师</b><span></span></div></a><a class="side-job" data-job-id="1714973" data-job-slug="job-qiu" data-job-date="2026-08-05 08:45:54" data-job-modified="" data-job-modified-source="" data-job-fingerprint="2c29068dd289e6c1" href="/job-qiu.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/08/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2-Q
2451IU-w77.jpg" alt="(深圳)英国Quality Innovation United深圳分公司 - 建筑设计师 / 资深建筑设计师  / 设计实习生 / 室内设计师(暂招满)" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(深圳)英国Quality Innovation United深圳分公司 - 建筑设计师 / 资深建筑设计师  / 设计实习生 / 室内设计师(暂招满)" data-en="(深圳)英国Quality Innovation United深圳分公司 - 建筑设计师 / 资深建筑设计师  / 设计实习生 / 室内设计师(暂招满)">(深圳)英国Quality Innovation United深圳分公司 - 建筑设计师 / 资深建筑设计师  / 设计实习生 / 室内设计师(暂招满)</b><span></span></div></a><a class="side-job" data-job-id="1714288" data-job-slug="job-landtek-group" data-job-date="2026-07-31 17:00:21" data-job-modified="" data-job-modified-source="" data-job-fingerprint="f768aa081dc97034" href="/job-landtek-group.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/07/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2-%E9%A3%8E%E7%89%A9%E8%90%A5%E9%80%A0-8gl.jpg" alt="(广州)风物营造 LANDTEK GROUP - 景观设计师 / 植物设计师 / 品牌运营 / 实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(广州)风物营造 LANDTEK GROUP - 景观设计师 / 植物设计师 / 品牌运营 / 实习生" data-en="(广州)风物营造 LANDTEK GROUP - 景观设计师 / 植物设计师 / 品牌运营 / 实习生">(广州)风物营造 LANDTEK GROUP - 景观设计师 / 植物设计师 / 品牌运营 / 实习生</b><span></span></div></a><a class="side-job" data-job-id="1709760" data-job-slug="job-studio-kukannai" data-job-date="2026-07-31 10:59:11" data-job-modified="" data-job-modified-source="" data-job-fingerprint="2cc0e4fd09f20dc1" href="/job-studio-kukannai.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/07/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2-%E7%A9%BA%E9%97%B4%E9%87%8C.jpg" alt="(上海)空间里建筑设计事务所 – 项目建筑师 / 室内设计师  / 实习生(建筑/室内)" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)空间里建筑设计事务所 – 项目建筑师 / 室内设计师  / 实习生(建筑/室内)" data-en="(上海)空间里建筑设计事务所 – 项目建筑师 / 室内设计师  / 实习生(建筑/室内)">(上海)空间里建筑设计事务所 – 项目建筑师 / 室内设计师  / 实习生(建筑/室内)</b><span></span></div></a><a class="side-job" data-job-id="1270605" data-job-slug="job-topo-design" data-job-date="2026-07-28 16:40:58" data-job-modified="" data-job-modified-source="" data-job-fingerprint="b95606b81aff111c" href="/job-topo-design.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2022/05/0513-topo-472x303.jpg" alt="(上海)TOPO Design Group - 景观设计师 / 景观后期设计师 / 景观实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)TOPO Design Group - 景观设计师 / 景观后期设计师 / 景观实习生" data-en="(上海)TOPO Design Group - 景观设计师 / 景观后期设计师 / 景观实习生">(上海)TOPO Design Group - 景观设计师 / 景观后期设计师 / 景观实习生</b><span></span></div></a><a class="side-job" data-job-id="747401" data-job-slug="job-flo" data-job-date="2026-07-21 12:00:00" data-job-modified="" data-job-modified-source="" data-job-fingerprint="633e96e61f0d56b2" href="/job-flo.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2022/11/flo-472x303.jpg" alt="(上海)FLO景观设计事务所 - 主创/资深景观设计师 / 景观设计师 / 设计实习生 / 商务行政助理 / 助理施工图设计师" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)FLO景观设计事务所 - 主创/资深景观设计师 / 景观设计师 / 设计实习生 / 商务行政助理 / 助理施工图设计师" data-en="(上海)FLO景观设计事务所 - 主创/资深景观设计师 / 景观设计师 / 设计实习生 / 商务行政助理 / 助理施工图设计师">(上海)FLO景观设计事务所 - 主创/资深景观设计师 / 景观设计师 / 设计实习生 / 商务行政助理 / 助理施工图设计师</b><span></span></div></a><a class="side-job" data-job-id="418137" data-job-slug="job-way-studio" data-job-date="2026-07-21 10:30:04" data-job-modified="" data-job-modified-source="" data-job-fingerprint="5b716e3fd3c39c03" href="/job-way-studio.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2025/07/waystudio-2.jpg" alt="(北京)未/WAY Studio建筑设计研究所 - 建筑设计师 / 助理设计师/初级设计师 / 实习生 / 办公室行政与商务助理" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(北京)未/WAY Studio建筑设计研究所 - 建筑设计师 / 助理设计师/初级设计师 / 实习生 / 办公室行政与商务助理" data-en="(北京)未/WAY Studio建筑设计研究所 - 建筑设计师 / 助理设计师/初级设计师 / 实习生 / 办公室行政与商务助理">(北京)未/WAY Studio建筑设计研究所 - 建筑设计师 / 助理设计师/初级设计师 / 实习生 / 办公室行政与商务助理</b><span></span></div></a><a class="side-job" data-job-id="1570854" data-job-slug="job-kokaistudios" data-job-date="2026-07-16 09:00:56" data-job-modified="" data-job-modified-source="" data-job-fingerprint="b850e5fbc0c06097" href="/job-kokaistudios.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2025/03/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2-kokai.jpg" alt="(上海)Kokaistudios - 室内设计师(商业/酒店)" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)Kokaistudios - 室内设计师(商业/酒店)" data-en="(上海)Kokaistudios - 室内设计师(商业/酒店)">(上海)Kokaistudios - 室内设计师(商业/酒店)</b><span></span></div></a><a class="side-job" data-job-id="4578" data-job-slug="job-kengo-kuma-and-associates" data-job-date="2026-07-15 10:00:00" data-job-modified="" data-job-modified-source="" data-job-fingerprint="c2006ec91d57b415" href="/job-kengo-kuma-and-associates.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/07/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2-%E9%9A%88%E7%A0%94%E5%90%BE.jpg" alt="(北京)隈研吾建筑都市设计事务所 - 设计管理统筹 / 全职建筑è
2451®¾è®¡å¸ˆ / 实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(北京)隈研吾建筑都市设计事务所 - 设计管理统筹 / 全职建筑设计师 / 实习生" data-en="(北京)隈研吾建筑都市设计事务所 - 设计管理统筹 / 全职建筑设计师 / 实习生">(北京)隈研吾建筑都市设计事务所 - 设计管理统筹 / 全职建筑设计师 / 实习生</b><span></span></div></a><a class="side-job" data-job-id="1023216" data-job-slug="job-pao" data-job-date="2026-07-14 12:00:13" data-job-modified="" data-job-modified-source="" data-job-fingerprint="08985529f292aa1d" href="/job-pao.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/07/PAO.jpg" alt="(北京/广州)众建筑 PAO - 建筑师 / 市场政策研究调查员/ 结构工程师 / 模块化产品建筑设计师 / 室内装修工程师 / 机电工程师 / 实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(北京/广州)众建筑 PAO - 建筑师 / 市场政策研究调查员/ 结构工程师 / 模块化产品建筑设计师 / 室内装修工程师 / 机电工程师 / 实习生" data-en="(北京/广州)众建筑 PAO - 建筑师 / 市场政策研究调查员/ 结构工程师 / 模块化产品建筑设计师 / 室内装修工程师 / 机电工程师 / 实习生">(北京/广州)众建筑 PAO - 建筑师 / 市场政策研究调查员/ 结构工程师 / 模块化产品建筑设计师 / 室内装修工程师 / 机电工程师 / 实习生</b><span></span></div></a><a class="side-job" data-job-id="1706949" data-job-slug="job-the-triangle-jp" data-job-date="2026-07-13 14:00:50" data-job-modified="" data-job-modified-source="" data-job-fingerprint="74037e04bdc4b6e8" href="/job-the-triangle-jp.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/07/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2-%E5%A4%9A%E4%B8%89%E8%A7%92%E7%A9%BA%E9%97%B4-0712.jpg" alt="(上海)多三角空间设计 – 资深主创设计师 / 主创设计师 / 助理设计师 / 品牌内容运营负责人" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)多三角空间设计 – 资深主创设计师 / 主创设计师 / 助理设计师 / 品牌内容运营负责人" data-en="(上海)多三角空间设计 – 资深主创设计师 / 主创设计师 / 助理设计师 / 品牌内容运营负责人">(上海)多三角空间设计 – 资深主创设计师 / 主创设计师 / 助理设计师 / 品牌内容运营负责人</b><span></span></div></a><a class="side-job" data-job-id="950416" data-job-slug="job-chiasmus-partners" data-job-date="2026-07-13 11:00:59" data-job-modified="" data-job-modified-source="" data-job-fingerprint="446b6a9487f1b4f8" href="/job-chiasmus-partners.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2024/02/Chiasmus.jpg" alt="(北京)Chiasmus 建筑设计事务所 - 建筑师 /  建筑师助理 / 室内设计师 / 新媒体公关 / 建筑实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(北京)Chiasmus 建筑设计事务所 - 建筑师 /  建筑师助理 / 室内设计师 / 新媒体公关 / 建筑实习生" data-en="(北京)Chiasmus 建筑设计事务所 - 建筑师 /  建筑师助理 / 室内设计师 / 新媒体公关 / 建筑实习生">(北京)Chiasmus 建筑设计事务所 - 建筑师 /  建筑师助理 / 室内设计师 / 新媒体公关 / 建筑实习生</b><span></span></div></a><a class="side-job" data-job-id="1705723" data-job-slug="job-l-p-architects" data-job-date="2026-07-09 16:31:39" data-job-modified="" data-job-modified-source="" data-job-fingerprint="c4c32b9d02212fe1" href="/job-l-p-architects.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/07/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2-LP.jpg" alt="(深圳/香港)L&amp;P Architects 瓴柏国际设计顾问有限公司 - 高级建筑师 / 建筑设计师 / 资深别墅豪宅精装设计师" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(深圳/香港)L&amp;P Architects 瓴柏国际设计顾问有限公司 - 高级建筑师 / 建筑设计师 / 资深别墅豪宅精装设计师" data-en="(深圳/香港)L&amp;P Architects 瓴柏国际设计顾问有限公司 - 高级建筑师 / 建筑设计师 / 资深别墅豪宅精装设计师">(深圳/香港)L&amp;P Architects 瓴柏国际设计顾问有限公司 - 高级建筑师 / 建筑设计师 / 资深别墅豪宅精装设计师</b><span></span></div></a><a class="side-job" data-job-id="1594637" data-job-slug="job-nian-landscape" data-job-date="2026-07-09 13:46:36" data-job-modified="" data-job-modified-source="" data-job-fingerprint="021e63de8680358a" href="/job-nian-landscape.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture">
2451<img src="https://oss.gooood.cn/uploads/2025/06/%E5%BB%BF%E6%99%AF%E8%A7%82-%E7%BD%91%E7%AB%99%E6%8B%9B%E8%81%98%E6%96%87%E7%AB%A0%E5%B0%81%E9%9D%A2.jpg" alt="(上海)廿景观 NIAN LANDSCAPE - 资深景观设计师/项目负责人 / 景观设计师 / 景观设计实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)廿景观 NIAN LANDSCAPE - 资深景观设计师/项目负责人 / 景观设计师 / 景观设计实习生" data-en="(上海)廿景观 NIAN LANDSCAPE - 资深景观设计师/项目负责人 / 景观设计师 / 景观设计实习生">(上海)廿景观 NIAN LANDSCAPE - 资深景观设计师/项目负责人 / 景观设计师 / 景观设计实习生</b><span></span></div></a><a class="side-job" data-job-id="1705138" data-job-slug="job-deep-design-consultant" data-job-date="2026-07-07 10:52:09" data-job-modified="" data-job-modified-source="" data-job-fingerprint="06b8e3a8a09b8a74" href="/job-deep-design-consultant.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/07/0707%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2-%E5%AE%BD%E5%93%81%E8%AE%BE%E8%AE%A1.jpg" alt="(厦门)宽品设计 - 室内设计师 / 设计助理 / 项目深化设计师" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(厦门)宽品设计 - 室内设计师 / 设计助理 / 项目深化设计师" data-en="(厦门)宽品设计 - 室内设计师 / 设计助理 / 项目深化设计师">(厦门)宽品设计 - 室内设计师 / 设计助理 / 项目深化设计师</b><span></span></div></a><a class="side-job" data-job-id="972843" data-job-slug="job-vari-architects" data-job-date="2026-07-06 16:00:09" data-job-modified="" data-job-modified-source="" data-job-fingerprint="ee30548cb047a4f0" href="/job-vari-architects.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2024/06/VARI-kla.jpg" alt="(重庆)vari architects 几里建筑 - 建筑师 / 助理建筑师 / 室内设计师 / 媒体运营专员 / 实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(重庆)vari architects 几里建筑 - 建筑师 / 助理建筑师 / 室内设计师 / 媒体运营专员 / 实习生" data-en="(重庆)vari architects 几里建筑 - 建筑师 / 助理建筑师 / 室内设计师 / 媒体运营专员 / 实习生">(重庆)vari architects 几里建筑 - 建筑师 / 助理建筑师 / 室内设计师 / 媒体运营专员 / 实习生</b><span></span></div></a><a class="side-job" data-job-id="725861" data-job-slug="job-gmp" data-job-date="2026-07-06 14:30:40" data-job-modified="" data-job-modified-source="" data-job-fingerprint="47678ec6a7edb2aa" href="/job-gmp.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2023/06/gmp.jpg" alt="(深圳)德国gmp建筑师事务所(Architects von Gerkan, Marg and Partner)- 建筑实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(深圳)德国gmp建筑师事务所(Architects von Gerkan, Marg and Partner)- 建筑实习生" data-en="(深圳)德国gmp建筑师事务所(Architects von Gerkan, Marg and Partner)- 建筑实习生">(深圳)德国gmp建筑师事务所(Architects von Gerkan, Marg and Partner)- 建筑实习生</b><span></span></div></a><a class="side-job" data-job-id="1702374" data-job-slug="job-whatever-design-office" data-job-date="2026-07-03 17:06:50" data-job-modified="" data-job-modified-source="" data-job-fingerprint="eeaf47ab3864d217" href="/job-whatever-design-office.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/07/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2-%E5%8B%89%E5%BC%BA%E8%AE%BE%E8%AE%A1.jpg" alt="(重庆)勉强设计事务所 - 空间设计师 / 空间设计助理 / 施工图设计师 / 实习生(长期招募)" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(重庆)勉强设计事务所 - 空间设计师 / 空间设计助理 / 施工图设计师 / 实习生(长期招募)" data-en="(重庆)勉强设计事务所 - 空间设计师 / 空间设计助理 / 施工图设计师 / 实习生(长期招募)">(重庆)勉强设计事务所 - 空间设计师 / 空间设计助理 / 施工图设计师 / 实习生(长期招募)</b><span></span></div></a><a class="side-job" data-job-id="1606496" data-job-slug="job-tens-atelier" data-job-date="2026-07-03 15:00:17" data-job-modified="" data-job-modified-source="" data-job-fingerprint="ee5c939affce3c06" href="/job-tens-atelier.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/07/tens-atelier-2.jpg" alt="(上海)弹性工作室Tens Atelier - 项目室内设计师 /  助理室内设计师 / 实习生(长期招募)" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)弹性工作室Tens Atelier - 项目室内设计师 /  助理室内设计师 / 实习生(长期招募)" data-en="(上海)弹性工作室Tens Atelier - 项目室内设计师 /  助理室内设计师 / 实习生(长期招募)">(上海)弹性工作室Tens Atelier - 项目室内设计师 /  助理室内设计师 / 实习生(长期招募)</b><span></span></div></a><a class="side-job" data-job-id="617902" data-job-slug="job-leeko" data-job-date="2026-07-02 15:00:58" data-job-modified="" data-job-modified-source="" data-job-fingerprint="76b450787361da84" href="/job-leeko.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2022/08/0228-472x303-slb.jpg" alt="(上海)以靠建筑 - 室内设计师 / 助理室内设计师 / 建筑师 / 助理建筑师 / 助理景观设计师" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)以靠建筑 - 室内设计师 / 助理室内设计师 / 建筑师 / 助理建筑师 / 助理景观设计师" data-en="(上海)以靠建筑 - 室内设计师 / 助理室内设计师 / 建筑师 / 助理建筑师 / 助理景观设计师">(上海)以靠建筑 - 室内设计师 / 助理室内设计师 / 建筑师 / 助理建筑师 / 助理景观设计师</b><span></span></div></a><a class="side-job" data-job-id="834732" data-job-slug="job-wsp" data-job-date="2026-06-29 16:30:44" data-job-modified="" data-job-modified-source="" data-job-fingerprint="05aa28a3341ea85f" href="/job-wsp.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2022/09/WechatIMG13.jpg" alt="(北京)维思平WSP - 新媒体运营 / 商务总监/商务经理 / 建筑主创设计师 / 建筑助理设计师 / 建筑设计实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(北京)维思平WSP - 新媒体运营 / 商务总监/商务经理 / 建筑主创设计师 / 建筑助理设计师 / 建筑设计实习生" data-en="(北京)维思平WSP - 新媒体运营 / 商务总监/商务经理 / 建筑主创设计师 / 建筑助理设计师 / 建筑设计实习生">(北京)维思平WSP - 新媒体运营 / 商务总监/商务经理 / 建筑主创设计师 / 建筑助理设计师 / 建筑设计实习生</b><span></span></div></a><a class="side-job" data-job-id="1070070" data-job-slug="job-ask-architecture" data-job-date="2026-06-29 14:00:04" data-job-modified="" data-job-modified-source="" data-job-fingerprint="c07b5d85e33cc271" href="/job-ask-architecture.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2024/04/0629%E9%97%A8%E5%8F%A3-%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2.jpg" alt="(成都)門口建筑工作室 Ask Architecture - 建筑师 / 室内设计师 / 设计实习生 / 媒体助理" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(成都)門口建筑工作室 Ask Architecture - 建筑师 / 室内设计师 / 设计实习生 / 媒体助理" data-en="(成都)門口建筑工作室 Ask Architecture - 建筑师 / 室内设计师 / 设计实习生 / 媒体助理">(成都)門口建筑工作室 Ask Architecture - 建筑师 / 室内设计师 / 设计实习生 / 媒体助理</b><span></span></div></a><a class="side-job" data-job-id="777945" data-job-slug="job-fab-architects" data-job-date="2026-06-26 09:00:22" data-job-modified="" data-job-modified-source="" data-job-fingerprint="8f03695cb173eaa0" href="/job-fab-architects.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2022/05/qinghua-1-22-472x303.jpg" alt="(北京)清华大学建筑设计研究院第一分院 – 建筑师(医疗康养) / 实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(北京)清华大学建筑设计研究院第一分院 – 建筑师(医疗康养) / 实习生" data-en="(北京)清华大学建筑设计研究院第一分院 – 建筑师(医疗康养) / 实习生">(北京)清华大学建筑设计研究院第一分院 – 建筑师(医疗康养) / 实习生</b><span></span></div></a><a class="side-job" data-job-id="1701215" data-job-slug="job-atmosphere" data-job-date="2026-06-24 11:50:34" data-job-modified="" data-job-modified-source="" data-job-fingerprint="638f4d49fc94841d" href="/job-atmosphere.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/06/ATMOSPHERE-Architects-2.jpg" alt="(成都)ATMOSPHERE Architects氣象建築 - 建筑设计师 / 空间设计师 / 设计师助理" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(成都)ATMOSPHERE Architects氣象建築 - 建筑设计师 / 空间设计师 / 设计师助理" data-en="(成都)ATMOSPHERE Architects氣象建築 - 建筑设计师 / 空间设计师 / 设计师助理">(成都)ATMOSPHERE Architects氣象建築 - 建筑设计师 / 空间设计师 / 设计师助理</b><span></span></div></a><a class="side-job" data-job-id="1542809" data-job-slug="job-eeri-studio-2" data-job-date="2026-06-22 16:00:47" data-job-modified="" data-job-modified-source="" data-job-fingerprint="cee1dca8a7aee994" href="/job-eeri-studio-2.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/06/eeri-2.jpg" alt="(上海)EERI  即域建筑è
2451®¾è®¡å·¥ä½œå®¤ - 项目建筑师 / 助理建筑师 / 助理室内设计师 / 媒体与研究助理 / 建筑实习生(长期有效)" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)EERI  即域建筑设计工作室 - 项目建筑师 / 助理建筑师 / 助理室内设计师 / 媒体与研究助理 / 建筑实习生(长期有效)" data-en="(上海)EERI  即域建筑设计工作室 - 项目建筑师 / 助理建筑师 / 助理室内设计师 / 媒体与研究助理 / 建筑实习生(长期有效)">(上海)EERI  即域建筑设计工作室 - 项目建筑师 / 助理建筑师 / 助理室内设计师 / 媒体与研究助理 / 建筑实习生(长期有效)</b><span></span></div></a><a class="side-job" data-job-id="1699206" data-job-slug="job-oll-opple" data-job-date="2026-06-16 10:30:47" data-job-modified="" data-job-modified-source="" data-job-fingerprint="c0a89c3ac2a05306" href="/job-oll-opple.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/06/oll-2.jpg" alt="(上海)OLL(欧乐照明)- 室内设计师 / 照明设计师 / 客户/设计师拓展主管 / 品牌市场主管 / 设计实习生(室内/平面/照明设计)" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)OLL(欧乐照明)- 室内设计师 / 照明设计师 / 客户/设计师拓展主管 / 品牌市场主管 / 设计实习生(室内/平面/照明设计)" data-en="(上海)OLL(欧乐照明)- 室内设计师 / 照明设计师 / 客户/设计师拓展主管 / 品牌市场主管 / 设计实习生(室内/平面/照明设计)">(上海)OLL(欧乐照明)- 室内设计师 / 照明设计师 / 客户/设计师拓展主管 / 品牌市场主管 / 设计实习生(室内/平面/照明设计)</b><span></span></div></a><a class="side-job" data-job-id="1266653" data-job-slug="job-ondo-studio" data-job-date="2026-06-12 16:00:03" data-job-modified="" data-job-modified-source="" data-job-fingerprint="0523c4d6bce3feaa" href="/job-ondo-studio.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2023/05/ondo.jpg" alt="(杭州)温度ONDO空间设计 - 室内设计师 / 辅案设计助理 / 实习生 / 施工图深化设计师 / 商务总监" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(杭州)温度ONDO空间设计 - 室内设计师 / 辅案设计助理 / 实习生 / 施工图深化设计师 / 商务总监" data-en="(杭州)温度ONDO空间设计 - 室内设计师 / 辅案设计助理 / 实习生 / 施工图深化设计师 / 商务总监">(杭州)温度ONDO空间设计 - 室内设计师 / 辅案设计助理 / 实习生 / 施工图深化设计师 / 商务总监</b><span></span></div></a><a class="side-job" data-job-id="1697755" data-job-slug="job-uad-acrc" data-job-date="2026-06-11 17:10:25" data-job-modified="" data-job-modified-source="" data-job-fingerprint="5855a30d8a4c15a1" href="/job-uad-acrc.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/06/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2.jpg" alt="(杭州)UAD-ACRC浙江大学建筑设计研究院有限公司 - 建筑师" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(杭州)UAD-ACRC浙江大学建筑设计研究院有限公司 - 建筑师" data-en="(杭州)UAD-ACRC浙江大学建筑设计研究院有限公司 - 建筑师">(杭州)UAD-ACRC浙江大学建筑设计研究院有限公司 - 建筑师</b><span></span></div></a><a class="side-job" data-job-id="843832" data-job-slug="job-formless-architects" data-job-date="2026-06-11 14:20:45" data-job-modified="" data-job-modified-source="" data-job-fingerprint="b4ad82fffceadafb" href="/job-formless-architects.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/06/formless-2.jpg" alt="(上海)形非建筑 Formless Architects -  助理室内设计师 / 室内设计师 / 建筑设计师 / 助理建筑师 / 建筑实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)形非建筑 Formless Architects -  助理室内设计师 / 室内设计师 / 建筑设计师 / 助理建筑师 / 建筑实习生" data-en="(上海)形非建筑 Formless Architects -  助理室内设计师 / 室内设计师 / 建筑设计师 / 助理建筑师 / 建筑实习生">(上海)形非建筑 Formless Architects -  助理室内设计师 / 室内设计师 / 建筑设计师 / 助理建筑师 / 建筑实习生</b><span></span></div></a><a class="side-job" data-job-id="1693839" data-job-slug="job-office-mass" data-job-date="2026-06-01 14:03:16" data-job-modified="" data-job-modified-source="" data-job-fingerprint="73597b0522d48469" href="/job-office-mass.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/05/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2.jpg" alt="(上海)曼景建筑 OFFICE MASS - 主创建筑师 / 建筑师 / 助理建筑师/媒体实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)曼景建筑 OFFICE MASS - 主创建筑师 / 建筑师 / 助理建筑师/媒体实习生" data-en="(上海)曼景建筑 OFFICE MASS - 主创建筑师 / 建筑师 / 助理建筑师/媒体实习生">(上海)曼景建筑 OFFICE MASS - 主创建筑师 / 建筑师 / 助理建筑师/媒体实习生</b><span></span></div></a><a class="side-job" data-job-id="1693904" data-job-slug="jobs-xian-architects" data-job-date="2026-05-29 17:04:14" data-job-modified="" data-job-modified-source="" data-job-fingerprint="02f72c2e3e91074a" href="/jobs-xian-architects.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/05/0529%E6%B0%99%E5%BB%BA%E7%AD%91%E5%B7%A5%E4%BD%9C%E5%AE%A4-p2t.jpg" alt="(北京)xiān氙建筑工作室 - 项目建筑师 / 助理设计师 / 实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(北京)xiān氙建筑工作室 - 项目建筑师 / 助理设计师 / 实习生" data-en="(北京)xiān氙建筑工作室 - 项目建筑师 / 助理设计师 / 实习生">(北京)xiān氙建筑工作室 - 项目建筑师 / 助理设计师 / 实习生</b><span></span></div></a><a class="side-job" data-job-id="1571492" data-job-slug="job-duts-design" data-job-date="2026-05-29 09:34:25" data-job-modified="" data-job-modified-source="" data-job-fingerprint="57dd601ff1fd3f9b" href="/job-duts-design.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture">
2451<img src="https://oss.gooood.cn/uploads/2026/05/duts-design-2.jpg" alt="(上海)杜兹设计 DUTS design -  室内设计师(主创)/ 助理建筑设计师 / 实习生(建筑、媒体、景观、室内)" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)杜兹设计 DUTS design -  室内设计师(主创)/ 助理建筑设计师 / 实习生(建筑、媒体、景观、室内)" data-en="(上海)杜兹设计 DUTS design -  室内设计师(主创)/ 助理建筑设计师 / 实习生(建筑、媒体、景观、室内)">(上海)杜兹设计 DUTS design -  室内设计师(主创)/ 助理建筑设计师 / 实习生(建筑、媒体、景观、室内)</b><span></span></div></a><a class="side-job" data-job-id="1692907" data-job-slug="jobs-waa" data-job-date="2026-05-28 17:36:56" data-job-modified="" data-job-modified-source="" data-job-fingerprint="8d0a58ef2bec96db" href="/jobs-waa.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/05/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2-waa%E6%9C%AA%E8%A7%89%E5%BB%BA%E7%AD%910528.jpg" alt="(北京)waa未觉建筑 - 建筑设计师 / 室内设计师 / 助理设计师 / 建筑实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(北京)waa未觉建筑 - 建筑设计师 / 室内设计师 / 助理设计师 / 建筑实习生" data-en="(北京)waa未觉建筑 - 建筑设计师 / 室内设计师 / 助理设计师 / 建筑实习生">(北京)waa未觉建筑 - 建筑设计师 / 室内设计师 / 助理设计师 / 建筑实习生</b><span></span></div></a><a class="side-job" data-job-id="1117478" data-job-slug="job-fangxia" data-job-date="2026-05-28 10:00:13" data-job-modified="" data-job-modified-source="" data-job-fingerprint="7e1bd063641cf7d7" href="/job-fangxia.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2025/05/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2-0522%E6%96%B9%E5%A4%8F.jpg" alt="(北京)方夏设计 - 高级室内设计师 / 室内方案设计师 / 高级软装设计师 / 三维建模设计师 / 商务负责人或经理" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(北京)方夏设计 - 高级室内设计师 / 室内方案设计师 / 高级软装设计师 / 三维建模设计师 / 商务负责人或经理" data-en="(北京)方夏设计 - 高级室内设计师 / 室内方案设计师 / 高级软装设计师 / 三维建模设计师 / 商务负责人或经理">(北京)方夏设计 - 高级室内设计师 / 室内方案设计师 / 高级软装设计师 / 三维建模设计师 / 商务负责人或经理</b><span></span></div></a><a class="side-job" data-job-id="1170463" data-job-slug="job-plpl" data-job-date="2026-05-27 11:30:30" data-job-modified="" data-job-modified-source="" data-job-fingerprint="12f70af5ca125c31" href="/job-plpl.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2025/10/%E5%B0%81%E9%9D%A2%E6%8B%9B%E8%81%98.jpg" alt="(上海)PLPL|Philip Liao &amp; Partners Limited(Shanghai) 廖宜康建筑设计顾问(上海)有限公司 - 室内设计师 / 效果图设计师 / 建筑设计师&amp;高级建筑师 / 实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)PLPL|Philip Liao &amp; Partners Limited(Shanghai) 廖宜康建筑设计顾问(上海)有限公司 - 室内设计师 / 效果图设计师 / 建筑设计师&amp;高级建筑师 / 实习生" data-en="(上海)PLPL|Philip Liao &amp; Partners Limited(Shanghai) 廖宜康建筑设计顾问(上海)有限公司 - 室内设计师 / 效果图设计师 / 建筑设计师&amp;高级建筑师 / 实习生">(上海)PLPL|Philip Liao &amp;
2451 Partners Limited(Shanghai) 廖宜康建筑设计顾问(上海)有限公司 - 室内设计师 / 效果图设计师 / 建筑设计师&amp;高级建筑师 / 实习生</b><span></span></div></a><a class="side-job" data-job-id="994853" data-job-slug="job-atelier-lai" data-job-date="2026-05-27 10:00:42" data-job-modified="" data-job-modified-source="" data-job-fingerprint="5e10d1bc6af2ee70" href="/job-atelier-lai.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2023/01/LAI.jpg" alt="(上海 / 合肥)来建筑设计工作室 Atelier LAI - 项目建筑师 / 建筑师 / 实习生 / 驻场设计师" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海 / 合肥)来建筑设计工作室 Atelier LAI - 项目建筑师 / 建筑师 / 实习生 / 驻场设计师" data-en="(上海 / 合肥)来建筑设计工作室 Atelier LAI - 项目建筑师 / 建筑师 / 实习生 / 驻场设计师">(上海 / 合肥)来建筑设计工作室 Atelier LAI - 项目建筑师 / 建筑师 / 实习生 / 驻场设计师</b><span></span></div></a><a class="side-job" data-job-id="1215830" data-job-slug="job-dazhou" data-job-date="2026-05-27 09:00:10" data-job-modified="" data-job-modified-source="" data-job-fingerprint="bf5d9fd70436a05b" href="/job-dazhou.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/05/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2-dazhou.jpg" alt="(上海)大舟建筑设计事务所 - 项目建筑师 / 助理建筑师 / 建筑实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)大舟建筑设计事务所 - 项目建筑师 / 助理建筑师 / 建筑实习生" data-en="(上海)大舟建筑设计事务所 - 项目建筑师 / 助理建筑师 / 建筑实习生">(上海)大舟建筑设计事务所 - 项目建筑师 / 助理建筑师 / 建筑实习生</b><span></span></div></a><a class="side-job" data-job-id="1059049" data-job-slug="job-project" data-job-date="2026-05-26 13:50:57" data-job-modified="" data-job-modified-source="" data-job-fingerprint="cf713aa0e945786c" href="/job-project.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2024/06/%E6%8B%9B%E8%81%98%E5%B0%81%E9%9D%A2-%E6%99%AE%E7%BD%97%E5%BB%BA%E7%AD%91-20260526.jpg" alt="(北京)PROJECT普罗建筑 - 建筑实习生 / 助理建筑师 / 项目建筑师 / 媒体专员" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(北京)PROJECT普罗建筑 - 建筑实习生 / 助理建筑师 / 项目建筑师 / 媒体专员" data-en="(北京)PROJECT普罗建筑 - 建筑实习生 / 助理建筑师 / 项目建筑师 / 媒体专员">(北京)PROJECT普罗建筑 - 建筑实习生 / 助理建筑师 / 项目建筑师 / 媒体专员</b><span></span></div></a><a class="side-job" data-job-id="761016" data-job-slug="job-zxdarchitects" data-job-date="2026-05-26 10:30:27" data-job-modified="" data-job-modified-source="" data-job-fingerprint="423b494f2996e7d3" href="/job-zxdarchitects.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/05/zxd-2.jpg" alt="(北京)朱小地建筑事务所 - 品牌宣传专员 / 助理建筑师 / 建筑实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(北京)朱小地建筑事务所 - 品牌宣传专员 / 助理建筑师 / 建筑实习生" data-en="(北京)朱小地建筑事务所 - 品牌宣传专员 / 助理建筑师 / 建筑实习生">(北京)朱小地建筑事务所 - 品牌宣传专员 / 助理建筑师 / 建筑实习生</b><span></span></div></a><a class="side-job" data-job-id="782112" data-job-slug="job-chengwai" data-job-date="2026-05-25 11:30:49" data-job-modified="" data-job-modified-source="" data-job-fingerprint="4022114ed2cd710a" href="/job-chengwai.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2022/09/0901-472x303.jpg" alt="(广州)城外建筑 - 建筑师 / 助理建筑师 / 室内/环艺设计师 / 建筑实习生(长期有效)" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(广州)城外建筑 - 建筑师 / 助理建筑师 / 室内/环艺设计师 / 建筑实习生(长期有效)" data-en="(广州)城外建筑 - 建筑师 / 助理建筑师 / 室内/环艺设计师 / 建筑实习生(长期有效)">(广州)城外建筑 - 建筑师 / 助理建筑师 / 室内/环艺设计师 / 建筑实习生(长期有效)</b><span></span></div></a><a class="side-job" data-job-id="4496" data-job-slug="job-verse-design" data-job-date="2026-05-19 16:30:00" data-job-modified="" data-job-modified-source="" data-job-fingerprint="28c2f7ddc7e80189" href="/job-verse-design.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/07/verse-design-refine.jpg" alt="(上海)Verse Design 建言建筑 – 建筑师 / 助理建筑师 / 建筑实习生" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(上海)Verse Design 建言建筑 – 建筑师 / 助理建筑师 / 建筑实习生" data-en="(上海)Verse Design 建言建筑 – 建筑师 / 助理建筑师 / 建筑实习生">(上海)Verse Design 建言建筑 – 建筑师 / 助理建筑师 / 建筑实习生</b><span></span></div></a><a class="side-job" data-job-id="792389" data-job-slug="job-11architecture" data-job-date="2026-05-19 13:30:25" data-job-modified="" data-job-modified-source="" data-job-fingerprint="f5fc81a697848f8a" href="/job-11architecture.htm" target="_blank" rel="noopener"><div class="cover"><picture class="job-cover-picture"><img src="https://oss.gooood.cn/uploads/2026/05/%E4%B8%80%E5%8D%81%E4%B8%80-2.jpg" alt="(深圳)一十一建筑 - 建筑设计师 / 助理建筑师 / 室内设计师 / 平面设计师" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></picture></div><div class="side-job-text"><b data-zh="(深圳)一十一建筑 - 建筑设计师 / 助理建筑师 / 室内设计师 / 平面设计师" data-en="(深圳)一十一建筑 - 建筑设计师 / 助理建筑师 / 室内设计师 / 平面设计师">(深圳)一十一建筑 - 建筑设计师 / 助理建筑师 / 室内设计师 / 平面设计师</b><span></span></div></a></div>
2452          </div>
2453        </div>
2454      </div>
2455    </aside>
2456  </div>
2457  <section class="footer-nav" aria-label="页底导航">
2458    <div class="footer-nav-inner">
2459      <div class="footer-col">
2460        <h4 data-zh="投稿与关于" data-en="Submissions &amp; About">投稿与关于</h4>
2461        <a href="/submissions" data-zh="免费投稿" data-en="Submissions">免费投稿</a>
2462        <a href="/aboutus" data-zh="关于我们" data-en="About us">
2462关于我们</a>
2463        <a href="/work-for-gooood" data-zh="加入我们" data-en="Work for gooood">加入我们</a>
2464        <a href="/copyright" data-zh="版权声明" data-en="Copyright">版权声明</a>
2465      </div>
2466      <div class="footer-col">
2467        <h4 data-zh="服务" data-en="Services">服务</h4>
2468        <a href="/job-service-info" data-zh="雇主招聘人才" data-en="Recruitment service">雇主招聘人才</a>
2469        <a href="/ad-article" data-zh="文章付费推广" data-en="Article AD">文章付费推广</a>
2470        <a href="/materials" data-zh="建材推广" data-en="Materials">建材推广</a>
2471        <a href="/find-designer" data-zh="业主找设计师" data-en="Find designers">业主找设计师</a>
2472        <a href="/get-project-designer" data-zh="设计师接项目" data-en="Get Projects">设计师接项目</a>
2473        <a href="/talks" data-zh="试听会员" data-en="Talks">试听会员</a>
2474      </div>
2475      <div class="footer-col">
2476        <h4 data-zh="独家专辑" data-en="Series">独家专辑</h4>
2477        <a href="/category/series" data-zh="所有专辑" data-en="All Series">所有专辑</a>
2478        <a href="/category/series/gooood-interview" data-zh="访谈专辑" data-en="Interview">访谈专辑</a>
2479        <a href="/category/series/office-fact" data-zh="办公室真相" data-en="Office Fact">办公室真相</a>
2480        <a href="/category/series/under-35" data-zh="未满35岁创意人记录" data-en="Under 35">未满35岁创意人记录</a>
2481        <a href="/category/series/topic" data-zh="日常深度+" data-en="Topic">日常深度+</a>
2482        <a href="/category/series/oversea" data-zh="在海外" data-en="Oversea">在海外</a>
2483        <a href="/category/type/anniversary" data-zh="大周年" data-en="Anniversary">大周年</a>
2484      </div>
2485      <div class="footer-col">
2486        <h4 data-zh="分类" data-en="Type">分类</h4>
2487        <a href="/category/jobs" data-zh="工作" data-en="Jobs">工作</a>
2488        <a href="/category/type/architecture" data-zh="建筑" data-en="Architecture">建筑</a>
2489        <a href="/category/type/landscape" data-zh="景观" data-en="Landscape">景观</a>
2490        <a href="/category/type/archive" data-zh="合集" data-en="Archive">合集</a>
2491        <a href="/category/type/art" data-zh="艺术" data-en="Art">艺术</a>
2492        <a href="/category/type/design" data-zh="设计" data-en="Design">设计</a>
2493      </div>
2494      <div class="footer-col">
2495        <h4 data-zh="关注我们" data-en="Follow us">关注我们</h4>
2496        <a href="http://weibo.com/goooodgooood" target="_blank" rel="noopener" data-zh="微博" data-en="Weibo">微博</a>
2497        <a href="https://oss.gooood.cn/uploads/2020/06/weixin1.jpg" target="_blank" rel="noopener" data-zh="微信" data-en="WeChat">微信</a>
2498        <a href="https://www.xiaohongshu.com/user/profile/63ede8e3000000001001ce69?xhsshare=WeixinSession&amp;appuid=641404080000000014013693&amp;apptime=1730862558" target="_blank" rel="noopener" data-zh="小红书" data-en="Xiaohongshu">小红书</a>
2499        <a href="https://www.instagram.com/goooodofficial/" target="_blank" rel="noopener" data-zh="Instagram" data-en="Instagram">Instagram</a>
2500        <a href="https://www.pinterest.com/gooood0103/pins/" target="_blank" rel="noopener" data-zh="Pinterest" data-en="Pinterest">Pinterest</a>
2501      </div>
2502    </div>
2503  </section>
2504  <footer class="footer"><a href="/aboutus" data-zh="关于我们" data-en="About us">关于我们</a> | ©2010-2026 谷德设计网 | <a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener">京ICP备17062545号-1</a> | <a href="https://www.beian.gov.cn/portal/registerSystemInfo?recordcode=11010502061450" target="_blank" rel="noopener">京公网安备11010502061450号</a></footer>
2505</div>
2506  
2506<script data-v10-ssr-snapshot="1">
2507  document.documentElement.dataset.ssrHomeData = 'connected';
2508  document.documentElement.dataset.ssrHomeSource = "nuxt-v10-runtime:archive-full-page:categories:news";
2509  document.documentElement.dataset.liveHomeData = 'connected';
2510  document.documentElement.dataset.liveHomeSource = "nuxt-v10-runtime:archive-full-page:categories:news";
2511</script>
vendor: 1 bytes, line 2511
2511
2512<script>
2513  (() => {
2514    const latestJobTitles = [
2515      '如恩设计上海招聘室内设计师',
2516      'gad · line+ studio 杭州招聘项目建筑师',
2517      'OPEN Architecture 北京招聘建筑设计师',
2518      '大舍建筑上海招聘项目负责人',
2519      '直向建筑北京招聘初级建筑师',
2520      'Heatherwick Studio 上海招聘高级设计师',
2521      'BIG 深圳招聘项目建筑师',
2522      '藤本壮介建筑上海招聘建筑设计师',
2523      'Snøhetta 香港招聘项目建筑师',
2524      '非常建筑北京招聘建筑师',
2525      '刘家琨建筑成都招聘项目建筑师',
2526      '隈研吾建筑都市东京招聘建筑设计师',
2527      'OMA 香港招聘高级建筑师',
2528      'MVRDV 上海招聘项目负责人',
2529      '迹 · 建筑事务所北京招聘建筑师',
2530      '亘建筑事务所上海招聘建筑师',
2531      '出品建筑深圳招聘项目建筑师',
2532      'SOM 上海招聘城市设计师',
2533      'AECOM 北京招聘景观设计师',
2534      'KPF 上海招聘建筑设计师',
2535      'Gensler 北京招聘室内设计师',
2536      'Perkins&Will 上海招聘项目建筑师',
2537      'HPP 深圳招聘建筑设计师',
2538      'Chapman Taylor 上海招聘高级建筑师',
2539      '筑境设计杭州招聘项目负责人',
2540      '都设设计上海招聘建筑师',
2541      '山水秀北京招聘中级建筑师',
2542      '间筑设计上海招聘室内设计师',
2543      '形构设计上海招聘建筑设计师',
2544      'Link-Arc 杭州招聘项目建筑师',
2545      '地平线气象成都招聘空间设计师',
2546      '筑见视野北京招聘助理建筑师',
2547      'Mind Studio 上海招聘室内设计师',
2548      'PMT Partners 深圳招聘景观设计师',
2549      'PILLS 北京招聘品牌空间设计师',
2550      '墨工工作室广州招聘建筑师',
2551      'F.O.G. 上海招聘建筑设计师',
2552      'LYCS Architecture 杭州招聘项目负责人',
2553      '都市实践深圳招聘主创建筑师',
2554      '源计划建筑广州招聘建筑设计师',
2555      '本哲建筑上海招聘项目建筑师',
2556      '一持工作室北京招聘室内设计师',
2557      '立木设计杭州招聘景观设计师',
2558      '致正建筑上海招聘助理建筑师',
2559      '有方空间深圳招聘品牌编辑',
2560      '平介设计上海招聘室内主案',
2561      '原作设计成都招聘建筑设计师',
2562      '方所营造北京招聘项目经理',
2563      '空间站建筑南京招聘建筑师',
2564      '山川设计广州招聘景观设计师',
2565      '众建筑北京招聘建筑实习生',
2566      'goa 大象设计杭州招聘建筑师',
2567      'line+ 上海招聘室内设计师',
2568      'MDO 木君上海招聘项目建筑师',
2569      '水石设计上海招聘城市设计师',
2570      '栖城设计深圳招聘景观设计师',
2571      '裸筑更新北京招聘项目负责人',
2572      '米凹工作室杭州招聘建筑设计师',
2573      '森上建筑成都招聘室内设计师',
2574      '万社设计上海招聘品牌空间设计师',
2575      'atelier tao+c 上海招聘项目建筑师',
2576      'BAU 深圳招聘城市设计师',
2577      'Crossboundaries 北京招聘建筑师',
2578      'Wutopia Lab 上海招聘主创建筑师',
2579      '三文建筑北京招聘项目负责人',
2580      '如是设计杭州招聘室内设计师',
2581      '大观景观深圳招聘景观设计师',
2582      '未觉建筑上海招聘助理建筑师',
2583      '素建筑广州招聘建筑设计师',
2584      '时地建筑成都招聘项目建筑师'
2585    ];
2586
2587    const backendSnapshot = window.__GOOOOD_V10_BACKEND_SNAPSHOT__ || null;
2588    let backendRenderedLatestJobs = false;
2589    let language = 'zh';
2590
2591    const decodeHtml = (value) => {
2592      const node = document.createElement('textarea');
2593      node.innerHTML = String(value || '');
2594      return node.value.trim();
2595    };
2596    const escapeHtml = (value) => String(value || '').replace(/[&<>"']/g, (char) => ({
2597      '&': '&amp;',
2598      '<': '&lt;',
2599      '>': '&gt;',
2600      '"': '&quot;',
2601      "'": '&#39;'
2602    })[char]);
2603    const zhText = (value) => decodeHtml(value).split('|')[0].trim();
2604    const enText = (value, fallback = '') => {
2605      const parts = decodeHtml(value).split('|');
2606      return (parts[1] || fallback || parts[0] || '').trim();
2607    };
2608    const setBilingualText = (node, zh, en = zh) => {
2609      if (!node) return;
2610      node.dataset.zh = zh || '';
2611      node.dataset.en = en || zh || '';
2612      node.textContent = language === 'en' ? node.dataset.en : node.dataset.zh;
2613    };
2614    const formatDate = (value) => {
2615      const date = value ? new Date(value) : null;
2616      if (!date || Number.isNaN(date.getTime())) return '';
2617      const y = date.getFullYear();
2618      const m = String(date.getMonth() + 1).padStart(2, '0');
2619      const d = String(date.getDate()).padStart(2, '0');
2620      return `${y}.${m}.${d}`;
2621    };
2622    const postUrl = (slug) => slug ? `https://www.gooood.cn/${slug}.htm` : '#';
2623    const communityUrl = (slug) => slug ? `https://www.gooood.cn/community/${slug}` : '#';
2624    const criticalImageReplacements = window.__GOOOOD_V10_CRITICAL_IMAGES__ || {};
2625    const decodeCriticalImageUrl = (url) => {
2626      try {
2627        return decodeURI(url || '');
2628      } catch (error) {
2629        return url || '';
2630      }
2631    };
2632    const optimizeCriticalImage = (url) => criticalImageReplacements[url] || criticalImageReplacements[decodeCriticalImageUrl(url)] || url;
2633    const postImage = (post) => optimizeCriticalImage(post?.summary_image_url || post?.featured_image?.sizes?.medium?.source_url || post?.featured_image?.source_url || post?.cover || post?.thumbnail || '');
2634    const jobTitle = (job) => job?.title?.rendered || job?.title?.fulltitle || job?.title || '';
2635    const jobImage = (job) => job?.thumb || job?.thumbnail || job?.cover || job?.featured_image?.sizes?.['size-310']?.source_url || job?.featured_image?.source_url || '';
2636    const compactTitle = (value) => zhText(value);
2637    const applyImageAttrs = (img, width, height, loading = 'lazy', fetchPriority = 'low') => {
2638      if (!img) return;
2639      if (width && !img.hasAttribute('width')) img.setAttribute('width', String(width));
2640      if (height && !img.hasAttribute('height')) img.setAttribute('height', String(height));
2641      img.setAttribute('decoding', 'async');
2642      img.setAttribute('loading', loading);
2643      img.setAttribute('fetchpriority', fetchPriority);
2644    };
2645	    const normalizeV10ImagePerformanceAttrs = () => {
2646	      document.querySelectorAll('.top-slider img').forEach((img, index) => {
2647	        applyImageAttrs(img, 2000, 600, index === 0 ? 'eager' : 'lazy', 'low');
2648	      });
2649	      document.querySelectorAll('.article .cover img').forEach((img, index) => {
2650	        applyImageAttrs(img, index < 4 ? 650 : 472, index < 4 ? 417 : 303, index === 0 ? 'eager' : 'lazy', index === 0 ? 'auto' : 'low');
2651	      });
2652      document.querySelectorAll('.album .cover img').forEach((img) => applyImageAttrs(img, 310, 200));
2653      document.querySelectorAll('.side-job .cover img').forEach((img) => applyImageAttrs(img, 150, 96));
2654      document.querySelectorAll('.home-top-ad-image img, .home-inline-ad-image img').forEach((img) => applyImageAttrs(img, 1100, 220));
2655      document.querySelectorAll('img:not([width]), img:not([height])').forEach((img) => {
2656        if (img.closest('.side-job')) return;
2657        if (img.naturalWidth && img.naturalHeight) {
2658          applyImageAttrs(img, img.naturalWidth, img.naturalHeight);
2659        } else {
2660          img.addEventListener('load', () => applyImageAttrs(img, img.naturalWidth, img.naturalHeight), { once: true });
2661        }
2662      });
2663    };
2664    const normalizeUrl = (value) => {
2665      const url = String(value || '').trim();
2666      if (!url) return '#';
2667      if (url.startsWith('mailto:') || url.startsWith('tel:') || url.startsWith('//')) return url;
2668      try {
2669        const parsed = new URL(url, 'https://www.gooood.cn');
2670        if (parsed.origin === 'https://www.gooood.cn') {
2671          return `${parsed.pathname}${parsed.search}${parsed.hash}` || '/';
2672        }
2673      } catch {}
2674      return url;
2675    };
2676    const jobPostUrl = (slug) => {
2677      const normalized = String(slug || '').trim().replace(/^\/+/, '').replace(/^jobs\//, '').replace(/\.htm$/, '');
2678      return /^[a-z0-9][a-z0-9_-]*$/i.test(normalized) ? `https://www.gooood.cn/${normalized}.htm` : '#';
2679    };
2680    const normalizeJobUrl = (value) => {
2681      const normalized = normalizeUrl(value);
2682      try {
2683        const parsed = new URL(normalized, 'https://www.gooood.cn');
2684        if (parsed.origin !== 'https://www.gooood.cn') return normalized;
2685        const match = parsed.pathname.match(/^\/jobs\/([a-z0-9][a-z0-9_-]*)\/?$/i);
2686        return match ? `/${match[1]}.htm${parsed.search}${parsed.hash}` : normalized;
2687      } catch {
2688        return normalized;
2689      }
2690    };
2691    const buildPostLink = (post) => {
2692      if (!post) return '#';
2693      if (post.linkurl) return normalizeUrl(post.linkurl);
2694      if (post.link) return normalizeUrl(post.link);
2695      return post.slug ? postUrl(post.slug) : '#';
2696    };
2697    const pageUrl = (page, pageInfo = {}) => {
2698      const pageNumber = Number(page) || 1;
2699      const basePath = String(pageInfo.basePath || '').replace(/\/$/, '');
2700      const pagePathStyle = String(pageInfo.pagePathStyle || 'page-segment');
2701      if (basePath) {
2702        if (pageNumber <= 1) return basePath || '/';
2703        const suffix = pagePathStyle === 'trailing-number' ? `/${pageNumber}` : `/page/${pageNumber}`;
2704        return `${basePath}${suffix}`;
2705      }
2706      return pageNumber <= 1 ? '/' : `/page/${pageNumber}`;
2707    };
2708    const currentPageFromLocation = () => {
2709      const match = window.location.pathname.match(/\/page\/(\d+)\/?$/) || window.location.pathname.match(/\/(\d+)\/?$/);
2710      return match ? Number(match[1]) || 1 : 1;
2711    };
2712    const authoritativeAdArray = (sources, label) => {
2713      const source = sources.find((items) => items !== undefined);
2714      if (source === undefined) return [];
2715      if (!Array.isArray(source)) throw new Error(`${label} advertisement source is not an array`);
2716      return source;
2717    };
2718    const getCarouselAds = (snapshot) => {
2719      const sources = [
2720        snapshot?.home?.carouselAds,
2721        snapshot?.ads?.home_banners,
2722        snapshot?.indexAds?.home_banners,
2723        snapshot?.ads?.['首页轮播图广告'],
2724        snapshot?.indexAds?.['首页轮播图广告'],
2725        snapshot?.adsByPosition?.home_banners,
2726        snapshot?.adsByPosition?.home_carousel,
2727        snapshot?.adsByPosition?.['34627']
2728      ];
2729      return authoritativeAdArray(sources, 'home carousel').filter((ad) => ad?.acf?.ad_image || ad?.image || ad?.featured_image?.source_url || ad?.cover || ad?.gallery?.[0]?.full_url).slice(0, 20);
2730    };
2731
2732    const getHomeTopAds = (snapshot) => {
2733      const sources = [
2734        snapshot?.home?.homeTopAds,
2735        snapshot?.ads?.home_list_0,
2736        snapshot?.indexAds?.home_list_0,
2737        snapshot?.ads?.['首页轮播图下方广告'],
2738        snapshot?.indexAds?.['首页轮播图下方广告'],
2739        snapshot?.adsByPosition?.home_list_0,
2740        snapshot?.adsByPosition?.['34628']
2741      ];
2742      return authoritativeAdArray(sources, 'home top').filter((ad) => ad?.acf?.ad_content || ad?.acf?.ad_image || ad?.image || ad?.featured_image?.source_url || ad?.cover || ad?.gallery?.[0]?.full_url).slice(0, 2);
2743    };
2744
2745    const getHomeInlineAds = (snapshot, field, slug, positionId, label) => {
2746      const sources = [
2747        snapshot?.home?.[field],
2748        snapshot?.ads?.[slug],
2749        snapshot?.indexAds?.[slug],
2750        snapshot?.ads?.[label],
2751        snapshot?.indexAds?.[label],
2752        snapshot?.adsByPosition?.[slug],
2753        snapshot?.adsByPosition?.[positionId]
2754      ];
2755      return authoritativeAdArray(sources, `home ${positionId}`).filter((ad) => ad?.acf?.ad_content || ad?.acf?.ad_image || ad?.image || ad?.featured_image?.source_url || ad?.cover || ad?.gallery?.[0]?.full_url).slice(0, 1);
2756    };
2757
2758    const adText = (value) => String(value || '').trim();
2759    const adFnv1a32 = (value, seed) => {
2760      let hash = seed >>> 0;
2761      for (let index = 0; index < value.length; index += 1) {
2762        hash ^= value.charCodeAt(index);
2763        hash = Math.imul(hash, 0x01000193);
2764      }
2765      return (hash >>> 0).toString(16).padStart(8, '0');
2766    };
2767    const adFingerprint = (ad = {}) => {
2768      const canonical = [
2769        adText(ad.id),
2770        adText(ad.slug),
2771        adText(ad.acf?.ad_name),
2772        adText(typeof ad.title === 'string' ? ad.title : ad.title?.fulltitle || ad.title?.rendered),
2773        adText(ad.acf?.ad_link || ad.linkurl || ad.imagelink || ad.url || ad.href || ad.link),
2774        adText(ad.acf?.ad_image || ad.image || ad.cover || ad.featured_image?.source_url || ad.gallery?.[0]?.full_url),
2775        adText(ad.acf?.ad_content)
2776      ].join('\u001f');
2777      return `${adFnv1a32(canonical, 0x811c9dc5)}${adFnv1a32(canonical, 0x9e3779b9)}`;
2778    };
2779    const adSetFingerprint = (ads = []) => {
2780      const canonical = ads.map((ad) => `${adText(ad.id)}:${adFingerprint(ad)}`).join('\u001e');
2781      return `${adFnv1a32(canonical, 0x811c9dc5)}${adFnv1a32(canonical, 0x9e3779b9)}`;
2782    };
2783    const clearAdIdentity = (node) => {
2784      ['adRecordId', 'adRecordIds', 'adSlug', 'adModified', 'adTitle', 'adHref', 'adFingerprint', 'backendAdContent'].forEach((key) => {
2785        delete node.dataset[key];
2786      });
2787    };
2788    const applyAdState = ({ node, snapshot, ads, positionId, slug, sourceLabel }) => {
2789      const freshness = snapshot?.adFreshnessByPosition?.[positionId] || {};
2790      const first = ads[0];
2791      clearAdIdentity(node);
2792      node.dataset.backendAdPosition = positionId;
2793      node.dataset.backendAdSource = `dashboard.api.api-advert-adposition.php?slugName=${slug}`;
2794      node.dataset.backendAdStatus = first ? 'connected' : 'empty';
2795      node.dataset.adItemCount = String(ads.length);
2796      node.dataset.wpTagId = positionId;
2797      node.dataset.wpTermSlug = slug;
2798      node.dataset.adSource = freshness.source || sourceLabel || `legacy-api:${slug}`;
2799      node.dataset.adSetFingerprint = freshness.setFingerprint || adSetFingerprint(ads);
2800      node.dataset.adSourceFetchedAt = freshness.sourceFetchedAt || snapshot?.fetchedAt || new Date().toISOString();
2801      node.dataset.adCacheStatus = freshness.cacheStatus || 'direct-request';
2802	      if (first) {
2803	        node.dataset.adRecordId = String(first.id || '');
2804	        node.dataset.adRecordIds = ads.map((ad) =>
2804 String(ad.id || '')).filter(Boolean).join(',');
2805	        node.dataset.adSlug = String(first.slug || '');
2806        node.dataset.adModified = String(first.modified || '');
2807        node.dataset.adTitle = zhText(first.acf?.ad_name || first.name || first.title?.fulltitle || first.title?.rendered || first.title || '');
2808        node.dataset.adHref = normalizeUrl(first.acf?.ad_link || first.linkurl || first.imagelink || first.url || first.href || '#');
2809        node.dataset.adFingerprint = first.acf?.advertisement_fingerprint || adFingerprint(first);
2810      }
2811      node.hidden = !first;
2812      if (first) node.removeAttribute('aria-hidden');
2813      else node.setAttribute('aria-hidden', 'true');
2814    };
2815
2816    const renderBackendCarousel = (snapshot) => {
2817      const ads = getCarouselAds(snapshot);
2818      const slider = document.querySelector('.top-slider');
2819      if (!slider) return;
2820      Array.from(slider.querySelectorAll('.slide')).forEach((node) => node.remove());
2821      const dotsWrap = slider.querySelector('.top-slider-dots');
2822      if (dotsWrap) dotsWrap.innerHTML = '';
2823      applyAdState({ node: slider, snapshot, ads, positionId: '34627', slug: 'home_banners', sourceLabel: 'legacy-api:home_banners' });
2824      if (!ads.length) return;
2825      const controls = slider.querySelector('.slider-controls');
2826      ads.forEach((ad, index) => {
2827        const title = zhText(ad.acf?.ad_name || ad.name || ad.title?.fulltitle || ad.title?.rendered || ad.title || `首页轮播图广告 ${index + 1}`);
2828        const image = optimizeCriticalImage(ad.acf?.ad_image || ad.image || ad.featured_image?.source_url || ad.featured_image?.sizes?.medium?.source_url || ad.cover || ad.gallery?.[0]?.full_url || '');
2829        const href = normalizeUrl(ad.acf?.ad_link || ad.linkurl || ad.imagelink || ad.url || ad.href || '#');
2830        const slide = document.createElement('div');
2831	        slide.className = `slide${index === 0 ? ' is-active' : ''}`;
2832        slide.dataset.adRecordId = String(ad.id || '');
2833        slide.dataset.adSlug = String(ad.slug || '');
2834        slide.dataset.adModified = String(ad.modified || '');
2835        slide.dataset.adTitle = title;
2836        slide.dataset.adFingerprint = ad.acf?.advertisement_fingerprint || adFingerprint(ad);
2837	        const imageSource = index === 0
2838	          ? `src="${escapeHtml(image)}" loading="eager" fetchpriority="low"`
2839	          : `data-src="${escapeHtml(image)}" loading="lazy" fetchpriority="low"`;
2840        slide.innerHTML = `<a class="slide-link" href="${escapeHtml(href)}" target="_blank" rel="noopener"><img ${imageSource} alt="${escapeHtml(title)}" width="2000" height="600" decoding="async" loading="lazy" fetchpriority="low"></a>`;
2841        slider.insertBefore(slide, controls);
2842      });
2843      if (dotsWrap) {
2844        dotsWrap.innerHTML = ads.map((_, index) => `<button class="${index === 0 ? 'is-active' : ''}" type="button" data-slide-dot="${index}" aria-label="第 ${index + 1} 张"></button>`).join('');
2845      }
2846    };
2847
2848	    const renderBackendHomeTopAd = (snapshot) => {
2849	      const ads = getHomeTopAds(snapshot);
2850	      const section = document.querySelector('.ad-embed.hero-below');
2851	      if (!section) return;
2852	      const ad = ads[0];
2853	      applyAdState({ node: section, snapshot, ads, positionId: '34628', slug: 'home_list_0', sourceLabel: 'legacy-api:home_list_0' });
2854	      if (!ad) {
2855	        section.replaceChildren();
2856	        return;
2857	      }
2858	      const contentKinds = [];
2859	      const bodies = ads.map((item) => {
2860	        const html = typeof item.acf?.ad_content === 'string' ? item.acf.ad_content.trim() : '';
2861	        if (html) {
2862	          contentKinds.push('acf.ad_content');
2863	          return html;
2864	        }
2865	        const image = item.acf?.ad_image || item.image || item.featured_image?.source_url || item.featured_image?.sizes?.medium?.source_url || item.cover || item.gallery?.[0]?.full_url || '';
2866	        if (!image) return '';
2867	        contentKinds.push('ad_image');
2868	        const title = zhText(item.acf?.ad_name || item.name || item.title?.fulltitle || item.title?.rendered || item.title || '首页轮播图下方广告');
2869	        const href = normalizeUrl(item.acf?.ad_link || item.linkurl || item.imagelink || item.url || item.href || '#');
2870	        return `<a class="home-top-ad-image" href="${escapeHtml(href)}" target="_blank" rel="noopener"><img src="${escapeHtml(image)}" alt="${escapeHtml(title)}" width="1100" height="220" decoding="async" loading="lazy" fetchpriority="low"></a>`;
2871	      }
2871).filter(Boolean);
2872	      section.innerHTML = bodies.join('');
2873	      const uniqueContentKinds = Array.from(new Set(contentKinds));
2874	      section.dataset.backendAdContent = uniqueContentKinds.length === 1 ? uniqueContentKinds[0] : 'mixed';
2875	    };
2876
2877    const renderBackendInlineAd = ({ snapshot, selector, field, slug, positionId, label }) => {
2878      const ads = getHomeInlineAds(snapshot, field, slug, positionId, label);
2879      const section = document.querySelector(selector);
2880      if (!section) return;
2881      const ad = ads[0];
2882      applyAdState({ node: section, snapshot, ads, positionId, slug, sourceLabel: `legacy-api:${slug}` });
2883      if (!ad) {
2884        section.replaceChildren();
2885        return;
2886      }
2887      const html = typeof ad.acf?.ad_content === 'string' ? ad.acf.ad_content.trim() : '';
2888      if (html) {
2889        section.innerHTML = html;
2890        section.dataset.backendAdContent = 'acf.ad_content';
2891        return;
2892      }
2893      const image = ad.acf?.ad_image || ad.image || ad.featured_image?.source_url || ad.featured_image?.sizes?.medium?.source_url || ad.cover || ad.gallery?.[0]?.full_url || '';
2894      if (!image) return;
2895      const title = zhText(ad.acf?.ad_name || ad.name || ad.title?.fulltitle || ad.title?.rendered || ad.title || label);
2896      const href = normalizeUrl(ad.acf?.ad_link || ad.linkurl || ad.imagelink || ad.url || ad.href || '#');
2897      section.innerHTML = `<a class="home-inline-ad-image" href="${escapeHtml(href)}" target="_blank" rel="noopener"><img src="${escapeHtml(image)}" alt="${escapeHtml(title)}" width="1100" height="220" decoding="async" loading="lazy" fetchpriority="low"></a>`;
2898      section.dataset.backendAdContent = 'ad_image';
2899    };
2900
2901    const renderBackendPosts = (posts = []) => {
2902      const articles = Array.from(document.querySelectorAll('.article'));
2903      posts.slice(0, articles.length).forEach((post, index) => {
2904        const article = articles[index];
2905        const titleSource = post.title?.fulltitle || post.title?.rendered || post.title;
2906        const subtitleSource = post.goooodSubtitle?.zh || post.homeSubtitleZh || post.excerpt?.rendered || post.excerpt;
2907        const categorySource = post.taxonomies?.category?.[0]?.name || '';
2908        const title = zhText(titleSource);
2909        const titleEn = enText(titleSource, title);
2910        const subtitle = zhText(subtitleSource);
2911        const subtitleEn = post.goooodSubtitle?.en || post.homeSubtitleEn || enText(post.excerpt?.rendered || post.excerpt || subtitleSource, subtitle);
2912        const category = zhText(categorySource);
2913        const categoryEn = enText(categorySource, category);
2914        const url = buildPostLink(post);
2915        const image = postImage(post);
2916        const titleLink = article.querySelector('h3 a');
2917        const coverLink = article.querySelector(':scope > .cover a');
2918        const coverImg = article.querySelector(':scope > .cover img, :scope > .cover .article-cover-link img');
2919        const kicker = article.querySelector('.kicker');
2920        const subtitleNode = article.querySelector('.article-subtitle');
2921        const time = article.querySelector('time');
2922        article.dataset.backendPostId = String(post.id || '');
2923        article.dataset.backendPostSlug = post.slug || '';
2924        article.dataset.backendPrimaryTypeId = String(post.primary_type_id || post.type?.[0] || post.taxonomies?.type?.[0]?.id || post.taxonomies?.type?.[0]?.term_id || '');
2925        if (titleLink) {
2926          titleLink.href = url;
2927          titleLink.target = '_blank';
2928          titleLink.rel = 'noopener';
2929          setBilingualText(titleLink, title, titleEn);
2930        }
2931        if (coverLink) {
2932          coverLink.href = url;
2933          coverLink.target = '_blank';
2934          coverLink.rel = 'noopener';
2935          coverLink.setAttribute('aria-label', title);
2936        }
2937	        if (coverImg && image) {
2938	          coverImg.src = image;
2939	          coverImg.alt = title;
2940	          applyImageAttrs(coverImg, index < 4 ? 650 : 472, index < 4 ? 417 : 303, index === 0 ? 'eager' : 'lazy', index === 0 ? 'auto' : 'low');
2941	        }
2942        if (kicker && category) setBilingualText(kicker, category, c
2942ategoryEn);
2943        if (subtitleNode) setBilingualText(subtitleNode, subtitle, subtitleEn);
2944        if (time) {
2945          const label = formatDate(post.date);
2946          time.textContent = label;
2947          if (post.date) time.dateTime = post.date;
2948          }
2949      });
2950      articles.slice(posts.length).forEach((article) => {
2951        const row = article.closest('section.row');
2952        article.remove();
2953        if (row && !row.querySelector('.article')) row.remove();
2954      });
2955    };
2956
2957    const buildJobLink = (job) => {
2958      if (!job) return '#';
2959      if (job.linkurl) return normalizeJobUrl(job.linkurl);
2960      if (job.link) return normalizeJobUrl(job.link);
2961      return job.slug ? jobPostUrl(job.slug) : '#';
2962    };
2963
2964    const renderBackendTextJobs = (jobs = [], showNumbers = {}, jumpUrls = {}) => {
2965      const list = document.querySelector('.job-cols');
2966      if (!list || !jobs.length) return;
2967	      const parsedRowsPerColumn = Number(showNumbers.options_column_count);
2968	      const rowsPerColumn = Number.isFinite(parsedRowsPerColumn) && parsedRowsPerColumn >= 1 ? Math.floor(parsedRowsPerColumn) : 13;
2969      const count = Math.min(jobs.length, rowsPerColumn * 3);
2970      const columns = [[], [], []];
2971      jobs.slice(0, count).forEach((job, index) => columns[Math.floor(index / rowsPerColumn)].push(job));
2972      list.innerHTML = columns.map((column) => `
2973	        <div class="job-col" data-admin-setting="options_column_count" data-configured-count="${rowsPerColumn}">
2974          ${column.map((job) => { const source = jobTitle(job); const zh = zhText(source); const en = enText(source, zh); return `<a class="job-line" href="${escapeHtml(buildJobLink(job))}" target="_blank" rel="noopener"><b data-zh="${escapeHtml(zh)}" data-en="${escapeHtml(en)}">${escapeHtml(language === 'en' ? en : zh)}</b><em></em></a>`; }).join('')}
2975        </div>
2976      `).join('');
2977      const submit = document.querySelector('.job-head .job-submit');
2978      const all = document.querySelector('.job-head .job-all');
2979      if (submit && jumpUrls.options_new_recommend_linkurl) submit.href = jumpUrls.options_new_recommend_linkurl;
2980      if (all) all.href = 'https://www.gooood.cn/category/jobs';
2981    };
2982
2983    const latestShowNumbers = (snapshot = {}) => {
2984      return snapshot?.home?.showNumbers || snapshot?.showNumbers || {};
2985    };
2986
2987    const renderBackendSideJobs = (jobs = [], showNumbers = {}) => {
2988      const list = document.querySelector('.side-jobs.home-pinned');
2989      if (!list || !jobs.length) return;
2990      const backendJobCount = Number(
2991        showNumbers.options_jobs_index_number ||
2992        latestShowNumbers(backendSnapshot).options_jobs_index_number
2993      ) || 0;
2994      const targetCount = backendJobCount || Number(list.dataset.defaultCount) || 74;
2995      const normalizedJobs = jobs.slice(0, targetCount);
2996      list.dataset.source = snapshot?.home?.showNumbersSource || (showNumbers.options_jobs_index_number ? 'live-home-runtime.showNumbers' : 'window.__GOOOOD_V10_BACKEND_SNAPSHOT__.home.homeSideJobs');
2997      list.dataset.renderedCount = String(normalizedJobs.length);
2998      list.dataset.backendCount = String(jobs.length);
2999      list.dataset.configuredCount = String(targetCount);
3000      list.innerHTML = normalizedJobs.map((job) => {
3001        const titleSource = jobTitle(job);
3002        const title = zhText(titleSource);
3003        const titleEn = enText(titleSource, title);
3004        const image = jobImage(job);
3005        return `<a class="side-job" href="${escapeHtml(buildJobLink(job))}" target="_blank" rel="noopener"><div class="cover"><img src="${escapeHtml(image)}" alt="${escapeHtml(title)}" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></div><div class="side-job-text"><b data-zh="${escapeHtml(title)}" data-en="${escapeHtml(titleEn)}">${escapeHtml(language === 'en' ? titleEn : title)}</b><span></span></div></a>`;
3006      }).join('');
3007      backendRenderedLatestJobs = true;
3008    };
3009
3010    const collectPinnedJobs = (snapshot) => {
3011      const home = snapshot?.home || {};
3012      const candidates = [
3013        home.pinnedJobs,
3014        home.topJobs,
3015        home.featuredJobs,
3016        home.homeTopJobs,
3017        home.homePinnedJobs,
3018        home.topRecruitJobs,
3019        snapshot?.pinnedJobs,
3020        snapshot?.topJobs
3021      ];
3022      return candidates.find((items) => Array.isArray(items) && items.length) || [];
3023    };
3024
3025    const renderBackendPinnedJobs = (jobs = [], jumpUrls = {}) => {
3026      const list = document.querySelector('.side-jobs.pinned');
3027      const section = list?.closest('.pinned-jobs-section');
3028      if (!list || !section) return;
3029      const normalizedJobs = Array.isArray(jobs) ? jobs.filter(Boolean) : [];
3030      const topLink = section.querySelector('.side-title-action');
3031      if (topLink) {
3032        topLink.href = jumpUrls.options_top_recruit_linkurl || jumpUrls.options_buy_top_linkurl || topLink.href;
3033      }
3034      if (!normalizedJobs.length) {
3035        list.innerHTML = '';
3036        section.hidden = true;
3037        section.dataset.renderedCount = '0';
3038        section.dataset.emptyState = 'no-pinned-jobs';
3039        return;
3040      }
3041      section.hidden = false;
3042      section.dataset.renderedCount = String(normalizedJobs.length);
3043      section.dataset.emptyState = '';
3044      list.innerHTML = normalizedJobs.map((job) => {
3045        const titleSource = jobTitle(job);
3046        const title = zhText(titleSource);
3047        const titleEn = enText(titleSource, title);
3048        const image = jobImage(job);
3049        return `<a class="side-job" href="${escapeHtml(buildJobLink(job))}" target="_blank" rel="noopener"><div class="cover"><img src="${escapeHtml(image)}" alt="${escapeHtml(title)}" width="150" height="96" decoding="async" loading="lazy" fetchpriority="low"></div><div class="side-job-text"><b data-zh="${escapeHtml(title)}" data-en="${escapeHtml(titleEn)}">${escapeHtml(language === 'en' ? titleEn : title)}</b><span></span></div></a>`;
3050      }).join('');
3051    };
3052
3053    const renderPagination = (pageInfo = {}) => {
3054      const nav = document.querySelector('.pagination');
3055      if (!nav) return;
3056      const current = Math.max(1, Number(pageInfo.page || currentPageFromLocation() || 1));
3057      const totalPages = Math.max(1, Number(pageInfo.totalPages || pageInfo.total_pages || nav.dataset.totalPages || 1));
3058      const totalItems = Number(pageInfo.total || nav.dataset.totalItems || 0);
3059      const items = [];
3060      items.push(current > 1
3061        ? `<a href="${escapeHtml(pageUrl(current - 1, pageInfo))}" aria-label="上一页">←</a>`
3062        : '<span class="page-item disabled" aria-disabled="true">←</span>');
3063      items.push(`<a class="active" href="${escapeHtml(pageUrl(current, pageInfo))}">${current}</a>`);
3064      [current + 1, current + 2].forEach((page) => {
3065        if (page <= totalPages) items.push(`<a href="${escapeHtml(pageUrl(page, pageInfo))}">${page}</a>`);
3066      });
3067      if (current + 3 < totalPages) items.push('<span class="page-item dots">...</span>');
3068      if (current + 2 < totalPages) items.push(`<a href="${escapeHtml(pageUrl(totalPages, pageInfo))}">${totalPages}</a>`);
3069      items.push(current < totalPages
3070        ? `<a href="${escapeHtml(pageUrl(current + 1, pageInfo))}" aria-label="下一页">→</a>`
3071        : '<span class="page-item disabled" aria-disabled="true">→</span>');
3072      items.push(`<span class="page-count">${current}/${totalPages}</span>`);
3073      items.push(`<label class="page-jump"><input type="number" min="1" max="${totalPages}" placeholder="5" aria-label="跳转页码"><button type="button" data-zh="跳页" data-en="Go">${language === 'en' ? 'Go' : '跳页'}</button></label>`);
3074      nav.dataset.currentPage = String(current);
3075      nav.dataset.totalPages = String(totalPages);
3076      if (totalItems) nav.dataset.totalItems = String(totalItems);
3077      nav.innerHTML = items.join('');
3078      const input = nav.querySelector('.page-jump input');
3079      const button = nav.querySelector('.page-jump button');
3080      const go = () => {
3081        const target = Math.min(totalPages, Math.max(1, Number(input?.value || 1)));
3082        window.location.href = pageUrl(target, pageInfo);
3083      };
3084      button?.addEventListener('click', go);
3085      input?.addEventListener('keydown', (event) => {
3086        if (event.key === 'Enter') go();
3087      });
3088    };
3089
3090    const renderBackendSeries = (posts = []) => {
3091      const panel = document.querySelector('.sidebar .panel:nth-of-type(1)');
3092      if (!panel || !posts.length) return;
3093      const head = panel.querySelector('.panel-head');
3094      const allLink = head?.querySelector('a');
3095      if (allLink) {
3096        allLink.href = 'https://www.gooood.cn/category/series';
3097        allLink.target = '_blank';
3098        allLink.rel = 'noopener';
3099      }
3100      panel.innerHTML = '';
3101      if (head) panel.appendChild(head);
3102      posts.slice(0, 3).forEach((post) => {
3103        const title = post.titleZh || zhText(post.title);
3104        const titleEn = post.titleEn || enText(post.title, title);
3105        const subtitle = post.excerptZh || zhText(post.excerpt);
3106        const subtitleEn = post.excerptEn || enText(post.excerpt, subtitle);
3107        const link = document.createElement('a');
3108        link.className = 'album';
3109        link.href = normalizeUrl(post.url || post.link || (post.slug ? postUrl(post.slug) : '#'));
3110        link.target = '_blank';
3111        link.rel = 'noopener';
3112        const image = post.thumbnail || post.cover || post.summary_image_url || post.image || post.featured_image?.source_url || post.featured_image?.sizes?.medium?.source_url || '';
3113        link.innerHTML = `<div class="cover"><img src="${escapeHtml(image)}" alt="${escapeHtml(title)}" width="310" height="200" decoding="async" loading="lazy" fetchpriority="low"></div><div><b data-zh="${escapeHtml(title)}" data-en="${escapeHtml(titleEn)}">${escapeHtml(language === 'en' ? titleEn : title)}</b><span data-zh="${escapeHtml(subtitle)}" data-en="${escapeHtml(subtitleEn)}">${escapeHtml(language === 'en' ? subtitleEn : subtitle)}</span></div>`;
3114        panel.appendChild(link);
3115      });
3116    };
3117
3118    const renderBackendHot = (posts = []) => {
3119      const panel = document.querySelector('.sidebar .panel:nth-of-type(2)');
3120      if (!panel || !posts.length) return;
3121      const head = panel.querySelector('.panel-head');
3122      head?.querySelector('a')?.remove();
3123      panel.innerHTML = '';
3124      if (head) panel.appendChild(head);
3125      posts.slice(0, 5).forEach((post, index) => {
3126        const title = post.titleZh || compactTitle(post.title);
3127        const titleEn = post.titleEn || enText(post.title, title);
3128        const visibleTitle = language === 'en' ? titleEn : title;
3129        const link = document.createElement('a');
3130        link.className = 'hot';
3131        link.href = normalizeUrl(post.url || post.link || (post.slug ? postUrl(post.slug) : '#'));
3132        link.target = '_blank';
3133        link.rel = 'noopener';
3134        link.innerHTML = `<div class="rank">${String(index + 1).padStart(2, '0')}</div><div><b data-zh="${escapeHtml(title)}" data-en="${escapeHtml(titleEn)}">${escapeHtml(visibleTitle)}</b><span></span></div>`;
3135        panel.appendChild(link);
3136      });
3137    };
3138
3139    const renderBackendData = (snapshot) => {
3140      if (!snapshot?.home) return;
3141      renderBackendCarousel(snapshot);
3142      renderBackendHomeTopAd(snapshot);
3143      renderBackendInlineAd({ snapshot, selector: '.ad-embed.materials-ad', field: 'homeMaterialAds', slug: 'home_list_8', positionId: '34630', label: '首页第 8 篇文章后' });
3144      renderBackendInlineAd({ snapshot, selector: '.ad-embed.project-ad', field: 'homeProjectAds', slug: 'home_list_12', positionId: '34632', label: '首页第 12 篇文章后' });
3145      renderBackendInlineAd({ snapshot, selector: '.ad-embed.page-bottom', field: 'homePaginationBottomAds', slug: 'home_pagination_bottom', positionId: '34642', label: '页码下方广告' });
3146      const latestJobs = snapshot.home.homeSideJobs?.length ? snapshot.home.homeSideJobs : (snapsh
3146ot.home.jobs || []);
3147      const showNumbers = latestShowNumbers(snapshot);
3148      renderBackendPosts(snapshot.home.posts || []);
3149      renderBackendTextJobs(latestJobs, showNumbers, snapshot.jumpUrls || snapshot.home.jumpUrls || {});
3150      renderBackendPinnedJobs(collectPinnedJobs(snapshot), snapshot.jumpUrls || snapshot.home.jumpUrls || {});
3151      renderBackendSideJobs(latestJobs, showNumbers);
3152      renderBackendSeries(snapshot.home.top_posts || []);
3153      renderBackendHot(snapshot.home.week_hot || []);
3154      renderPagination(snapshot.home.pageInfo || snapshot.pageInfo || {});
3155      normalizeV10ImagePerformanceAttrs();
3156      document.documentElement.dataset.backendSnapshot = '20260709';
3157    };
3158
3159    const shouldUseLiveHomeData = () => {
3160      const params = new URLSearchParams(window.location.search);
3161      const hostname = window.location.hostname;
3162      return hostname === 'www.gooood.cn' || hostname === '127.0.0.1' || hostname === 'localhost' || params.get('live') === '1' || params.has('fixture');
3163    };
3164
3165    const loadFixtureSnapshot = async () => {
3166      const params = new URLSearchParams(window.location.search);
3167      const fixture = params.get('fixture');
3168      if (!fixture) return null;
3169      if (!/^[a-zA-Z0-9._-]+$/.test(fixture)) throw new Error('Invalid V10 fixture name');
3170      const fixtureResponse = await fetch(`/api/home/v10-fixture?name=${encodeURIComponent(fixture)}`, {
3171        credentials: 'omit',
3172        cache: 'no-store'
3173      });
3174      if (!fixtureResponse.ok) throw new Error(`V10 fixture not found: ${fixture}`);
3175      const fixtureSnapshot = await fixtureResponse.json();
3176      return { fixture, snapshot: fixtureSnapshot };
3177    };
3178
3179    const withFreshCarouselAds = async (snapshot) => {
3180      try {
3181        const carouselUrl = `https://dashboard.gooood.cn/wp-json/wp/v2/advertisement?adposition=34627&per_page=20&order=asc&orderby=menu_order&_fresh=${Date.now()}`;
3182        const response = await fetch(carouselUrl, { credentials: 'omit', cache: 'no-store' });
3183        if (!response.ok) return snapshot;
3184        const carouselAds = await response.json();
3185        if (!Array.isArray(carouselAds)) return snapshot;
3186        const freshSnapshot = JSON.parse(JSON.stringify(snapshot));
3187        freshSnapshot.home = freshSnapshot.home || {};
3188        freshSnapshot.home.carouselAds = carouselAds;
3189        freshSnapshot.adsByPosition = freshSnapshot.adsByPosition || {};
3190        freshSnapshot.adsByPosition['34627'] = carouselAds;
3191        freshSnapshot.adFreshnessByPosition = freshSnapshot.adFreshnessByPosition || {};
3192        freshSnapshot.adFreshnessByPosition['34627'] = {
3193          source: 'wp/v2/advertisement',
3194          sourceFetchedAt: new Date().toISOString(),
3195          cacheStatus: 'direct-request',
3196          itemCount: carouselAds.length,
3197          setFingerprint: adSetFingerprint(carouselAds)
3198        };
3199        return freshSnapshot;
3200      } catch (error) {
3201        return snapshot;
3202      }
3203    };
3204
3205    const refreshLiveHomeData = async () => {
3206      if (!backendSnapshot?.home || !shouldUseLiveHomeData()) return null;
3207      if (backendSnapshot.home.pageInfo?.basePath) {
3208        const freshArchiveSnapshot = await withFreshCarouselAds(backendSnapshot);
3209        renderBackendData(freshArchiveSnapshot);
3210        document.documentElement.dataset.liveHomeData = 'ssr-archive-snapshot';
3211        document.documentElement.dataset.liveHomeSource = freshArchiveSnapshot.source || 'nuxt-v10-runtime:archive-full-page';
3212        return freshArchiveSnapshot;
3213      }
3214      const page = currentPageFromLocation();
3215      const fixtureResult = await loadFixtureSnapshot();
3216      if (fixtureResult?.snapshot) {
3217        renderBackendData(fixtureResult.snapshot);
3218        document.documentElement.dataset.liveHomeData = 'connected';
3219        document.documentElement.dataset.liveHomeSource = `v10-fixture:${fixtureResult.fixture}`;
3220        return fixtureResult.snapshot;
3221      }
3222      try {
3223        const localPreview = window.location.hostname === '127.0.0.1' || window.location.hostname === 'localhost';
3224        const runtimeUrl = `/api/home/v10-runtime?page=${page}&hotPerPage=5${localPreview ? '&refresh=1' : ''}`;
3225        const runtimeResponse = await fetch(runtimeUrl, { credentials: 'omit', cache: localPreview ? 'no-store' : 'default' });
3226        if (runtimeResponse.ok) {
3227          const runtimeSnapshot = await withFreshCarouselAds(await runtimeResponse.json());
3228          renderBackendData(runtimeSnapshot);
3229          document.documentElement.dataset.liveHomeData = 'connected';
3230          document.documentElement.dataset.liveHomeSource = runtimeSnapshot.source || 'nuxt-v10-runtime';
3231          return runtimeSnapshot;
3232        }
3233      } catch (error) {
3234        document.documentElement.dataset.liveHomeData = 'nuxt-v10-runtime-fallback';
3235      }
3236      const initialPerPage = Number(backendSnapshot.home.pageInfo?.perPage) || 18;
3237      let perPage = initialPerPage;
3238      try {
3239        const countResponse = await fetch(`https://dashboard.gooood.cn/api/api-blogjobs-number.php?_fresh=${Date.now()}`, { credentials: 'omit', cache: 'no-store' });
3240        const countText = await countResponse.text();
3241        perPage = Number(countText.trim()) || initialPerPage;
3242      } catch (error) {
3243        perPage = initialPerPage;
3244      }
3245      const postsEndpoint = `https://dashboard.gooood.cn/wp-json/wp/v2/fetch-posts?post_type%5B0%5D=post&post_type%5B1%5D=jobs&page=${page}&per_page=${perPage}&orderby=date&order=desc&_fresh=${Date.now()}`;
3246      const [postsResult, jobsResult, carouselResult, runtimeResult, showNumbersResult] = await Promise.allSettled([
3247        fetch(postsEndpoint, { credentials: 'omit', cache: 'no-store' }),
3248        fetch('https://dashboard.gooood.cn/api/api-jobs-index.php', { credentials: 'omit' }),
3249        fetch(`https://dashboard.gooood.cn/wp-json/wp/v2/advertisement?adposition=34627&per_page=20&order=asc&orderby=menu_order&_fresh=${Date.now()}`, { credentials: 'omit', cache: 'no-store' }),
3250        fetch('/api/home/runtime?hotPerPage=5', { credentials: 'omit' }),
3251        fetch(`https://dashboard.gooood.cn/api/api-show-number.php?_fresh=${Date.now()}`, { credentials: 'omit', cache: 'no-store' })
3252      ]);
3253      const postsResponse = postsResult.status === 'fulfilled' && postsResult.value.ok ? postsResult.value : null;
3254      const posts = postsResponse ? await postsResponse.json() : (backendSnapshot.home.posts || []);
3255      const jobs = jobsResult.status === 'fulfilled' && jobsResult.value.ok ? await jobsResult.value.json() : backendSnapshot.home.homeSideJobs || [];
3256      const carouselAds = carouselResult.status === 'fulfilled' && carouselResult.value.ok ? await carouselResult.value.json() : null;
3257      const runtime = runtimeResult.status === 'fulfilled' && runtimeResult.value.ok ? await runtimeResult.value.json() : null;
3258      const freshShowNumbers = showNumbersResult.status === 'fulfilled' && showNumbersResult.value.ok ? await showNumbersResult.value.json() : null;
3259      const total = Number(postsResponse?.headers.get('x-wp-total')) || Number(backendSnapshot.home.pageInfo?.total) || posts.length;
3260      const totalPages = Number(postsResponse?.headers.get('x-wp-totalpages')) || Number(backendSnapshot.home.pageInfo?.totalPages) || Math.max(1, Math.ceil(total / perPage));
3261      const liveSnapshot = JSON.parse(JSON.stringify(backendSnapshot));
3262      liveSnapshot.home.posts = posts;
3263      liveSnapshot.home.homeSideJobs = jobs;
3264      liveSnapshot.home.sideJobsCount = jobs.length;
3265      const liveShowNumbers = freshShowNumbers && Object.keys(freshShowNumbers).length ? freshShowNumbers : runtime?.showNumbers;
3266      if (liveShowNumbers) {
3267        liveSnapshot.showNumbers = liveShowNumbers;
3268        liveSnapshot.home.showNumbers = liveShowNumbers;
3269        liveSnapshot.home.showNumbersSource = freshShowNumbers ? 'https://dashboard.gooood.cn/api/api-show-number.php' : (runtime.home?.showNumbersSource || runtime.home?.v10RuntimeSources?.showNumbers || runtime.source || 'local-home-runtime');
3270        liveSnapshot.home.showNumbersFetchedAt = freshShowNumbers ? new Date().toISOString() : (runtime.home?.showNumbersFetchedAt || runtime.fetchedAt || '');
3271      }
3272      if (Array.isArray(runtime?.weekHot) && runtime.weekHot.length) {
3273        liveSnapshot.home.week_hot = runtime.weekHot;
3274      }
3275      liveSnapshot.home.pageInfo = {
3276        page,
3277        perPage,
3278        total,
3279        totalPages,
3280        source: postsEndpoint,
3281        countSource: 'https://dashboard.gooood.cn/api/api-blogjobs-number.php',
3282        frontendBaseUrl: 'https://www.gooood.cn',
3283        corsAllowedOrigin: 'https://www.gooood.cn'
3284      };
3285	      if (Array.isArray(carouselAds)) {
3286	        liveSnapshot.adsByPosition = liveSnapshot.adsByPosition || {};
3287	        liveSnapshot.ads = liveSnapshot.ads || {};
3288	        liveSnapshot.indexAds = liveSnapshot.indexAds || {};
3289        liveSnapshot.adsByPosition['34627'] = carouselAds;
3290        liveSnapshot.ads.home_banners = carouselAds;
3291	        liveSnapshot.indexAds.home_banners = carouselAds;
3292	        liveSnapshot.home.carouselAds = carouselAds;
3293	        liveSnapshot.adFreshnessByPosition = liveSnapshot.adFreshnessByPosition || {};
3294	        liveSnapshot.adFreshnessByPosition['34627'] = {
3295	          source: 'wp/v2/advertisement',
3296	          sourceFetchedAt: new Date().toISOString(),
3297	          cacheStatus: 'direct-request',
3298	          itemCount: carouselAds.length,
3299	          setFingerprint: adSetFingerprint(carouselAds)
3300	        };
3301	      }
3302      renderBackendData(liveSnapshot);
3303      document.documentElement.dataset.liveHomeData = 'connected';
3304      return liveSnapshot;
3305    };
3306
3307    renderBackendData(backendSnapshot);
3308
3309    document.querySelectorAll('.article').forEach((article) => {
3310      const titleLink = article.querySelector('.article-text h3 a');
3311      const cover = article.querySelector(':scope > .cover');
3312      if (!titleLink || !cover || cover.querySelector('a')) return;
3313      const coverLink = document.createElement('a');
3314      coverLink.className = 'article-cover-link';
3315      coverLink.href = titleLink.getAttribute('href') || '#';
3316      coverLink.setAttribute('aria-label', titleLink.textContent.trim());
3317      if (titleLink.target) coverLink.target = titleLink.target;
3318      if (titleLink.rel) coverLink.rel = titleLink.rel;
3319      while (cover.firstChild) coverLink.appendChild(cover.firstChild);
3320      cover.appendChild(coverLink);
3321    });
3322
3323    document.querySelectorAll('.article-actions').forEach((actions) => {
3324      actions.innerHTML = `
3325        <a class="action-item favorite-action" href="#login" data-gooood-favorite-trigger="1" role="button">
3326          <span class="action-icon">☆</span><span data-zh="收藏" data-en="Favorites">收藏</span>
3327        </a>
3328        <div class="action-item share-action">
3329          <button type="button" aria-label="分享"><span class="action-icon">↗</span><span data-zh="分享" data-en="Share">分享</span></button>
3330          <div class="share-icons-dropdown">
3331            <a href="javascript:;" class="share-icon wechat" aria-label="微信">微</a>
3332            <a href="javascript:;" class="share-icon weibo" aria-label="微博">博</a>
3333            <a href="javascript:;" class="share-icon twitter" aria-label="X">X</a>
3334            <a href="javascript:;" class="share-icon facebook" aria-label="Facebook">f</a>
3335            <a href="javascript:;" class="share-icon pinterest" aria-label="Pinterest">P</a>
3336            <a href="javascript:;" class="share-icon copy-link" aria-label="复制链接">链</a>
3337          </div>
3338        </div>
3339      `;
3340    });
3341
3342    document.querySelectorAll('.article-actions').forEach((actions) => {
3343      const links = actions.querySelectorAll('a, button');
3344      setBilingualText(links[0], '收藏', 'Favorites');
3345      setBilingualText(links[1], '分享', 'Share');
3346    });
3347    document.querySelectorAll('.page-jump button').forEach((button) => setBilingualText(button, '跳页', 'Go'));
3348
3349    const translatable = () => Array.from(document.querySelectorAll('[data-zh][data-en]'));
3350    const languageToggles = Array.from(document.querySelectorAll('[data-lang-toggle]'));
3351    const applyLanguage = (next) => {
3352      language = next === 'en' ? 'en' : 'zh';
3353      document.documentElement.lang = language === 'en' ? 'en' : 'zh-CN';
3354      translatable().forEach((node) => {
3355        node.textContent = node.dataset[language] || '';
3356      });
3357      document.querySelectorAll('[data-placeholder-zh][data-placeholder-en]').forEach((node) => {
3358        node.setAttribute('placeholder', node.dataset[`placeholder${language === 'en' ? 'En' : 'Zh'}`] || '');
3359      });
3360    };
3361    languageToggles.forEach((toggle) => {
3362      toggle.addEventListener('click', () => applyLanguage(language === 'zh' ? 'en' : 'zh'));
3363    });
3364    applyLanguage('zh');
3365
3366    const headerSearchToggle = document.querySelector('[data-header-search-toggle]');
3367    const headerSearchPanel = document.querySelector('#header-search-panel');
3368    const headerSearchInput = headerSearchPanel?.querySelector('input');
3369    const setHeaderSearchOpen = (nextOpen) => {
3370      if (!headerSearchToggle || !headerSearchPanel) return;
3371      headerSearchToggle.setAttribute('aria-expanded', String(nextOpen));
3372      headerSearchPanel.hidden = !nextOpen;
3373      if (nextOpen) {
3374        window.setTimeout(() => headerSearchInput?.focus(), 0);
3375      }
3376    };
3377    const buildSearchPath = (value) => {
3378      const query = String(value || '').trim();
3379      return query ? `https://www.gooood.cn/search/${encodeURIComponent(query)}` : '';
3380    };
3381    const bindSearchPathSubmit = (form) => {
3382      form?.addEventListener('submit', (event) => {
3383        const input = form.querySelector('input[name="q"], input[name="s"]');
3384        const path = buildSearchPath(input?.value);
3385        if (!path) return;
3386        event.preventDefault();
3387        const navigationTarget = document.documentElement.dataset.v10Embed === 'header' && window.top !== window
3388          ? window.top
3389          : window;
3390        navigationTarget.location.href = path;
3391      });
3392    };
3393    headerSearchToggle?.addEventListener('click', (event) => {
3394      event.preventDefault();
3395      event.stopPropagation();
3396      setHeaderSearchOpen(headerSearchToggle.getAttribute('aria-expanded') !== 'true');
3397    });
3398    headerSearchPanel?.addEventListener('click', (event) => {
3399      event.stopPropagation();
3400    });
3401    document.querySelectorAll('[data-header-search-close]').forEach((button) => {
3402      button.addEventListener('click', () => setHeaderSearchOpen(false));
3403    });
3404    document.addEventListener('click', () => setHeaderSearchOpen(false));
3405    document.addEventListener('keydown', (event) => {
3406      if (event.key === 'Escape') setHeaderSearchOpen(false);
3407    });
3408    bindSearchPathSubmit(document.querySelector('.header-search-form'));
3409    bindSearchPathSubmit(document.querySelector('.mobile-search-form'));
3410
3411    const mobileMenuToggle = document.querySelector('.mobile-menu-toggle');
3412    const mobileMenu = document.querySelector('#mobile-menu');
3413    const mobileMenuBackdrop = document.querySelector('.mobile-menu-backdrop');
3414    const headerActions = document.querySelector('.header-actions');
3415    const setMobileMenuOpen = (nextOpen) => {
3416      mobileMenuToggle?.setAttribute('aria-expanded', String(nextOpen));
3417      if (mobileMenu) {
3418        mobileMenu.hidden = !nextOpen;
3419        mobileMenu.classList.toggle('is-open', nextOpen);
3420      }
3421      if (mobileMenuBackdrop) {
3422        mobileMenuBackdrop.hidden = !nextOpen;
3423        mobileMenuBackdrop.classList.toggle('is-open', nextOpen);
3424      }
3425      headerActions?.classList.toggle('menu-open', nextOpen);
3426    };
3427    mobileMenuToggle?.addEventListener('click', () => {
3428      const isOpen = mobileMenuToggle.getAttribute('aria-expanded') === 'true';
3429      setMobileMenuOpen(!isOpen);
3430    });
3431    mobileMenuBackdrop?.addEventListener('click', () => setMobileMenuOpen(false));
3432    document.addEventListener('keydown', (event) => {
3433      if (event.key === 'Escape') setMobileMenuOpen(false);
3434    });
3435    document.querySelectorAll('.mobile-menu-parent').forEach((button) => {
3436      button.addEventListener('click', () => {
3437        button.closest('.mobile-menu-item')?.classList.toggle('is-open');
3438      });
3439    });
3440
3441    const setupSlider = () => {
3442      const slider = document.querySelector('.top-slider');
3443      if (!slider) return;
3444      const slides = Array.from(slider.querySelectorAll('.slide'));
3445      const dots = Array.from(slider.querySelectorAll('[data-sli
3445de-dot]'));
3446      const prev = slider.querySelector('[data-slide-prev]');
3447      const next = slider.querySelector('[data-slide-next]');
3448      if (!slides.length) return;
3449      let active = Math.max(0, slides.findIndex((slide) => slide.classList.contains('is-active')));
3450      const loadSlideImage = (slide) => {
3451        const img = slide?.querySelector('img[data-src]');
3452        if (!img) return;
3453        img.src = img.dataset.src || '';
3454        img.removeAttribute('data-src');
3455      };
3456
3457      const show = (index) => {
3458        active = (index + slides.length) % slides.length;
3459        loadSlideImage(slides[active]);
3460        slides.forEach((slide, i) => slide.classList.toggle('is-active', i === active));
3461        dots.forEach((dot, i) => dot.classList.toggle('is-active', i === active));
3462      };
3463
3464      if (prev) prev.onclick = () => show(active - 1);
3465      if (next) next.onclick = () => show(active + 1);
3466      dots.forEach((dot, i) => {
3467        dot.onclick = () => show(i);
3468      });
3469      show(active);
3470    };
3471
3472    if (document.documentElement.dataset.v10Embed === 'header') return;
3473
3474    setupSlider();
3475    refreshLiveHomeData()
3476      .then((snapshot) => {
3477        if (!snapshot) return;
3478        applyLanguage(language);
3479        setupSlider();
3480      })
3481      .catch((error) => {
3482        document.documentElement.dataset.liveHomeData = 'snapshot-fallback';
3483        console.warn('[gooood V10] live home data fallback', error);
3484      });
3485  })();
3486</script>
vendor: 1 bytes, line 3486
3486
3487<script data-v10-header-embed="1">
3488  (() => {
3489    if (document.documentElement.dataset.v10Embed !== 'header' || window.parent === window) return;
3490
3491    const reportHeight = (height) => {
3492      window.parent.postMessage({ type: 'gooood-v10-header-height', height }, window.location.origin);
3493    };
3494    const header = document.querySelector('.site-header');
3495    const desktopHeight = 65;
3496    const expandedHeight = 460;
3497
3498    document.querySelectorAll('.site-header a[href]').forEach((link) => {
3499      const href = link.getAttribute('href') || '';
3500      if (href && !href.startsWith('#') && !href.startsWith('javascript:')) link.target = '_top';
3501    });
3502    document.querySelectorAll('.site-header form').forEach((form) => { form.target = '_top'; });
3503
3504    header?.addEventListener('pointerover', () => reportHeight(expandedHeight));
3505    header?.addEventListener('pointerout', (event) => {
3506      if (!header.contains(event.relatedTarget)) reportHeight(desktopHeight);
3507    });
3508    document.addEventListener('click', (event) => {
3509      if (event.target.closest('[data-header-search-toggle], .mobile-menu-toggle, .mobile-menu-parent')) {
3510        reportHeight(Math.max(expandedHeight, window.innerHeight));
3511      }
3512      if (event.target.closest('[data-header-search-close], .mobile-menu-backdrop')) reportHeight(desktopHeight);
3513    });
3514    new MutationObserver(() => {
3515      if (document.querySelector('.mobile-menu-toggle[aria-expanded="true"]')) {
3516        reportHeight(Math.max(expandedHeight, window.innerHeight));
3517      }
3518    }).observe(document.documentElement, { attributes: true, subtree: true, attributeFilter: ['aria-expanded'] });
3519    reportHeight(desktopHeight);
3520  })();
3521</script>
vendor: 1 bytes, line 3521
3521
3522<script data-gooood-home-auth-favorites>(() => {
3523  if (window.__GOOOOD_HOME_AUTH_FAVORITES__) return;
3524  window.__GOOOOD_HOME_AUTH_FAVORITES__ = true;
3525  const API_BASE = 'https://dashboard.gooood.cn/wp-json';
3526  const BROKEN_ACCOUNT_PATHS = new Set(['/member']);
3527  let pendingFavorite = null;
3528  let toastTimer = 0;
3529  let currentUser = null;
3530  let authMode = 'login';
3531  let forgotMethod = 'email';
3532  let telCodesLoaded = false;
3533  let telCodes = [{ en: 'China', zh: '中国', locale: 'CN', code: '86' }];
3534  let registerCountdown = 0;
3535  let forgotCountdown = 0;
3536  let registerCountdownTimer = 0;
3537  let forgotCountdownTimer = 0;
3538  let authRestoreRetryTimer = 0;
3539  let authRestoreRetryAttempts = 0;
3540  const ALIYUN_CAPTCHA_SRC = 'https://o.alicdn.com/captcha-frontend/aliyunCaptcha/AliyunCaptcha.js';
3541  const CAPTCHA_INIT_TIMEOUT_MS = 90000;
3542  const CAPTCHA_VERIFY_TIMEOUT_MS = 180000;
3543  const CAPTCHA_LOAD_ERROR_GRACE_MS = 20000;
3544  const CAPTCHA_REQUEST_TIMEOUT_MS = 15000;
3545  const CAPTCHA_VISIBLE_ACTION_TIMEOUT_MS = 25000;
3546  const CAPTCHA_EXISTING_SCRIPT_TIMEOUT_MS = 3000;
3547  const CAPTCHA_MIN_WARMUP_MS = 2200;
3548  const CAPTCHA_UI_SCALE = 1;
3549  let aliyunCaptchaScriptPromise = null;
3550
3551  const logCaptchaDiagnostic = (stage, details = {}) => {
3552    try {
3553      window.console && window.console.warn && window.console.warn('[gooood sms captcha]', stage, JSON.stringify(details));
3554    } catch (_) {
3555      // Best-effort browser-side diagnostics only.
3556    }
3557  };
3558  const sanitizeAliyunResourceName = (name) => {
3559    try {
3560      const url = new URL(name);
3561      if (!/alicdn\.com$/.test(url.hostname)) return url.hostname;
3562      return `${url.hostname}${url.pathname}`;
3563    } catch (_) {
3564      return String(name || '').slice(0, 160);
3565    }
3566  };
3567  const aliyunResourceDiagnostics = () => {
3568    try {
3569      return window.performance.getEntriesByType('resource')
3570        .filter((entry) => /captcha|FeiLin|aliyun/i.test(entry.name))
3571        .slice(-12)
3572        .map((entry) => ({
3573          name: sanitizeAliyunResourceName(entry.name),
3574          type: entry.initiatorType || 'unknown',
3575          durationMs: Math.round(entry.duration),
3576          transferSize: entry.transferSize || 0,
3577          decodedBodySize: entry.decodedBodySize || 0
3578        }));
3579    } catch (_) {
3580      return [];
3581    }
3582  };
3583  const cookieValue = (name) => {
3584    const prefix = `${name}=`;
3585    const values = document.cookie.split(';').map((part) => part.trim()).filter((part) => part.startsWith(prefix)).map((part) => {
3586      try { return decodeURIComponent(part.slice(prefix.length)); } catch (_) { return part.slice(prefix.length); }
3587    }).filter(Boolean);
3588    return values.length ? values[values.length - 1] : '';
3589  };
3590  const saveToken = (token, expire) => {
3591    const stale = ['auth_token=', 'Path=/', 'SameSite=Lax', 'Max-Age=0'];
3592    if (window.location.protocol === 'https:') stale.push('Secure');
3593    document.cookie = stale.join('; ');
3594    const parts = [`auth_token=${encodeURIComponent(token)}`, 'Path=/', 'SameSite=Lax'];
3595    if (window.location.protocol === 'https:') parts.push('Secure');
3596    if (window.location.hostname === 'gooood.cn' || window.location.hostname.endsWith('.gooood.cn')) parts.push('Domain=.gooood.cn');
3597    const unix = Number(expire);
3598    if (Number.isFinite(unix) && unix > 0) parts.push(`Expires=${new Date(unix * 1000).toUTCString()}`);
3599    document.cookie = parts.join('; ');
3600  };
3601  const clearToken = () => {
3602    const expire = (domain = '') => {
3603      const parts = ['auth_token=', 'Path=/', 'SameSite=Lax', 'Max-Age=0'];
3604      if (window.location.protocol === 'https:') parts.push('Secure');
3605      if (domain) parts.push(`Domain=${domain}`);
3606      document.cookie = parts.join('; ');
3607    };
3608    expire();
3609    if (window.location.hostname === 'gooood.cn' || window.location.hostname.endsWith('.gooood.cn')) expire('.gooood.cn');
3610  };
3611  const resolveAvatarUrl = (user) => {
3612    if (!user) return '';
3613    if (user.avatar) return user.avatar;
3614    if (user.user_data && user.user_data.avatar) return user.user_data.avatar;
3615    const urls = user.avatar_urls;
3616    if (urls && typeof urls === 'object') return urls['96'] || urls['48'] || urls['24'] || Object.values(urls)[0] || '';
3617    return '';
3618  };
3619  const resolveDisplayName = (user) => {
3620    if (!user) return '';
3621    return user.displayname || user.name || (user.user_data && user.user_data.nickname) || user.nickname || '';
3622  };
3623  const resolveUserId = (user) => Number(user && (user.id || (user.user_data && user.user_data.id))) || 0;
3624  const hasRole = (user, expected) => {
3625    const roles = user && (user.roles || (user.user_data && user.user_data.roles));
3626    if (Array.isArray(roles)) return roles.includes(expected);
3627    return Boolean(roles && typeof roles === 'object' && roles[expected]);
3628  };
3629  const setAuthState = (status, user) => {
3630    window.__GOOOOD_HOME_AUTH_STATE__ = { status, userId: resolveUserId(user) || null };
3631  };
3632  const closeAccountMenus = (except = null) => {
3633    document.querySelectorAll('.gooood-account.is-open').forEach((account) => {
3634      if (account === except) return;
3635      account.classList.remove('is-open');
3636      const toggle = account.querySelector('[data-gooood-account-toggle]');
3637      if (toggle) toggle.setAttribute('aria-expanded', 'false');
3638    });
3639  };
3640  const appendMenuLink = (menu, href, zh, en, options = {}) => {
3641    const link = document.createElement('a');
3642    link.href = href;
3643    link.dataset.zh = zh;
3644    link.dataset.en = en;
3645    link.textContent = currentLanguage() === 'en' ? en : zh;
3646    if (options.external) link.rel = 'noopener';
3647    menu.appendChild(link);
3648  };
3649  const renderLoggedOutSlot = (slot) => {
3650    const mode = slot.dataset.goooodAuthSlot || 'desktop';
3651    const link = document.createElement('a');
3652    link.href = '#login';
3653    link.dataset.goooodAuthMember = mode;
3654    link.dataset.goooodLoginTrigger = '1';
3655    link.dataset.zh = '会员/登录';
3656    link.dataset.en = 'VIP/Login';
3657    if (mode === 'mobile') {
3658      const icon = document.createElement('span');
3659      icon.className = 'mobile-user-icon';
3660      icon.textContent = '●';
3661      link.appendChild(icon);
3662    }
3663    const label = document.createElement('span');
3664    label.dataset.zh = '会员/登录';
3665    label.dataset.en = 'VIP/Login';
3666    label.textContent = currentLanguage() === 'en' ? 'VIP/Login' : '会员/登录';
3667    link.appendChild(label);
3668    slot.replaceChildren(link);
3669  };
3670  const renderLoggedInSlot = (slot, user) => {
3671    const mode = slot.dataset.goooodAuthSlot || 'desktop';
3672    const displayName = resolveDisplayName(user) || (currentLanguage() === 'en' ? 'Member' : '会员');
3673    const avatarUrl = resolveAvatarUrl(user);
3674    const userId = resolveUserId(user);
3675    const account = document.createElement('div');
3676    account.className = `gooood-account gooood-account--${mode}`;
3677
3678    const toggle = document.createElement('button');
3679    toggle.type = 'button';
3680    toggle.className = 'gooood-account-toggle';
3681    toggle.dataset.goooodAccountToggle = '1';
3682    toggle.setAttribute('aria-haspopup', 'menu');
3683    toggle.setAttribute('aria-expanded', 'false');
3684    toggle.setAttribute('aria-label', `${displayName} - ${currentLanguage() === 'en' ? 'Account menu' : '账户菜单'}`);
3685
3686    if (avatarUrl) {
3687      const avatar = document.createElement('img');
3688      avatar.className = 'gooood-account-avatar';
3689      avatar.src = avatarUrl;
3690      avatar.alt = displayName;
3691      avatar.referrerPolicy = 'no-referrer';
3692      toggle.appendChild(avatar);
3693    } else {
3694      const placeholder = document.createElement('span');
3695      placeholder.className = 'gooood-account-avatar gooood-account-avatar--placeholder';
3696      placeholder.setAttribute('aria-hidden', 'true');
3697      toggle.appendChild(placeholder);
3698    }
3699    const name = document.createElement('span');
3700    name.className = 'gooood-account-name';
3701    name.textContent = displayName;
3702    toggle.appendChild(name);
3703
3704    const menu = document.createElement('div');
3705    menu.className = 'gooood-account-menu';
3706    menu.setAttribute('role', 'menu');
3707    if (hasRole(user, 'administrator') || hasRole(user, 'editor') || hasRole(user, 'author')) {
3708      appendMenuLink(menu, 'https://dashboard.gooood.cn/wp-admin/', '管理后台', 'Dashboard', { external: true });
3709    }
3710    if (user && user.user_data && user.user_data.brand) appendMenuLink(menu, '/account/report', '品牌中心', 'Brand Center');
3711    if (userId) appendMenuLink(menu, `/people/${encodeURIComponent(String(userId))}`, '个人中心', 'Profile');
3712    appendMenuLink(menu, '/account/profile', '设置', 'Settings');
3713    const divider = document.createElement('span');
3714    divider.className = 'gooood-account-divider';
3715    divider.setAttribute('aria-hidden', 'true');
3716    menu.appendChild(divider);
3717    const logout = document.createElement('button');
3718    logout.type = 'button';
3719    logout.dataset.goooodAccountLogout = '1';
3720    logout.dataset.zh = '退出登录';
3721    logout.dataset.en = 'Log out';
3722    logout.textContent = currentLanguage() === 'en' ? 'Log out' : '退出登录';
3723    menu.appendChild(logout);
3724
3725    account.append(toggle, menu);
3726    slot.replaceChildren(account);
3727  };
3728  const updateMemberUI = (user) => {
3729    currentUser = user || null;
3730    closeAccountMenus();
3731    document.querySelectorAll('[data-gooood-auth-slot]').forEach((slot) => {
3732      if (user) renderLoggedInSlot(slot, user);
3733      else renderLoggedOutSlot(slot);
3734    });
3735    setAuthState(user ? 'authenticated' : 'logged-out', user);
3736  };
3737  const isConfirmedAuthInvalidation = (error) => {
3738    const status = Number(error && (error.status || error.statusCode || (error.data && error.data.status)) || 0);
3739    const code = String(error && (error.code || (error.data && (error.data.code || error.data.error))) || '').toLowerCase();
3740    if (status === 401) return true;
3741    return [
3742      'gooood_account_temporarily_unavailable',
3743      'gooood_jwt_expired_by_security_policy',
3744      'gooood_login_name_security_hold',
3745      'jwt_auth_bad_auth_header',
3746      'jwt_auth_invalid_token',
3747      'jwt_auth_no_auth_header',
3748      'rest_not_logged_in'
3749    ].includes(code);
3750  };
3751  const scheduleAuthRestoreRetry = () => {
3752    const delays = [1500, 5000, 15000];
3753    if (authRestoreRetryTimer || authRestoreRetryAttempts >= delays.length) return;
3754    const delay = delays[authRestoreRetryAttempts++];
3755    authRestoreRetryTimer = window.setTimeout(() => {
3756      authRestoreRetryTimer = 0;
3757      checkAndRestoreAuth();
3758    }, delay);
3759  };
3760  const retainAuthAfterTemporaryFailure = () => {
3761    setAuthState('temporarily-unavailable', null);
3762    scheduleAuthRestoreRetry();
3763  };
3764  const checkAndRestoreAuth = async () => {
3765    const token = cookieValue('auth_token');
3766    if (!token) { updateMemberUI(null); return; }
3767    try {
3768      const user = await apiRequest('/wp/v2/users/me', { token });
3769      authRestoreRetryAttempts = 0;
3770      updateMemberUI(user);
3771    } catch (error) {
3772      if (isConfirmedAuthInvalidation(error)) {
3773        clearToken();
3774        updateMemberUI(null);
3775      } else {
3776        retainAuthAfterTemporaryFailure();
3777      }
3778    }
3779  };
3780  const apiRequest = async (path, options = {}) => {
3781    const headers = { Accept: 'application/json', ...(options.headers || {}) };
3782    if (options.body) headers['Content-Type'] = 'application/json';
3783    const token = options.token || cookieValue('auth_token');
3784    if (token && options.auth !== false) headers.Authorization = `Bearer ${token}`;
3785    const response = await fetch(`${API_BASE}${path}`, { method: options.method || 'GET', body: options.body ? JSON.stringify(options.body) : undefined, headers, credentials: 'omit', cache: 'no-store' });
3786    const data = await response.json().catch(() => ({}));
3787    if (!response.ok) {
3788      const error = new Error(data.msg || data.message || `请求失败(${response.status})`);
3789      error.status = response.status;
3790      error.code = data.code;
3791      error.data = data;
3792      throw error;
3793    }
3794    return data;
3795  };
3796
3797  const modal = document.createElement('div');
3798  modal.className = 'gooood-auth-modal';
3799  modal.hidden = true;
3800  modal.innerHTML = `<div class="gooood-auth-dialog" role="dialog" aria-modal="true" aria-labelledby="gooood-auth-title"><button class="gooood-auth-close" type="button" aria-label="关闭登录">×</button><form class="gooood-auth-form"><h2 id="gooood-auth-title" data-zh="会员登录" data-en="Member Login">会员登录</h2><div class="gooood-auth-panel" data-auth-panel="login"><label class="gooood-auth-field"><span>账号</span><input name="username" type="text" autocomplete="username" data-placeholder-zh="请输入账号或手机号" data-placeholder-en="Username or mobile" placeholder="请输入账号或手机号" required></label><label class="gooood-auth-field"><span>密码</span><input name="password" type="password" autocomplete="current-password" data-placeholder-zh="请输入密码" data-placeholder-en="Password" placeholder="请输入密码" required></label></div><div class="gooood-auth-panel" data-auth-panel="register" hidden><label class="gooood-auth-field"><span>区号</span><select name="register_region" autocomplete="tel-country-code"></select></label><label class="gooood-auth-field"><span>手机号</span><input name="register_mobile" type="tel" inputmode="tel" autocomplete="tel" data-placeholder-zh="请输入手机号" data-placeholder-en="Mobile number" placeholder="请输入手机号"></label><div class="gooood-auth-code-row"><label class="gooood-auth-field"><span>验证码</span><input name="register_code" type="text" inputmode="numeric" autocomplete="one-time-code" data-placeholder-zh="请输入验证码" data-placeholder-en="Verification code" placeholder="请输入验证码"></label><button class="gooood-auth-code" type="button" data-code-kind="register" data-zh="获取验证码" data-en="Get code">获取验证码</button></div><label class="gooood-auth-field"><span>密码</span><input name="register_password" type="password" autocomplete="new-password" data-placeholder-zh="请输入密码" data-placeholder-en="Password" placeholder="请输入密码"></label><label class="gooood-auth-field"><span>确认密码</span><input name="register_password2" type="password" autocomplete="new-password" data-placeholder-zh="请再次输入密码" data-placeholder-en="Confirm password" placeholder="请再次输入密码"></label></div><div class="gooood-auth-panel" data-auth-panel="forgot" hidden><div class="gooood-auth-forgot-email" data-forgot-method-panel="email"><p class="gooood-auth-hint" data-zh="请输入用户名或邮箱地址。你将通过邮箱收到创建新密码的链接。" data-en="Please enter your username or email address. You will receive a link to create a new password via email.">请输入用户名或邮箱地址。你将通过邮箱收到创建新密码的链接。</p><label class="gooood-auth-field"><span>Username or E-mail</span><input name="reset_login" type="text" autocomplete="username" data-placeholder-zh="username or email address" data-placeholder-en="username or email address" placeholder="username or email address"></label><button class="gooood-auth-method-toggle" type="button" data-auth-forgot-method="phone" data-zh="手机号找回 »" data-en="Mobile recovery »">手机号找回 »</button></div><div class="gooood-auth-forgot-phone" data-forgot-method-panel="phone" hidden><label class="gooood-auth-field"><span>区号</span><select name="forgot_region" autocomplete="tel-country-code"></select></label><label class="gooood-auth-field"><span>手机号</span><input name="forgot_mobile" type="tel" inputmode="tel" autocomplete="tel" data-placeholder-zh="填写手机号" data-placeholder-en="Mobile number" placeholder="填写手机号"></label><div class="gooood-auth-code-row"><label class="gooood-auth-field"><span>验证码</span><input name="forgot_code" type="text" inputmode="numeric" autocomplete="one-time-code" data-placeholder-zh="验证码" data-placeholder-en="Verification code" placeholder="验证码"></label><button class="gooood-auth-code" type="button" data-code-kind="forgot" data-zh="获取验证码" data-en="Get code">获取验证码</button></div><label class="gooood-auth-field"><span>新密码</span><input name="forgot_password" type="password" autocomplete="new-password" data-placeholder-zh="新密码" data-placeholder-en="New password" placeholder="新密码"></label><label class="gooood-auth-field"><span>确认密码</span><input name="forgot_password2" type="password" autocomplete="new-password" data-placeholder-zh="确认密码" data-placeholder-en="Confirm password" placeholder="确认密码"></label><button class="gooood-auth-method-toggle" type="button" data-auth-forgot-method="email" data-zh="邮箱找回 »" data-en="Email recovery »">邮箱找回 »</button></div></div><p class="gooood-auth-error" role="alert" hidden></p><p class="gooood-auth-feedback" role="status" hidden></p><button class="gooood-auth-submit" type="submit" data-zh="登录" data-en="Login">登录</button><div class="gooood-auth-links"><button type="button" data-auth-mode-button="register" data-zh="手机号注册 »" data-en="Mobile register »">手机号注册 »</button><button type="button" data-auth-mode-button="forgot" data-zh="忘记密码?" data-en="Forgot password?">忘记密码?</button></div><div class="gooood-auth-social"><div class="gooood-auth-divider" data-zh="社交登录" data-en="Social Login">社交登录</div><button class="gooood-auth-wechat" type="button" data-zh="微信登录" data-en="Login with WeChat">微信登录</button></div></form></div>`;
3801  document.body.appendChild(modal);
3802  const toast = document.createElement('div');
3803  toast.className = 'gooood-auth-toast';
3804  toast.setAttribute('role', 'status');
3805  toast.hidden = true;
3806  document.body.appendChild(toast);
3807  const form = modal.querySelector('.gooood-auth-form');
3808  const titleNode = modal.querySelector('#gooood-auth-title');
3809  const errorNode = modal.querySelector('.gooood-auth-error');
3810  const feedbackNode = modal.querySelector('.gooood-auth-feedback');
3811  const submitButton = modal.querySelector('.gooood-auth-submit');
3812  const codeButtons = Array.from(modal.querySelectorAll('.gooood-auth-code'));
3813  const wechatButton = modal.querySelector('.gooood-auth-wechat');
3814  const socialBlock = modal.querySelector('.gooood-auth-social');
3815  const wechatMobileGuidance = document.createElement('p');
3816  wechatMobileGuidance.className = 'gooood-auth-wechat-mobile-guidance';
3817  wechatMobileGuidance.setAttribute('role', 'status');
3818  wechatMobileGuidance.dataset.zh = '微信登录请在微信内打开。当前浏览器会显示电脑扫码,无法在同一部手机完成登录。';
3819  wechatMobileGuidance.dataset.en = 'Open this page in WeChat to continue. This browser can only show a desktop QR code.';
3820  wechatMobileGuidance.hidden = true;
3821  socialBlock.appendChild(wechatMobileGuidance);
3822  const currentLanguage = () => document.documentElement.lang === 'en' ? 'en' : 'zh';
3823  const currentPathLanguage = () => /^\/en(?:\/|$)/.test(window.location.pathname) ? 'en' : 'zh';
3824  const isExternalMobileWechatLogin = () => window.matchMedia('(max-width: 767px)').matches && !/MicroMessenger/i.test(navigator.userAgent);
3825  const syncWechatLoginEntry = () => {
3826    const showGuidance = isExternalMobileWechatLogin();
3827    wechatButton.hidden = showGuidance;
3828    wechatMobileGuidance.hidden = !showGuidance;
3829    if (showGuidance) wechatButton.disabled = false;
3830  };
3831  const mobileWechatLoginMedia = window.matchMedia('(max-width: 767px)');
3832  if (typeof mobileWechatLoginMedia.addEventListener === 'function') mobileWechatLoginMedia.addEventListener('change', syncWechatLoginEntry);
3833  const stripEnglishPrefix = (path) => {
3834    const normalized = path && path.startsWith('/') ? path : `/${path || ''}`;
3835    if (normalized === '/en' || normalized === '/en/') return '/';
3836    return normalized.startsWith('/en/') ? normalized.slice(3) || '/' : normalized;
3837  };
3838  const localizedPath = (path, language) => {
3839    const clean = stripEnglishPrefix(path);
3840    if (language !== 'en') return clean;
3841    return clean === '/' ? '/en/' : `/en${clean}`;
3842  };
3843  const saveLanguage = (language) => {
3844    const parts = [
3845      `language=${language === 'en' ? 'en_US' : 'zh_CN'}`,
3846      'Path=/',
3847      'SameSite=Lax',
3848      'Max-Age=31536000'
3849    ];
3850    if (window.location.protocol === 'https:') parts.push('Secure');
3851    if (window.location.hostname === 'gooood.cn' || window.location.hostname.endsWith('.gooood.cn')) parts.push('Domain=.gooood.cn');
3852    document.cookie = parts.join('; ');
3853  };
3854  const switchLanguage = (language) => {
3855    saveLanguage(language);
3856    const url = new URL(window.location.href);
3857    url.pathname = localizedPath(url.pathname, language);
3858    url.searchParams.delete('lang');
3859    window.location.assign(`${url.pathname}${url.search}${url.hash}`);
3860  };
3861  const responseMessage = (response, fallback) => String((response && (response.msg || response.message)) || fallback).split('|')[0] || fallback;
3862  const responseSucceeded = (response) => {
3863    if (!response) return true;
3864    const status = String(response.status || '').toLowerCase();
3865    const code = String(response.code || '');
3866    return status === '1' || status === 'success' || code === '200';
3867  };
3868  const showToast = (zh, en = zh) => {
3869    window.clearTimeout(toastTimer);
3870    toast.textContent = currentLanguage() === 'en' ? en : zh;
3871    toast.hidden = false;
3872    toastTimer = window.setTimeout(() => { toast.hidden = true; }, 2600);
3873  };
3874  const setError = (message = '') => { errorNode.textContent = message; errorNode.hidden = !message; };
3875  const setFeedback = (message = '') => { feedbackNode.textContent = message; feedbackNode.hidden = !message; };
3876  const applyModalLanguage = () => {
3877    const language = currentLanguage();
3878    modal.querySelectorAll('[data-zh][data-en]').forEach((node) => { node.textContent = node.dataset[language] || node.dataset.zh || ''; });
3879    modal.querySelectorAll('[data-placeholder-zh][data-placeholder-en]').forEach((node) => { node.placeholder = language === 'en' ? node.dataset.placeholderEn : node.dataset.placeholderZh; });
3880  };
3881  const updateCodeButton = (kind, busy = false) => {
3882    const button = modal.querySelector(`[data-code-kind="${kind}"]`);
3883    if (!button) return;
3884    const countdown = kind === 'register' ? registerCountdown : forgotCountdown;
3885    if (busy) button.textContent = '验证中...';
3886    else if (countdown > 0) button.textContent = `已发送 ${countdown} s`;
3887    else button.textContent = currentLanguage() === 'en' ? 'Get code' : '获取验证码';
3888    button.disabled = busy || countdown > 0;
3889  };
3890  const startCodeCountdown = (kind) => {
3891    if (kind === 'register' && registerCountdownTimer) window.clearInterval(registerCountdownTimer);
3892    if (kind === 'forgot' && forgotCountdownTimer) window.clearInterval(forgotCountdownTimer);
3893    if (kind === 'register') registerCountdown = 60;
3894    else forgotCountdown = 60;
3895    updateCodeButton(kind);
3896    const timer = window.setInterval(() => {
3897      if (kind === 'register') registerCountdown -= 1;
3898      else forgotCountdown -= 1;
3899      if ((kind === 'register' ? registerCountdown : forgotCountdown) <= 0) {
3900        if (kind === 'register') registerCountdown = 0;
3901        else forgotCountdown = 0;
3902        window.clearInterval(timer);
3903      }
3904      updateCodeButton(kind);
3905    }, 1000);
3906    if (kind === 'register') registerCountdownTimer = timer;
3907    else forgotCountdownTimer = timer;
3908  };
3909  const populateTelSelects = () => {
3910    modal.querySelectorAll('select[name="register_region"], select[name="forgot_region"]').forEach((select) => {
3911      const selected = select.value || '86';
3912      select.replaceChildren(...telCodes.map((item) => {
3913        const option = document.createElement('option');
3914        option.value = String(item.code);
3915        option.textContent = `${item.zh} + ${item.code}`;
3916        if (option.value === selected) option.selected = true;
3917        return option;
3918      }));
3919      if (!select.value) select.value = '86';
3920    });
3921  };
3922  const loadTelCodes = async () => {
3923    populateTelSelects();
3924    if (telCodesLoaded) { populateTelSelects(); return; }
3925    try {
3926      const response = await apiRequest('/wp/v2/tel/code', { auth: false });
3927      if (Array.isArray(response) && response.length) telCodes = response;
3928      telCodesLoaded = true;
3929    } catch (_) {
3930      telCodes = [{ en: 'China', zh: '中国', locale: 'CN', code: '86' }];
3931    }
3932    populateTelSelects();
3933  };
3934  const ensureAliyunCaptchaElements = () => {
3935    const existingElement = document.getElementById('gooood-aliyun-captcha-element');
3936    if (!existingElement) {
3937      const element = document.createElement('div');
3938      element.id = 'gooood-aliyun-captcha-element';
3939      document.body.appendChild(element);
3940    } else {
3941      existingElement.removeAttribute('style');
3942    }
3943    if (!document.getElementById('gooood-aliyun-captcha-button')) {
3944      const button = document.createElement('button');
3945      button.id = 'gooood-aliyun-captcha-button';
3946      button.type = 'button';
3947      button.style.position = 'fixed';
3948      button.style.left = '0';
3949      button.style.top = '0';
3950      button.style.width = '1px';
3951      button.style.height = '1px';
3952      button.style.opacity = '0.01';
3953      button.style.zIndex = '1';
3954      document.body.appendChild(button);
3955    }
3956  };
3957  const normalizeCaptchaParam = (payload) => {
3958    if (typeof payload === 'string') return payload;
3959    if (!payload || typeof payload !== 'object') return '';
3960    const value = payload.captchaVerifyParam || payload.CaptchaVerifyParam || payload.verifyParam || payload.token || payload.verifyToken || payload.data;
3961    if (typeof value === 'string') return value;
3962    if (value && typeof value === 'object') return JSON.stringify(value);
3963    return JSON.stringify(payload);
3964  };
3965  const loadAliyunCaptchaScript = () => {
3966    window.AliyunCaptchaConfig = { region: 'cn', prefix: 'svsmdc' };
3967    if (typeof window.initAliyunCaptcha === 'function') return Promise.resolve();
3968    if (aliyunCaptchaScriptPromise) return aliyunCaptchaScriptPromise;
3969
3970    aliyunCaptchaScriptPromise = new Promise((resolve, reject) => {
3971      let settled = false;
3972      let existingGuard = 0;
3973      const settleResolve = () => {
3974        if (settled) return;
3975        settled = true;
3976        if (existingGuard) window.clearTimeout(existingGuard);
3977        resolve();
3978      };
3979      const settleReject = (stage, error, details = {}) => {
3980        if (settled) return;
3981        settled = true;
3982        if (existingGuard) window.clearTimeout(existingGuard);
3983        logCaptchaDiagnostic(stage, details);
3984        reject(error);
3985      };
3986      const injectScript = () => {
3987        const script = document.createElement('script');
3988        script.src = ALIYUN_CAPTCHA_SRC;
3989        script.async = true;
3990        script.onload = () => {
3991          if (typeof window.initAliyunCaptcha === 'function') {
3992            settleResolve();
3993            return;
3994          }
3995          settleReject('script_load_without_init', new Error('人机验证加载失败,请刷新后重试'));
3996        };
3997        script.onerror = () => {
3998          settleReject('script_load_error', new Error('人机验证加载失败,请刷新后重试'));
3999        };
4000        document.head.appendChild(script);
4001      };
4002
4003      const existing = document.querySelector(`script[src="${ALIYUN_CAPTCHA_SRC}"]`);
4004      if (existing) {
4005        existing.addEventListener('load', () => {
4006          if (typeof window.initAliyunCaptcha === 'function') settleResolve();
4007          else settleReject('script_existing_without_init', new Error('人机验证加载失败,请刷新后重试'), { reason: 'load_without_init' });
4008        }, { once: true });
4009        existing.addEventListener('error', () => {
4010          settleReject('script_existing_error', new Error('人机验证加载失败,请刷新后重试'));
4011        }, { once: true });
4012        existingGuard = window.setTimeout(() => {
4013          if (typeof window.initAliyunCaptcha === 'function') settleResolve();
4014          else settleReject('script_existing_missing_init', new Error('人机验证加载失败,请刷新后重试'));
4015        }, CAPTCHA_EXISTING_SCRIPT_TIMEOUT_MS);
4016        return;
4017      }
4018
4019      injectScript();
4020    });
4021    return aliyunCaptchaScriptPromise;
4022  };
4023  const captchaErrorMessage = (error, fallback = '人机验证失败,请重试') => {
4024    if (error && error.message) return error.message;
4025    if (error && typeof error === 'object') {
4026      const code = error.code ? String(error.code) : '';
4027      const msg = error.msg || error.message;
4028      if (msg) return code ? `${code}: ${String(msg)}` : String(msg);
4029    }
4030    return fallback;
4031  };
4032  const ensureGoooodAliyunCaptchaSms = () => {
4033    if (window.goooodAliyunCaptchaSms) return;
4034    let instance = null;
4035    let loading = false;
4036    let waiters = [];
4037    let pending = null;
4038    let pendingFail = null;
4039    let pendingTimer = 0;
4040    let initGuard = 0;
4041    let loadErrorGuard = 0;
4042    let visibleActionGuard = 0;
4043    let preferVisible = false;
4044    let reinitializeBeforeNextRun = false;
4045    let instanceReadyAt = 0;
4046
4047    const clearVisibleActionGuard = () => {
4048      if (visibleActionGuard) window.clearTimeout(visibleActionGuard);
4049      visibleActionGuard = 0;
4050    };
4051    const clearPendingTimer = () => {
4052      if (pendingTimer) window.clearTimeout(pendingTimer);
4053      pendingTimer = 0;
4054    };
4055    const armVisibleActionGuard = () => {
4056      clearVisibleActionGuard();
4057      visibleActionGuard = window.setTimeout(() => {
4058        if (!pending) return;
4059        reinitializeBeforeNextRun = true;
4060        rejectPending(new Error('人机验证加载超时,请重新点击获取验证码'));
4061      }, CAPTCHA_VISIBLE_ACTION_TIMEOUT_MS);
4062    };
4063    const armPendingTimer = () => {
4064      clearPendingTimer();
4065      pendingTimer = window.setTimeout(() => {
4066        rejectPending(new Error('captcha_callback_timeout'));
4067      }, CAPTCHA_VERIFY_TIMEOUT_MS);
4068    };
4069    const clearInitGuard = () => {
4070      if (initGuard) window.clearTimeout(initGuard);
4071      initGuard = 0;
4072      if (loadErrorGuard) window.clearTimeout(loadErrorGuard);
4073      loadErrorGuard = 0;
4074    };
4075    const finish = (payload) => {
4076      const value = normalizeCaptchaParam(payload);
4077      if (!value) {
4078        rejectPending(new Error('人机验证结果无效,请重新点击获取验证码'));
4079        return;
4080      }
4081      clearPendingTimer();
4082      clearVisibleActionGuard();
4083      clearInitGuard();
4084      loading = false;
4085      reinitializeBeforeNextRun = true;
4086      resolveWaiters();
4087      const callback = pending;
4088      pending = null;
4089      pendingFail = null;
4090      if (callback) callback(value);
4091    };
4092    const handleChallengeFailure = () => {
4093      // Aliyun refreshes a failed challenge in-place. Keep this request pending so
4094      // the user can complete the refreshed challenge without clicking SMS again.
4095    };
4096    const handleLoadError = (error) => {
4097      reinitializeBeforeNextRun = true;
4098      logCaptchaDiagnostic(instance ? 'sdk_on_error_after_instance' : 'sdk_on_error_before_instance', {
4099        message: captchaErrorMessage(error, '')
4100      });
4101      if (instance) {
4102        if (pending) rejectPending(error || new Error('人机验证网络请求超时,请重新点击获取验证码'));
4103        return;
4104      }
4105      // The SDK can report a transient resource timeout before getInstance arrives.
4106      // Give that late initialization a short recovery window instead of showing a
4107      // terminal business error while the challenge is still appearing.
4108      if (!loading || instance) return;
4109      if (loadErrorGuard) window.clearTimeout(loadErrorGuard);
4110      loadErrorGuard = window.setTimeout(() => {
4111        loadErrorGuard = 0;
4112        if (!loading || instance) return;
4113        loading = false;
4114        if (initGuard) window.clearTimeout(initGuard);
4115        initGuard = 0;
4116        rejectWaiters(error || new Error('人机验证加载超时,请刷新后重试'));
4117      }, CAPTCHA_LOAD_ERROR_GRACE_MS);
4118    };
4119    const rejectPending = (error) => {
4120      clearVisibleActionGuard();
4121      clearPendingTimer();
4122      clearInitGuard();
4123      loading = false;
4124      const callback = pendingFail;
4125      pending = null;
4126      pendingFail = null;
4127      if (callback) callback(error);
4128    };
4129    const resolveWaiters = () => {
4130      const queue = waiters.slice();
4131      waiters = [];
4132      queue.forEach(({ resolve }) => resolve());
4133    };
4134    const rejectWaiters = (error) => {
4135      const queue = waiters.slice();
4136      waiters = [];
4137      queue.forEach(({ reject }) => reject(error));
4138    };
4139    const ready = (resolve, reject) => {
4140      ensureAliyunCaptchaElements();
4141      loadAliyunCaptchaScript().then(() => {
4142        if (instance) { resolve(); return; }
4143        waiters.push({ resolve, reject });
4144        if (loading) return;
4145        loading = true;
4146        initGuard = window.setTimeout(() => {
4147          if (!loading) return;
4148          loading = false;
4149          rejectWaiters(new Error('captcha_init_timeout'));
4150        }, CAPTCHA_INIT_TIMEOUT_MS);
4151
4152      try {
4153        window.initAliyunCaptcha({
4154          SceneId: '1rjb4fqs',
4155          mode: 'popup',
4156          element: '#gooood-aliyun-captcha-element',
4157          button: '#gooood-aliyun-captcha-button',
4158          success: finish,
4159          fail: handleChallengeFailure,
4160          onError: handleLoadError,
4161          getInstance: (captcha) => {
4162            clearInitGuard();
4163            instance = captcha;
4164            instanceReadyAt = Date.now();
4165            logCaptchaDiagnostic('sdk_instance_ready', {
4166              hasStartTracelessVerification: typeof captcha.startTracelessVerification === 'function',
4167              hasShow: typeof captcha.show === 'function',
4168              resources: aliyunResourceDiagnostics()
4169            });
4170            loading = false;
4171            resolveWaiters();
4172          },
4173          slideStyle: { width: 360, height: 40 },
4174          timeout: CAPTCHA_REQUEST_TIMEOUT_MS,
4175          rem: CAPTCHA_UI_SCALE,
4176          showErrorTip: false,
4177          language: 'cn'
4178        });
4179      } catch (error) {
4180        clearInitGuard();
4181        loading = false;
4182        rejectWaiters(error);
4183      }
4184      }).catch(reject);
4185    };
4186
4187    window.goooodAliyunCaptchaPreferVisible = () => {
4188      preferVisible = true;
4189    };
4190
4191    const resetCompletedCaptcha = () => {
4192      if (!reinitializeBeforeNextRun) return;
4193      try {
4194        const result = instance && instance.hide ? instance.hide() : null;
4195        if (result && typeof result.then === 'function') {
4196          Promise.resolve(result).catch(() => {});
4197        }
4198      } catch (_) {
4199        // A completed V3 instance is discarded even if its best-effort hide fails.
4200      }
4201      instance = null;
4202      instanceReadyAt = 0;
4203      reinitializeBeforeNextRun = false;
4204    };
4205
4206    const clickCaptchaButton = () => {
4207      const button = document.getElementById('gooood-aliyun-captcha-button');
4208      if (!button) return false;
4209      try {
4210        button.click();
4211      } catch (error) {
4212        rejectPending(error);
4213      }
4214      return true;
4215    };
4216    const runPendingCaptchaAction = () => {
4217      if (!pending) return;
4218      armPendingTimer();
4219      try {
4220        preferVisible = false;
4221        logCaptchaDiagnostic('sdk_button_click', {
4222          instanceAgeMs: instanceReadyAt ? Date.now() - instanceReadyAt : 0,
4223          hasStartTracelessVerification: typeof (instance && instance.startTracelessVerification) === 'function',
4224          hasShow: typeof (instance && instance.show) === 'function'
4225        });
4226        if (clickCaptchaButton()) {
4227          armVisibleActionGuard();
4228          return;
4229        }
4230        throw new Error('captcha_button_missing');
4231      } catch (error) {
4232        rejectPending(error);
4233      }
4234    };
4235
4236    window.goooodAliyunCaptchaSms = (ok, fail) => {
4237      pending = ok;
4238      pendingFail = fail || null;
4239      resetCompletedCaptcha();
4240      ready(() => {
4241        if (!pending) return;
4242        const warmupRemaining = Math.max(0, CAPTCHA_MIN_WARMUP_MS - (Date.now() - instanceReadyAt));
4243        if (warmupRemaining > 0) {
4244          window.setTimeout(runPendingCaptchaAction, warmupRemaining);
4245          return;
4246        }
4247        runPendingCaptchaAction();
4248      }, rejectPending);
4249    };
4250
4251    window.setTimeout(() => {
4252      ready(() => {}, () => {});
4253    }, 0);
4254
4255  };
4256  const runSmsCaptcha = async () => {
4257    ensureGoooodAliyunCaptchaSms();
4258    return new Promise((resolve, reject) => {
4259      window.goooodAliyunCaptchaSms(resolve, (error) => {
4260        reject(new Error(captchaErrorMessage(error, '人机验证超时,请刷新后重试')));
4261      });
4262    });
4263  };
4264  const preferVisibleSmsCaptcha = () => {
4265    ensureGoooodAliyunCaptchaSms();
4266    if (window.goooodAliyunCaptchaPreferVisible) window.goooodAliyunCaptchaPreferVisible();
4267  };
4268  const isCaptchaVerifyFailure = (source) => {
4269    const records = [source];
4270    if (source && typeof source === 'object' && source.data) records.push(source.data);
4271    return records.some((item) => {
4272      if (!item) return false;
4273      if (typeof item === 'string') return item.includes('captcha_verify_failed') || item.includes('人机验证');
4274      if (item instanceof Error) return isCaptchaVerifyFailure(item.message);
4275      if (typeof item !== 'object') return false;
4276      return [item.code, item.msg, item.message, item.error].some((value) => {
4277        const text = String(value || '');
4278        return text.includes('captcha_verify_failed') || text.includes('人机验证') || text.includes('captcha');
4279      });
4280    });
4281  };
4282  const requestSmsCodeWithCaptcha = async (request, failureMessage) => {
4283    setFeedback('正在加载人机验证...');
4284    const captchaVerifyParam = await runSmsCaptcha();
4285    try {
4286      const response = await request(captchaVerifyParam);
4287      if (!responseSucceeded(response)) {
4288        if (isCaptchaVerifyFailure(response)) {
4289          preferVisibleSmsCaptcha();
4290          throw new Error('人机验证未通过,请再次点击获取验证码完成安全验证。');
4291        }
4292        throw new Error(responseMessage(response, failureMessage));
4293      }
4294      return response;
4295    } catch (error) {
4296      if (isCaptchaVerifyFailure(error)) {
4297        preferVisibleSmsCaptcha();
4298        throw new Error('人机验证未通过,请再次点击获取验证码完成安全验证。');
4299      }
4300      throw error;
4301    }
4302  };
4303  const setForgotMethod = (method) => {
4304    forgotMethod = method;
4305    modal.querySelectorAll('[data-forgot-method-panel]').forEach((panel) => {
4306      const active = authMode === 'forgot' && panel.dataset.forgotMethodPanel === method;
4307      panel.hidden = !active;
4308      panel.querySelectorAll('input, select').forEach((control) => {
4309        control.disabled = !active;
4310        control.required = active;
4311      });
4312    });
4313    if (authMode === 'forgot') {
4314      titleNode.dataset.zh = method === 'phone' ? '重置密码' : '忘记密码';
4315      titleNode.dataset.en = method === 'phone' ? 'Reset Password' : 'Forgot Password';
4316      submitButton.dataset.zh = method === 'phone' ? '保存修改' : 'Get New Password';
4317      submitButton.dataset.en = method === 'phone' ? 'Save changes' : 'Get New Password';
4318    }
4319    if (method === 'phone') loadTelCodes();
4320    applyModalLanguage();
4321  };
4322  const setMode = (mode, keepFeedback = false) => {
4323    authMode = mode;
4324    setError('');
4325    if (!keepFeedback) setFeedback('');
4326    modal.querySelectorAll('[data-auth-panel]').forEach((panel) => {
4327      const active = panel.dataset.authPanel === mode;
4328      panel.hidden = !active;
4329      panel.querySelectorAll('input, select').forEach((input) => {
4330        const nestedForgotPanel = input.closest('[data-forgot-method-panel]');
4331        input.disabled = !active || (nestedForgotPanel && nestedForgotPanel.dataset.forgotMethodPanel !== forgotMethod);
4332        input.required = active && (!nestedForgotPanel || nestedForgotPanel.dataset.forgotMethodPanel === forgotMethod);
4333      });
4334    });
4335    if (mode !== 'forgot') setForgotMethod('email');
4336    if (mode === 'login') {
4337      titleNode.dataset.zh = '会员登录';
4338      titleNode.dataset.en = 'Member Login';
4339      submitButton.dataset.zh = '登录';
4340      submitButton.dataset.en = 'Login';
4341      socialBlock.hidden = false;
4342      syncWechatLoginEntry();
4343    } else if (mode === 'register') {
4344      titleNode.dataset.zh = '手机号注册';
4345      titleNode.dataset.en = 'Mobile Register';
4346      submitButton.dataset.zh = '注册';
4347      submitButton.dataset.en = 'Register';
4348      socialBlock.hidden = true;
4349      loadTelCodes();
4350    } else {
4351      setForgotMethod(forgotMethod);
4352      socialBlock.hidden = true;
4353    }
4354    modal.querySelectorAll('[data-auth-mode-button]').forEach((button) => {
4355      const target = button.dataset.authModeButton;
4356      if (target === 'register') {
4357        button.dataset.zh = mode === 'register' ? '返回登录' : '手机号注册 »';
4358        button.dataset.en = mode === 'register' ? 'Back to login' : 'Mobile register »';
4359        button.dataset.authModeTarget = mode === 'register' ? 'login' : 'register';
4360      } else {
4361        button.dataset.zh = mode === 'forgot' ? '返回登录' : '忘记密码?';
4362        button.dataset.en = mode === 'forgot' ? 'Back to login' : 'Forgot password?';
4363        button.dataset.authModeTarget = mode === 'forgot' ? 'login' : 'forgot';
4364      }
4365    });
4366    applyModalLanguage();
4367    updateCodeButton('register');
4368    updateCodeButton('forgot');
4369  };
4370  const openModal = (mode = 'login') => {
4371    ensureGoooodAliyunCaptchaSms();
4372    setMode(mode);
4373    modal.hidden = false;
4374    document.body.classList.add('gooood-auth-open');
4375    const focusTarget = authMode === 'register' ? form.elements.register_mobile : authMode === 'forgot' ? form.elements.reset_login : form.elements.username;
4376    window.setTimeout(() => focusTarget && focusTarget.focus(), 0);
4377  };
4378  const closeModal = () => { modal.hidden = true; document.body.classList.remove('gooood-auth-open'); setError(''); setFeedback(''); };
4379  const favoriteContains = (favorites, postId) => Array.isArray(favorites) && favorites.some((entry) => typeof entry === 'number' || typeof entry === 'string' ? Number(entry) === postId : Number(entry && entry.post_id) === postId);
4380  const setFavoriteState = (trigger, active) => {
4381    if (!trigger) return;
4382    trigger.classList.toggle('is-favorited', active);
4383    trigger.setAttribute('aria-pressed', String(active));
4384    const icon = trigger.querySelector('.action-icon');
4385    const label = trigger.querySelector('[data-zh][data-en]');
4386    if (icon) icon.textContent = active ? '★' : '☆';
4387    if (label) { label.dataset.zh = active ? '已收藏' : '收藏'; label.dataset.en = active ? 'Saved' : 'Favorites'; label.textContent = currentLanguage() === 'en' ? label.dataset.en : label.dataset.zh; }
4388  };
4389  const toggleFavorite = async (favorite) => {
4390    const { trigger, postId, typeId } = favorite || {};
4391    if (!trigger || !postId || !typeId) { showToast('文章收藏信息尚未加载,请稍后重试', 'Favorite data is still loading. Please try again.'); return; }
4392    trigger.classList.add('is-pending');
4393    try {
4394      const response = await apiRequest('/wp/v2/fav', { method: 'POST', body: { post_id: postId, type_id: typeId } });
4395      const active = favoriteContains(response.favorites, postId);
4396      setFavoriteState(trigger, active);
4397      showToast(active ? '已收藏' : '已取消收藏', active ? 'Saved' : 'Removed from favorites');
4398    } catch (error) {
4399      if (isConfirmedAuthInvalidation(error)) { clearToken(); pendingFavorite = favorite; openModal(); }
4400      else showToast(error.message || '收藏失败', error.message || 'Unable to save');
4401    } finally { trigger.classList.remove('is-pending'); }
4402  };
4403  const articleFavoriteFrom = (trigger) => {
4404    const article = trigger.closest('.article');
4405    return { trigger, postId: Number(article && article.dataset.backendPostId), typeId: Number(article && article.dataset.backendPrimaryTypeId) };
4406  };
4407  const normalizeBrokenTargets = () => {
4408    document.querySelectorAll('a[href]').forEach((link) => {
4409      let pathname = '';
4410      try { pathname = new URL(link.href, window.location.href).pathname.replace(/\/$/, '') || '/'; } catch (_) {}
4411      const isLoginHash = link.hash === '#login';
4412      if (!BROKEN_ACCOUNT_PATHS.has(pathname) && !isLoginHash) return;
4413      link.href = '#login';
4414      if (link.classList.contains('favorite-action') || link.closest('.article-actions')) { link.dataset.goooodFavoriteTrigger = '1'; link.setAttribute('role', 'button'); }
4415      else { link.dataset.goooodLoginTrigger = '1'; link.setAttribute('role', 'button'); }
4416    });
4417  };
4418
4419  modal.querySelector('.gooood-auth-close').addEventListener('click', closeModal);
4420  document.querySelectorAll('[data-lang-toggle]').forEach((button) => {
4421    button.addEventListener('click', (event) => {
4422      event.preventDefault();
4423      event.stopImmediatePropagation();
4424      switchLanguage(currentPathLanguage() === 'en' ? 'zh' : 'en');
4425    }, true);
4426  });
4427  modal.addEventListener('click', (event) => { if (event.target === modal) closeModal(); });
4428  document.addEventListener('keydown', (event) => {
4429    if (event.key !== 'Escape') return;
4430    if (!modal.hidden) closeModal();
4431    closeAccountMenus();
4432  });
4433  codeButtons.forEach((button) => {
4434    button.addEventListener('click', async () => {
4435      const kind = button.dataset.codeKind || 'register';
4436      setError(''); setFeedback('');
4437      const mobile = kind === 'forgot' ? form.elements.forgot_mobile.value.trim() : form.elements.register_mobile.value.trim();
4438      const region = kind === 'forgot' ? form.elements.forgot_region.value : form.elements.register_region.value;
4439      if (!mobile) { setError('请输入手机号'); return; }
4440      if ((kind === 'forgot' ? forgotCountdown : registerCountdown) > 0) return;
4441      updateCodeButton(kind, true);
4442      try {
4443        const response = await requestSmsCodeWithCaptcha((captchaVerifyParam) => apiRequest('/wp/v2/sms202601', {
4444          method: 'POST',
4445          auth: false,
4446          body: {
4447            region_number: region || '86',
4448            mobile,
4449            event: kind === 'forgot' ? 'editpass' : 'register',
4450            captchaVerifyParam,
4451            CaptchaVerifyParam: captchaVerifyParam
4452          }
4453        }), '验证码发送失败,请稍后重试。');
4454        setFeedback(responseMessage(response, '验证码已发送,请查收短信。'));
4455        startCodeCountdown(kind);
4456      } catch (error) { setFeedback(''); setError(error.message || '验证码发送失败,请稍后重试。'); }
4457      finally { updateCodeButton(kind, false); }
4458    });
4459  });
4460  modal.querySelectorAll('[data-auth-mode-button]').forEach((button) => {
4461    button.addEventListener('click', () => setMode(button.dataset.authModeTarget || 'login'));
4462  });
4463  modal.querySelectorAll('[data-auth-forgot-method]').forEach((button) => {
4464    button.addEventListener('click', () => {
4465      setError('');
4466      setFeedback('');
4467      setForgotMethod(button.dataset.authForgotMethod || 'email');
4468    });
4469  });
4470  form.addEventListener('submit', async (event) => {
4471    event.preventDefault(); setError(''); setFeedback(''); submitButton.disabled = true;
4472    try {
4473      if (authMode === 'register') {
4474        const mobile = form.elements.register_mobile.value.trim();
4475        const region = form.elements.register_region.value || '86';
4476        const password = form.elements.register_password.value;
4477        const password2 = form.elements.register_password2.value;
4478        if (password !== password2) throw new Error('两次输入的密码必须一致');
4479        const response = await apiRequest('/wp/v2/user/register', { method: 'POST', auth: false, body: { region_number: region, user_mobile: mobile, sms_code: form.elements.register_code.value.trim(), user_pass: password, user_pass2: password2, from_source: 2 } });
4480        if (!responseSucceeded(response)) throw new Error(responseMessage(response, '注册失败,请检查信息后重试。'));
4481        form.elements.username.value = mobile;
4482        form.elements.password.value = '';
4483        form.elements.register_code.value = '';
4484        form.elements.register_password.value = '';
4485        form.elements.register_password2.value = '';
4486        setFeedback(responseMessage(response, '注册成功,请使用手机号和密码登录。'));
4487        setMode('login', true);
4488      } else if (authMode === 'forgot') {
4489        if (forgotMethod === 'phone') {
4490          const mobile = form.elements.forgot_mobile.value.trim();
4491          const smsCode = form.elements.forgot_code.value.trim();
4492          const password = form.elements.forgot_password.value;
4493          const password2 = form.elements.forgot_password2.value;
4494          if (!mobile) throw new Error('请输入手机号');
4495          if (!smsCode) throw new Error('请输入验证码');
4496          if (!password) throw new Error('请输入新密码');
4497          if (password !== password2) throw new Error('两次输入的密码必须一致');
4498          const response = await apiRequest('/wp/v2/account/editpass', { method: 'POST', auth: false, body: { password: password2, mobile, sms_code: smsCode } });
4499          if (!responseSucceeded(response)) throw new Error(responseMessage(response, '密码修改失败,请检查信息后重试。'));
4500          form.elements.username.value = mobile;
4501          form.elements.password.value = '';
4502          form.elements.forgot_code.value = '';
4503          form.elements.forgot_password.value = '';
4504          form.elements.forgot_password2.value = '';
4505          setFeedback(responseMessage(response, '密码已修改,请返回登录。'));
4506          setMode('login', true);
4507        } else {
4508          const response = await apiRequest('/wp/v2/account/forgotpwd', { method: 'POST', auth: false, body: { user_login: form.elements.reset_login.value.trim() } });
4509          if (!responseSucceeded(response)) throw new Error(responseMessage(response, '提交失败,请稍后重试。'));
4510          setFeedback(responseMessage(response, '如果账号存在,重设密码邮件将发送到账号邮箱。'));
4511        }
4512      } else {
4513        const response = await apiRequest('/jwt-auth/v1/token', { method: 'POST', auth: false, body: { username: form.elements.username.value.trim(), password: form.elements.password.value } });
4514        if (!response.token) throw new Error('登录响应缺少 token');
4515        saveToken(response.token, response.expire);
4516        const user = await apiRequest('/wp/v2/users/me', { token: response.token });
4517        updateMemberUI(user);
4518        closeModal(); form.reset(); showToast(`登录成功${resolveDisplayName(user) ? `,欢迎 ${resolveDisplayName(user)}` : ''}`, 'Logged in');
4519        if (pendingFavorite) { const favorite = pendingFavorite; pendingFavorite = null; await toggleFavorite(favorite); }
4520      }
4521    } catch (error) {
4522      if (authMode === 'login') clearToken();
4523      setError(error.message || (authMode === 'register' ? '注册失败,请检查信息后重试。' : authMode === 'forgot' ? '提交失败,请稍后重试。' : '登录失败'));
4524    }
4525    finally { submitButton.disabled = false; }
4526  });
4527  wechatButton.addEventListener('click', async () => {
4528    if (isExternalMobileWechatLogin()) {
4529      syncWechatLoginEntry();
4530      setFeedback('请在微信内打开本页后,再使用微信登录。');
4531      return;
4532    }
4533    setError(''); wechatButton.disabled = true;
4534    try {
4535      const response = await apiRequest('/wp/v2/account/oauth', { method: 'POST', auth: false, body: { action: 'login', target: 'wechat', back: window.location.pathname + window.location.search } });
4536      const destination = response.url || response.redirect || response.location;
4537      if (!destination) throw new Error('微信登录暂时不可用');
4538      window.location.href = destination;
4539    } catch (error) { setError(error.message || '微信登录启动失败'); wechatButton.disabled = false; }
4540  });
4541  document.addEventListener('click', async (event) => {
4542    const accountToggle = event.target.closest('[data-gooood-account-toggle]');
4543    if (accountToggle) {
4544      event.preventDefault();
4545      const account = accountToggle.closest('.gooood-account');
4546      const opening = !account.classList.contains('is-open');
4547      closeAccountMenus(account);
4548      account.classList.toggle('is-open', opening);
4549      accountToggle.setAttribute('aria-expanded', String(opening));
4550      return;
4551    }
4552    const accountLogout = event.target.closest('[data-gooood-account-logout]');
4553    if (accountLogout) {
4554      event.preventDefault();
4555      try { await apiRequest('/wp/v2/users/logout', { method: 'POST' }); } catch (_) {}
4556      clearToken();
4557      updateMemberUI(null);
4558      showToast('已退出登录', 'Logged out');
4559      return;
4560    }
4561    if (!event.target.closest('.gooood-account')) closeAccountMenus();
4562    const favoriteTrigger = event.target.closest('[data-gooood-favorite-trigger], .favorite-action');
4563    if (favoriteTrigger) {
4564      event.preventDefault();
4565      const favorite = articleFavoriteFrom(favoriteTrigger);
4566      if (!cookieValue('auth_token')) { pendingFavorite = favorite; openModal(); } else await toggleFavorite(favorite);
4567      return;
4568    }
4569    const loginTrigger = event.target.closest('[data-gooood-login-trigger], a[href="#login"], a[href$="#login"]');
4570    if (!loginTrigger) return;
4571    event.preventDefault();
4572    if (!cookieValue('auth_token')) { openModal(); return; }
4573    try { const user = await apiRequest('/wp/v2/users/me'); updateMemberUI(user); showToast('当前已登录;可直接点击文章卡片上的收藏', 'You are logged in. Use Favorites on an article card.'); }
4574    catch (error) {
4575      if (isConfirmedAuthInvalidation(error)) { clearToken(); updateMemberUI(null);
4575 openModal(); }
4576      else { retainAuthAfterTemporaryFailure(); showToast('登录状态暂时无法确认,请稍后重试', 'Unable to confirm your sign-in right now. Please try again shortly.'); }
4577    }
4578  });
4579  normalizeBrokenTargets();
4580  new MutationObserver(normalizeBrokenTargets).observe(document.body, { childList: true, subtree: true });
4581  setAuthState('checking', null);
4582  if (document.readyState === 'loading') {
4583    document.addEventListener('DOMContentLoaded', () => { checkAndRestoreAuth(); });
4584  } else {
4585    checkAndRestoreAuth();
4586  }
4587})();
4588</script>
vendor: 1 bytes, line 4588
4588
4589<script data-gooood-home-share>"use strict";(()=>{var Ve=Object.create;var Ot=Object.defineProperty;var Ke=Object.getOwnPropertyDescriptor;var Je=Object.getOwnPropertyNames;var Ye=Object.getPrototypeOf,$e=Object.prototype.hasOwnProperty;var E=(o,t)=>()=>{try{return t||o((t={exports:{}}).exports,t),t.exports}catch(e){throw t=0,e}};var Ge=(o,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of Je(t))!$e.call(o,r)&&r!==e&&Ot(o,r,{get:()=>t[r],enumerable:!(n=Ke(t,r))||n.enumerable});return o};var je=(o,t,e)=>(e=o!=null?Ve(Ye(o)):{},Ge(t||!o||!o.__esModule?Ot(e,"default",{value:o,enumerable:!0}):e,o));var Vt=E((Yo,Ht)=>{Ht.exports=function(){return typeof Promise=="function"&&Promise.prototype&&Promise.prototype.then}});var _=E(z=>{var wt,Qe=[0,26,44,70,100,134,172,196,242,292,346,404,466,532,581,655,733,815,901,991,1085,1156,1258,1364,1474,1588,1706,1828,1921,2051,2185,2323,2465,2611,2761,2876,3034,3196,3362,3532,3706];z.getSymbolSize=function(t){if(!t)throw new Error('"version" cannot be null or undefined');if(t<1||t>40)throw new Error('"version" should be in range from 1 to 40');return t*4+17};z.getSymbolTotalCodewords=function(t){return Qe[t]};z.getBCHDigit=function(o){let t=0;for(;o!==0;)t++,o>>>=1;return t};z.setToSJISFunction=function(t){if(typeof t!="function")throw new Error('"toSJISFunc" is not a valid function.');wt=t};z.isKanjiModeEnabled=function(){return typeof wt!="undefined"};z.toSJIS=function(t){return wt(t)}});var it=E(P=>{P.L={bit:1};P.M={bit:0};P.Q={bit:3};P.H={bit:2};function We(o){if(typeof o!="string")throw new Error("Param is not a string");switch(o.toLowerCase()){case"l":case"low":return P.L;case"m":case"medium":return P.M;case"q":case"quartile":return P.Q;case"h":case"high":return P.H;default:throw new Error("Unknown EC Level: "+o)}}P.isValid=function(t){return t&&typeof t.bit!="undefined"&&t.bit>=0&&t.bit<4};P.from=function(t,e){if(P.isValid(t))return t;try{return We(t)}catch{return e}}});var Yt=E((jo,Jt)=>{function Kt(){this.buffer=[],this.length=0}Kt.prototype={get:function(o){let t=Math.floor(o/8);return(this.buffer[t]>>>7-o%8&1)===1},put:function(o,t){for(let e=0;e<t;e++)this.putBit((o>>>t-e-1&1)===1)},getLengthInBits:function(){return this.length},putBit:function(o){let t=Math.floor(this.length/8);this.buffer.length<=t&&this.buffer.push(0),o&&(this.buffer[t]|=128>>>this.length%8),this.length++}};Jt.exports=Kt});var Gt=E((Qo,$t)=>{function Q(o){if(!o||o<1)throw new Error("BitMatrix size must be defined and greater than 0");this.size=o,this.data=new Uint8Array(o*o),this.reservedBit=new Uint8Array(o*o)}Q.prototype.set=function(o,t,e,n){let r=o*this.size+t;this.data[r]=e,n&&(this.reservedBit[r]=!0)};Q.prototype.get=function(o,t){return this.data[o*this.size+t]};Q.prototype.xor=function(o,t,e){this.data[o*this.size+t]^=e};Q.prototype.isReserved=function(o,t){return this.reservedBit[o*this.size+t]};$t.exports=Q});var jt=E(at=>{var Xe=_().getSymbolSize;at.getRowColCoords=function(t){if(t===1)return[];let e=Math.floor(t/7)+2,n=Xe(t),r=n===145?26:Math.ceil((n-13)/(2*e-2))*2,i=[n-7];for(let a=1;a<e-1;a++)i[a]=i[a-1]-r;return i.push(6),i.reverse()};at.getPositions=function(t){let e=[],n=at.getRowColCoords(t),r=n.length;for(let i=0;i<r;i++)for(let a=0;a<r;a++)i===0&&a===0||i===0&&a===r-1||i===r-1&&a===0||e.push([n[i],n[a]]);return e}});var Xt=E(Wt=>{var Ze=_().getSymbolSize,Qt=7;Wt.getPositions=function(t){let e=Ze(t);return[[0,0],[e-Qt,0],[0,e-Qt]]}});var Zt=E(C=>{C.Patterns={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7};var F={N1:3,N2:3,N3:40,N4:10};C.isValid=function(t){return t!=null&&t!==""&&!isNaN(t)&&t>=0&&t<=7};C.from=function(t){return C.isValid(t)?parseInt(t,10):void 0};C.getPenaltyN1=function(t){let e=t.size,n=0,r=0,i=0,a=null,s=null;for(let u=0;u<e;u++){r=i=0,a=s=null;for(let f=0;f<e;f++){let g=t.get(u,f);g===a?r++:(r>=5&&(n+=F.N1+(r-5)),a=g,r=1),g=t.get(f,u),g===s?i++:(i>=5&&(n+=F.N1+(i-5)),s=g,i=1)}r>=5&&(n+=F.N1+(r-5)),i>=5&&(n+=F.N1+(i-5))}return n};C.getPenaltyN2=function(t){let e=t.size,n=0;for(let r=0;r<e-1;r++)for(let i=0;i<e-1;i++){let a=t.get(r,i)+t.get(r,i+1)+t.get(r+1,i)+t.get(r+1,i+1);(a===4||a===0)&&n++}return n*F.N2};C.getPenaltyN3=function(t){let e=t.size,n=0,r=0,i=0;for(let a=0;a<e;a++){r=i=0;for(let s=0;s<e;s++)r=r<<1&2047|t.get(a,s),s>=10&&(r===1488||r===93)&&n++,i=i<<1&2047|t.get(s,a),s>=10&&(i===1488||i===93)&&n++}return n*F.N3};C.getPenaltyN4=function(t){let e=0,n=t.data.length;for(let i=0;i<n;i++)e+=t.data[i];return Math.abs(Math.ceil(e*100/n/5)-10)*F.N4};function to(o,t,e){switch(o){case C.Patterns.PATTERN000:return(t+e)%2===0;case C.Patterns.PATTERN001:return t%2===0;case C.Patterns.PATTERN010:return e%3===0;case C.Patterns.PATTERN011:return(t+e)%3===0;case C.Patterns.PATTERN100:return(Math.floor(t/2)+Math.floor(e/3))%2===0;case C.Patterns.PATTERN101:return t*e%2+t*e%3===0;case C.Patterns.PATTERN110:return(t*e%2+t*e%3)%2===0;case C.Patterns.PATTERN111:return(t*e%3+(t+e)%2)%2===0;default:throw new Error("bad maskPattern:"+o)}}C.applyMask=function(t,e){let n=e.size;
4589for(let r=0;r<n;r++)for(let i=0;i<n;i++)e.isReserved(i,r)||e.xor(i,r,to(t,i,r))};C.getBestMask=function(t,e){let n=Object.keys(C.Patterns).length,r=0,i=1/0;for(let a=0;a<n;a++){e(a),C.applyMask(a,t);let s=C.getPenaltyN1(t)+C.getPenaltyN2(t)+C.getPenaltyN3(t)+C.getPenaltyN4(t);C.applyMask(a,t),s<i&&(i=s,r=a)}return r}});var Et=E(yt=>{var U=it(),st=[1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,4,1,2,4,4,2,4,4,4,2,4,6,5,2,4,6,6,2,5,8,8,4,5,8,8,4,5,8,11,4,8,10,11,4,9,12,16,4,9,16,16,6,10,12,18,6,10,17,16,6,11,16,19,6,13,18,21,7,14,21,25,8,16,20,25,8,17,23,25,9,17,23,34,9,18,25,30,10,20,27,32,12,21,29,35,12,23,34,37,12,25,34,40,13,26,35,42,14,28,38,45,15,29,40,48,16,31,43,51,17,33,45,54,18,35,48,57,19,37,51,60,19,38,53,63,20,40,56,66,21,43,59,70,22,45,62,74,24,47,65,77,25,49,68,81],ct=[7,10,13,17,10,16,22,28,15,26,36,44,20,36,52,64,26,48,72,88,36,64,96,112,40,72,108,130,48,88,132,156,60,110,160,192,72,130,192,224,80,150,224,264,96,176,260,308,104,198,288,352,120,216,320,384,132,240,360,432,144,280,408,480,168,308,448,532,180,338,504,588,196,364,546,650,224,416,600,700,224,442,644,750,252,476,690,816,270,504,750,900,300,560,810,960,312,588,870,1050,336,644,952,1110,360,700,1020,1200,390,728,1050,1260,420,784,1140,1350,450,812,1200,1440,480,868,1290,1530,510,924,1350,1620,540,980,1440,1710,570,1036,1530,1800,570,1064,1590,1890,600,1120,1680,1980,630,1204,1770,2100,660,1260,1860,2220,720,1316,1950,2310,750,1372,2040,2430];yt.getBlocksCount=function(t,e){switch(e){case U.L:return st[(t-1)*4+0];case U.M:return st[(t-1)*4+1];case U.Q:return st[(t-1)*4+2];case U.H:return st[(t-1)*4+3];default:return}};yt.getTotalCodewordsCount=function(t,e){switch(e){case U.L:return ct[(t-1)*4+0];case U.M:return ct[(t-1)*4+1];case U.Q:return ct[(t-1)*4+2];case U.H:return ct[(t-1)*4+3];default:return}}});var te=E(ut=>{var W=new Uint8Array(512),lt=new Uint8Array(256);(function(){let t=1;for(let e=0;e<255;e++)W[e]=t,lt[t]=e,t<<=1,t&256&&(t^=285);for(let e=255;e<512;e++)W[e]=W[e-255]})();ut.log=function(t){if(t<1)throw new Error("log("+t+")");return lt[t]};ut.exp=function(t){return W[t]};ut.mul=function(t,e){return t===0||e===0?0:W[lt[t]+lt[e]]}});var ee=E(X=>{var Ct=te();X.mul=function(t,e){let n=new Uint8Array(t.length+e.length-1);for(let r=0;r<t.length;r++)for(let i=0;i<e.length;i++)n[r+i]^=Ct.mul(t[r],e[i]);return n};X.mod=function(t,e){let n=new Uint8Array(t);for(;n.length-e.length>=0;){let r=n[0];for(let a=0;a<e.length;a++)n[a]^=Ct.mul(e[a],r);let i=0;for(;i<n.length&&n[i]===0;)i++;n=n.slice(i)}return n};X.generateECPolynomial=function(t){let e=new Uint8Array([1]);for(let n=0;n<t;n++)e=X.mul(e,new Uint8Array([1,Ct.exp(n)]));return e}});var re=E((nn,ne)=>{var oe=ee();function bt(o){this.genPoly=void 0,this.degree=o,this.degree&&this.initialize(this.degree)}bt.prototype.initialize=function(t){this.degree=t,this.genPoly=oe.generateECPolynomial(this.degree)};bt.prototype.encode=function(t){if(!this.genPoly)throw new Error("Encoder not initialized");let e=new Uint8Array(t.length+this.degree);e.set(t);let n=oe.mod(e,this.genPoly),r=this.degree-n.length;if(r>0){let i=new Uint8Array(this.degree);return i.set(n,r),i}return n};ne.exports=bt});var At=E(ie=>{ie.isValid=function(t){return!isNaN(t)&&t>=1&&t<=40}});var St=E(R=>{var ae="[0-9]+",eo="[A-Z $%*+\\-./:]+",Z="(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+";Z=Z.replace(/u/g,"\\u");var oo="(?:(?![A-Z0-9 $%*+\\-./:]|"+Z+`)(?:.|[\r
4590]))+`;R.KANJI=new RegExp(Z,"g");R.BYTE_KANJI=new RegExp("[^A-Z0-9 $%*+\\-./:]+","g");R.BYTE=new RegExp(oo,"g");R.NUMERIC=new RegExp(ae,"g");R.ALPHANUMERIC=new RegExp(eo,"g");var no=new RegExp("^"+Z+"$"),ro=new RegExp("^"+ae+"$"),io=new RegExp("^[A-Z0-9 $%*+\\-./:]+$");R.testKanji=function(t){return no.test(t)};R.testNumeric=function(t){return ro.test(t)};R.testAlphanumeric=function(t){return io.test(t)}});var D=E(A=>{var ao=At(),Bt=St();A.NUMERIC={id:"Numeric",bit:1,ccBits:[10,12,14]};A.ALPHANUMERIC={id:"Alphanumeric",bit:2,ccBits:[9,11,13]};A.BYTE={id:"Byte",bit:4,ccBits:[8,16,16]};A.KANJI={id:"Kanji",bit:8,ccBits:[8,10,12]};A.MIXED={bit:-1};A.getCharCountIndicator=function(t,e){if(!t.ccBits)throw new Error("Invalid mode: "+t);if(!ao.isValid(e))throw new Error("Invalid version: "+e);return e>=1&&e<10?t.ccBits[0]:e<27?t.ccBits[1]:t.ccBits[2]};A.getBestModeForData=function(t){return Bt.testNumeric(t)?A.NUMERIC:Bt.testAlphanumeric(t)?A.ALPHANUMERIC:Bt.testKanji(t)?A.KANJI:A.BYTE};A.toString=function(t){if(t&&t.id)return t.id;throw new Error("Invalid mode")};A.isValid=function(t){return t&&t.bit&&t.ccBits};function so(o){if(typeof o!="string")throw new Error("Param is not a string");switch(o.toLowerCase()){case"numeric":return A.NUMERIC;case"alphanumeric":return A.ALPHANUMERIC;case"kanji":return A.KANJI;case"byte":return A.BYTE;default:throw new Error("Unknown mode: "+o)}}A.from=function(t,e){if(A.isValid(t))return t;try{return so(t)}catch{return e}}});var de=E(O=>{var dt=_(),co=Et(),se=it(),k=D(),xt=At(),le=7973,ce=dt.getBCHDigit
4590(le);function lo(o,t,e){for(let n=1;n<=40;n++)if(t<=O.getCapacity(n,e,o))return n}function ue(o,t){return k.getCharCountIndicator(o,t)+4}function uo(o,t){let e=0;return o.forEach(function(n){let r=ue(n.mode,t);e+=r+n.getBitsLength()}),e}function ho(o,t){for(let e=1;e<=40;e++)if(uo(o,e)<=O.getCapacity(e,t,k.MIXED))return e}O.from=function(t,e){return xt.isValid(t)?parseInt(t,10):e};O.getCapacity=function(t,e,n){if(!xt.isValid(t))throw new Error("Invalid QR Code version");typeof n=="undefined"&&(n=k.BYTE);let r=dt.getSymbolTotalCodewords(t),i=co.getTotalCodewordsCount(t,e),a=(r-i)*8;if(n===k.MIXED)return a;let s=a-ue(n,t);switch(n){case k.NUMERIC:return Math.floor(s/10*3);case k.ALPHANUMERIC:return Math.floor(s/11*2);case k.KANJI:return Math.floor(s/13);case k.BYTE:default:return Math.floor(s/8)}};O.getBestVersionForData=function(t,e){let n,r=se.from(e,se.M);if(Array.isArray(t)){if(t.length>1)return ho(t,r);if(t.length===0)return 1;n=t[0]}else n=t;return lo(n.mode,n.getLength(),r)};O.getEncodedBits=function(t){if(!xt.isValid(t)||t<7)throw new Error("Invalid QR Code version");let e=t<<12;for(;dt.getBCHDigit(e)-ce>=0;)e^=le<<dt.getBCHDigit(e)-ce;return t<<12|e}});var pe=E(ge=>{var Tt=_(),fe=1335,fo=21522,he=Tt.getBCHDigit(fe);ge.getEncodedBits=function(t,e){let n=t.bit<<3|e,r=n<<10;for(;Tt.getBCHDigit(r)-he>=0;)r^=fe<<Tt.getBCHDigit(r)-he;return(n<<10|r)^fo}});var we=E((un,me)=>{var go=D();function J(o){this.mode=go.NUMERIC,this.data=o.toString()}J.getBitsLength=function(t){return 10*Math.floor(t/3)+(t%3?t%3*3+1:0)};J.prototype.getLength=function(){return this.data.length};J.prototype.getBitsLength=function(){return J.getBitsLength(this.data.length)};J.prototype.write=function(t){let e,n,r;for(e=0;e+3<=this.data.length;e+=3)n=this.data.substr(e,3),r=parseInt(n,10),t.put(r,10);let i=this.data.length-e;i>0&&(n=this.data.substr(e),r=parseInt(n,10),t.put(r,i*3+1))};me.exports=J});var Ee=E((dn,ye)=>{var po=D(),It=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"," ","$","%","*","+","-",".","/",":"];function Y(o){this.mode=po.ALPHANUMERIC,this.data=o}Y.getBitsLength=function(t){return 11*Math.floor(t/2)+6*(t%2)};Y.prototype.getLength=function(){return this.data.length};Y.prototype.getBitsLength=function(){return Y.getBitsLength(this.data.length)};Y.prototype.write=function(t){let e;for(e=0;e+2<=this.data.length;e+=2){let n=It.indexOf(this.data[e])*45;n+=It.indexOf(this.data[e+1]),t.put(n,11)}this.data.length%2&&t.put(It.indexOf(this.data[e]),6)};ye.exports=Y});var be=E((hn,Ce)=>{var mo=D();function $(o){this.mode=mo.BYTE,typeof o=="string"?this.data=new TextEncoder().encode(o):this.data=new Uint8Array(o)}$.getBitsLength=function(t){return t*8};$.prototype.getLength=function(){return this.data.length};$.prototype.getBitsLength=function(){return $.getBitsLength(this.data.length)};$.prototype.write=function(o){for(let t=0,e=this.data.length;t<e;t++)o.put(this.data[t],8)};Ce.exports=$});var Se=E((fn,Ae)=>{var wo=D(),yo=_();function G(o){this.mode=wo.KANJI,this.data=o}G.getBitsLength=function(t){return t*13};G.prototype.getLength=function(){return this.data.length};G.prototype.getBitsLength=function(){return G.getBitsLength(this.data.length)};G.prototype.write=function(o){let t;for(t=0;t<this.data.length;t++){let e=yo.toSJIS(this.data[t]);if(e>=33088&&e<=40956)e-=33088;else if(e>=57408&&e<=60351)e-=49472;else throw new Error("Invalid SJIS character: "+this.data[t]+`
4591Make sure your charset is UTF-8`);e=(e>>>8&255)*192+(e&255),o.put(e,13)}};Ae.exports=G});var Be=E((gn,Mt)=>{"use strict";var tt={single_source_shortest_paths:function(o,t,e){var n={},r={};r[t]=0;var i=tt.PriorityQueue.make();i.push(t,0);for(var a,s,u,f,g,b,w,S,M;!i.empty();){a=i.pop(),s=a.value,f=a.cost,g=o[s]||{};for(u in g)g.hasOwnProperty(u)&&(b=g[u],w=f+b,S=r[u],M=typeof r[u]=="undefined",(M||S>w)&&(r[u]=w,i.push(u,w),n[u]=s))}if(typeof e!="undefined"&&typeof r[e]=="undefined"){var x=["Could not find a path from ",t," to ",e,"."].join("");throw new Error(x)}return n},extract_shortest_path_from_predecessor_list:function(o,t){for(var e=[],n=t,r;n;)e.push(n),r=o[n],n=o[n];return e.reverse(),e},find_path:function(o,t,e){var n=tt.single_source_shortest_paths(o,t,e);return tt.extract_shortest_path_from_predecessor_list(n,e)},PriorityQueue:{make:function(o){var t=tt.PriorityQueue,e={},n;o=o||{};for(n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e.queue=[],e.sorter=o.sorter||t.default_sorter,e},default_sorter:function(o,t){return o.cost-t.cost}
4591,push:function(o,t){var e={value:o,cost:t};this.queue.push(e),this.queue.sort(this.sorter)},pop:function(){return this.queue.shift()},empty:function(){return this.queue.length===0}}};typeof Mt!="undefined"&&(Mt.exports=tt)});var Re=E(j=>{var p=D(),Ie=we(),Me=Ee(),Ne=be(),Pe=Se(),et=St(),ht=_(),Eo=Be();function xe(o){return unescape(encodeURIComponent(o)).length}function ot(o,t,e){let n=[],r;for(;(r=o.exec(e))!==null;)n.push({data:r[0],index:r.index,mode:t,length:r[0].length});return n}function Le(o){let t=ot(et.NUMERIC,p.NUMERIC,o),e=ot(et.ALPHANUMERIC,p.ALPHANUMERIC,o),n,r;return ht.isKanjiModeEnabled()?(n=ot(et.BYTE,p.BYTE,o),r=ot(et.KANJI,p.KANJI,o)):(n=ot(et.BYTE_KANJI,p.BYTE,o),r=[]),t.concat(e,n,r).sort(function(a,s){return a.index-s.index}).map(function(a){return{data:a.data,mode:a.mode,length:a.length}})}function Nt(o,t){switch(t){case p.NUMERIC:return Ie.getBitsLength(o);case p.ALPHANUMERIC:return Me.getBitsLength(o);case p.KANJI:return Pe.getBitsLength(o);case p.BYTE:return Ne.getBitsLength(o)}}function Co(o){return o.reduce(function(t,e){let n=t.length-1>=0?t[t.length-1]:null;return n&&n.mode===e.mode?(t[t.length-1].data+=e.data,t):(t.push(e),t)},[])}function bo(o){let t=[];for(let e=0;e<o.length;e++){let n=o[e];switch(n.mode){case p.NUMERIC:t.push([n,{data:n.data,mode:p.ALPHANUMERIC,length:n.length},{data:n.data,mode:p.BYTE,length:n.length}]);break;case p.ALPHANUMERIC:t.push([n,{data:n.data,mode:p.BYTE,length:n.length}]);break;case p.KANJI:t.push([n,{data:n.data,mode:p.BYTE,length:xe(n.data)}]);break;case p.BYTE:t.push([{data:n.data,mode:p.BYTE,length:xe(n.data)}])}}return t}function Ao(o,t){let e={},n={start:{}},r=["start"];for(let i=0;i<o.length;i++){let a=o[i],s=[];for(let u=0;u<a.length;u++){let f=a[u],g=""+i+u;s.push(g),e[g]={node:f,lastCount:0},n[g]={};for(let b=0;b<r.length;b++){let w=r[b];e[w]&&e[w].node.mode===f.mode?(n[w][g]=Nt(e[w].lastCount+f.length,f.mode)-Nt(e[w].lastCount,f.mode),e[w].lastCount+=f.length):(e[w]&&(e[w].lastCount=f.length),n[w][g]=Nt(f.length,f.mode)+4+p.getCharCountIndicator(f.mode,t))}}r=s}for(let i=0;i<r.length;i++)n[r[i]].end=0;return{map:n,table:e}}function Te(o,t){let e,n=p.getBestModeForData(o);if(e=p.from(t,n),e!==p.BYTE&&e.bit<n.bit)throw new Error('"'+o+'" cannot be encoded with mode '+p.toString(e)+`.
4592 Suggested mode is: `+p.toString(n));switch(e===p.KANJI&&!ht.isKanjiModeEnabled()&&(e=p.BYTE),e){case p.NUMERIC:return new Ie(o);case p.ALPHANUMERIC:return new Me(o);case p.KANJI:return new Pe(o);case p.BYTE:return new Ne(o)}}j.fromArray=function(t){return t.reduce(function(e,n){return typeof n=="string"?e.push(Te(n,null)):n.data&&e.push(Te(n.data,n.mode)),e},[])};j.fromString=function(t,e){let n=Le(t,ht.isKanjiModeEnabled()),r=bo(n),i=Ao(r,e),a=Eo.find_path(i.map,"start","end"),s=[];for(let u=1;u<a.length-1;u++)s.push(i.table[a[u]].node);return j.fromArray(Co(s))};j.rawSplit=function(t){return j.fromArray(Le(t,ht.isKanjiModeEnabled()))}});var _e=E(qe=>
4592{var gt=_(),Pt=it(),So=Yt(),Bo=Gt(),xo=jt(),To=Xt(),qt=Zt(),_t=Et(),Io=re(),ft=de(),Mo=pe(),No=D(),Lt=Re();function Po(o,t){let e=o.size,n=To.getPositions(t);for(let r=0;r<n.length;r++){let i=n[r][0],a=n[r][1];for(let s=-1;s<=7;s++)if(!(i+s<=-1||e<=i+s))for(let u=-1;u<=7;u++)a+u<=-1||e<=a+u||(s>=0&&s<=6&&(u===0||u===6)||u>=0&&u<=6&&(s===0||s===6)||s>=2&&s<=4&&u>=2&&u<=4?o.set(i+s,a+u,!0,!0):o.set(i+s,a+u,!1,!0))}}function Lo(o){let t=o.size;for(let e=8;e<t-8;e++){let n=e%2===0;o.set(e,6,n,!0),o.set(6,e,n,!0)}}function Ro(o,t){let e=xo.getPositions(t);for(let n=0;n<e.length;n++){let r=e[n][0],i=e[n][1];for(let a=-2;a<=2;a++)for(let s=-2;s<=2;s++)a===-2||a===2||s===-2||s===2||a===0&&s===0?o.set(r+a,i+s,!0,!0):o.set(r+a,i+s,!1,!0)}}function qo(o,t){let e=o.size,n=ft.getEncodedBits(t),r,i,a;for(let s=0;s<18;s++)r=Math.floor(s/3),i=s%3+e-8-3,a=(n>>s&1)===1,o.set(r,i,a,!0),o.set(i,r,a,!0)}function Rt(o,t,e){let n=o.size,r=Mo.getEncodedBits(t,e),i,a;for(i=0;i<15;i++)a=(r>>i&1)===1,i<6?o.set(i,8,a,!0):i<8?o.set(i+1,8,a,!0):o.set(n-15+i,8,a,!0),i<8?o.set(8,n-i-1,a,!0):i<9?o.set(8,15-i-1+1,a,!0):o.set(8,15-i-1,a,!0);o.set(n-8,8,1,!0)}function _o(o,t){let e=o.size,n=-1,r=e-1,i=7,a=0;for(let s=e-1;s>0;s-=2)for(s===6&&s--;;){for(let u=0;u<2;u++)if(!o.isReserved(r,s-u)){let f=!1;a<t.length&&(f=(t[a]>>>i&1)===1),o.set(r,s-u,f),i--,i===-1&&(a++,i=7)}if(r+=n,r<0||e<=r){r-=n,n=-n;break}}}function Uo(o,t,e){let n=new So;e.forEach(function(u){n.put(u.mode.bit,4),n.put(u.getLength(),No.getCharCountIndicator(u.mode,o)),u.write(n)});let r=gt.getSymbolTotalCodewords(o),i=_t.getTotalCodewordsCount(o,t),a=(r-i)*8;for(n.getLengthInBits()+4<=a&&n.put(0,4);n.getLengthInBits()%8!==0;)n.putBit(0);let s=(a-n.getLengthInBits())/8;for(let u=0;u<s;u++)n.put(u%2?17:236,8);return Do(n,o,t)}function Do(o,t,e){let n=gt.getSymbolTotalCodewords(t),r=_t.getTotalCodewordsCount(t,e),i=n-r,a=_t.getBlocksCount(t,e),s=n%a,u=a-s,f=Math.floor(n/a),g=Math.floor(i/a),b=g+1,w=f-g,S=new Io(w),M=0,x=new Array(a),m=new Array(a),v=0,mt=new Uint8Array(o.buffer);for(let q=0;q<a;q++){let V=q<u?g:b;x[q]=mt.slice(M,M+V),m[q]=S.encode(x[q]),M+=V,v=Math.max(v,V)}let L=new Uint8Array(n),rt=0,N,T;for(N=0;N<v;N++)for(T=0;T<a;T++)N<x[T].length&&(L[rt++]=x[T][N]);for(N=0;N<w;N++)for(T=0;T<a;T++)L[rt++]=m[T][N];return L}function ko(o,t,e,n){let r;if(Array.isArray(o))r=Lt.fromArray(o);else if(typeof o=="string"){let f=t;if(!f){let g=Lt.rawSplit(o);f=ft.getBestVersionForData(g,e)}r=Lt.fromString(o,f||40)}else throw new Error("Invalid data");let i=ft.getBestVersionForData(r,e);if(!i)throw new Error("The amount of data is too big to be stored in a QR Code");if(!t)t=i;else if(t<i)throw new Error(`
4593The chosen QR Code version cannot contain this amount of data.
4594Minimum version required to store current data is: `+i+`.
4595`);let a=Uo(t,e,r),s=gt.getSymbolSize(t),u=new Bo(s);return Po(u,t),Lo(u),Ro(u,t),Rt(u,e,0),t>=7&&qo(u,t),_o(u,a),isNaN(n)&&(n=qt.getBestMask(u,Rt.bind(null,u,e))),qt.applyMask(n,u),Rt(u,e,n),{modules:u,version:t,errorCorrectionLevel:e,maskPattern:n,segments:r}}qe.create=function(t,e){if(typeof t=="undefined"||t==="")throw new Error("No input text");let n=Pt.M,r,i;return typeof e!="undefined"&&(n=Pt.from(e.errorCorrectionLevel,Pt.M),r=ft.from(e.version),i=qt.from(e.maskPattern),e.toSJISFunc&&gt.setToSJISFunction(e.toSJISFunc)),ko(t,r,n,i)}});var Ut=E(H=>{function Ue(o){if(typeof o=="number"&&(o=o.toString()),typeof o!="string")throw new Error("Color should be defined as hex string");let t=o.slice().replace("#","").split("");if(t.length<3||t.length===5||t.length>8)throw new Error("Invalid hex color: "+o);(t.length===3||t.length===4)&&(t=Array.prototype.concat.apply([],t.map(function(n){return[n,n]}))),t.length===6&&t.push("F","F");let e=parseInt(t.join(""),16);return{r:e>>24&255,g:e>>16&255,b:e>>8&255,a:e&255,hex:"#"+t.slice(0,6).join("")}}H.getOptions=function(t){t||(t={}),t.color||(t.color={});let e=typeof t.margin=="undefined"||t.margin===null||t.margin<0?4:t.margin,n=t.width&&t.width>=21?t.width:void 0,r=t.scale||4;
4595return{width:n,scale:n?4:r,margin:e,color:{dark:Ue(t.color.dark||"#000000ff"),light:Ue(t.color.light||"#ffffffff")},type:t.type,rendererOpts:t.rendererOpts||{}}};H.getScale=function(t,e){return e.width&&e.width>=t+e.margin*2?e.width/(t+e.margin*2):e.scale};H.getImageWidth=function(t,e){let n=H.getScale(t,e);return Math.floor((t+e.margin*2)*n)};H.qrToImageData=function(t,e,n){let r=e.modules.size,i=e.modules.data,a=H.getScale(r,n),s=Math.floor((r+n.margin*2)*a),u=n.margin*a,f=[n.color.light,n.color.dark];for(let g=0;g<s;g++)for(let b=0;b<s;b++){let w=(g*s+b)*4,S=n.color.light;if(g>=u&&b>=u&&g<s-u&&b<s-u){let M=Math.floor((g-u)/a),x=Math.floor((b-u)/a);S=f[i[M*r+x]?1:0]}t[w++]=S.r,t[w++]=S.g,t[w++]=S.b,t[w]=S.a}}});var De=E(pt=>{var Dt=Ut();function vo(o,t,e){o.clearRect(0,0,t.width,t.height),t.style||(t.style={}),t.height=e,t.width=e,t.style.height=e+"px",t.style.width=e+"px"}function zo(){try{return document.createElement("canvas")}catch{throw new Error("You need to specify a canvas element")}}pt.render=function(t,e,n){let r=n,i=e;typeof r=="undefined"&&(!e||!e.getContext)&&(r=e,e=void 0),e||(i=zo()),r=Dt.getOptions(r);let a=Dt.getImageWidth(t.modules.size,r),s=i.getContext("2d"),u=s.createImageData(a,a);return Dt.qrToImageData(u.data,t,r),vo(s,i,a),s.putImageData(u,0,0),i};pt.renderToDataURL=function(t,e,n){let r=n;typeof r=="undefined"&&(!e||!e.getContext)&&(r=e,e=void 0),r||(r={});let i=pt.render(t,e,r),a=r.type||"image/png",s=r.rendererOpts||{};return i.toDataURL(a,s.quality)}});var ze=E(ve=>{var Fo=Ut();function ke(o,t){let e=o.a/255,n=t+'="'+o.hex+'"';return e<1?n+" "+t+'-opacity="'+e.toFixed(2).slice(1)+'"':n}function kt(o,t,e){let n=o+t;return typeof e!="undefined"&&(n+=" "+e),n}function Oo(o,t,e){let n="",r=0,i=!1,a=0;for(let s=0;s<o.length;s++){let u=Math.floor(s%t),f=Math.floor(s/t);!u&&!i&&(i=!0),o[s]?(a++,s>0&&u>0&&o[s-1]||(n+=i?kt("M",u+e,.5+f+e):kt("m",r,0),r=0,i=!1),u+1<t&&o[s+1]||(n+=kt("h",a),a=0)):r++}return n}ve.render=function(t,e,n){let r=Fo.getOptions(e),i=t.modules.size,a=t.modules.data,s=i+r.margin*2,u=r.color.light.a?"<path "+ke(r.color.light,"fill")+' d="M0 0h'+s+"v"+s+'H0z"/>':"",f="<path "+ke(r.color.dark,"stroke")+' d="'+Oo(a,i,r.margin)+'"/>',g='viewBox="0 0 '+s+" "+s+'"',w='<svg xmlns="http://www.w3.org/2000/svg" '+(r.width?'width="'+r.width+'" height="'+r.width+'" ':"")+g+' shape-rendering="crispEdges">'+u+f+`</svg>
4596`;return typeof n=="function"&&n(null,w),w}});var Oe=E(nt=>{var Ho=Vt(),vt=_e(),Fe=De(),Vo=ze();function zt(o,t,e,n,r){let i=[].slice.call(arguments,1),a=i.length,s=typeof i[a-1]=="function";if(!s&&!Ho())throw new Error("Callback required as last argument");if(s){if(a<2)throw new Error("Too few arguments provided");a===2?(r=e,e=t,t=n=void 0):a===3&&(t.getContext&&typeof r=="undefined"?(r=n,n=void 0):(r=n,n=e,e=t,t=void 0))}else{if(a<1)throw new Error("Too few arguments provided");return a===1?(e=t,t=n=void 0):a===2&&!t.getContext&&(n=e,e=t,t=void 0),new Promise(function(u,f){try{let g=vt.create(e,n);u(o(g,t,n))}catch(g){f(g)}})}try{let u=vt.create(e,n);r(null,o(u,t,n))}catch(u){r(u)}}nt.create=vt.create;nt.toCanvas=zt.bind(null,Fe.render);nt.toDataURL=zt.bind(null,Fe.renderToDataURL);nt.toString=zt.bind(null,function(o,t,e){return Vo.render(o,e)})});var He=je(Oe(),1);(()=>{if(window.__GOOOOD_HOME_SHARE__)return;window.__GOOOOD_HOME_SHARE__=!0,window.__GOOOOD_HOME_SHARE_TOUCH__=!0;let o=0,t=null,e=0,n=()=>{if(document.getElementById("gooood-share-runtime-layer"))return;let l=document.createElement("style");l.id="gooood-share-runtime-layer",l.textContent=`@media (max-width: 767px) {
4597  .v10-candidate-header .site-header,
4598  .site-header[data-v10-fragment="header"] { z-index: 10030 !important; overflow: visible !important; }
4599  .v10-candidate-header .header-row,
4600  .site-header[data-v10-fragment="header"] .header-row,
4601  .v10-candidate-header .header-actions,
4602  .site-header[data-v10-fragment="header"] .header-actions { overflow: visible !important; }
4603  .v10-candidate-header .header-actions > [data-gooood-page-share],
4604  .site-header[data-v10-fragment="header"] .header-actions > [data-gooood-page-share],
4605  .header-actions > [data-gooood-page-share] { display: none !important; }
4606  .mobile-share,
4607  .user-field > .share-action { display: none !important; }
4608  .header-actions > .gooood-auth-slot { display: none !important; }
4609  .v10-candidate-header .header-actions > .header-search,
4610  .site-header[data-v10-fragment="header"] .header-actions > .header-search,
4611  .header-actions > .header-search { display: inline-flex !important; }
4612  .header-actions > .header-search .header-search-toggle {
4613    align-items: center !important;
4614    background: #fff !important;
4615    color: #333 !important;
4616    display: inline-flex !important;
4617    font-size: 13px !important;
4618    gap: 5px !important;
4619    height: 60px !important;
4620    justify-content: center !important;
4621    min-height: 60px !important;
4622    width: 76px !important;
4623  }
4624  .header-actions > .header-search .header-search-icon,
4625  .user-field > .search-action .header-search-icon {
4626    height: 15px !important;
4627    width: 15px !important;
4628  }
4629  .header-actions > .header-search .header-search-icon::after,
4630  .user-field > .search-action .header-search-icon::after {
4631    bottom: -3px !important;
4632    right: -5px !important;
4633    width: 7px !important;
4634  }
4635  .user-field {
4636    background: #fff !important;
4637    display: flex !important;
4638    height: 60px !important;
4639    position: fixed !important;
4640    right: 0 !important;
4641    top: 0 !important;
4642    width: 76px !important;
4643    z-index: 2000 !important;
4644  }
4645  .user-field > li:not(.search-action) { display: none !important; }
4646  .user-field > .search-action {
4647    display: flex !important;
4648    height: 60px !important;
4649    width: 76px !important;
4650  }
4651  .user-field > .search-action button {
4652    align-items: center !important;
4653    display: inline-flex !important;
4654    flex-direction: row-reverse !important;
4655    font-size: 13px !important;
4656    gap: 5px !important;
4657    height: 60px !important;
4658    justify-content: center !important;
4659    padding: 0 !important;
4660    width: 76px !important;
4661  }
4662  .mobile-menu-item > a,
4663  .mobile-menu-parent,
4664  .mobile-menu-tools a,
4665  .mobile-user-links button { font-size: 16px !important; }
4666  .mobile-submenu a,
4667  .dropdown-menu a { font-size: 14px !important; line-height: 42px !important; padding-left: 46px !important; }
4668  [data-gooood-page-share].is-open .action-dropdown,
4669  [data-gooood-page-share] .action-dropdown { position: fixed !important; right: 0 !important; top: 60px !important; z-index: 10047 !important; pointer-events: auto !important; }
4670  [data-gooood-page-share].is-open .action-dropdown { display: block !important; opacity: 1 !important; visibility: visible !important; transform: translateY(0) !important; }
4671  [data-gooood-share="wechat"],
4672  [data-gooood-share-legacy-wechat],
4673  .share-icon.wechat,
4674  .wechat-share-wrap,
4675  .wechat-control { display: none !important; }
4676}
4677/* step-share-g3-header-search-final */
4678@media (max-width: 991px) {
4679  .v10-candidate-header .header-actions > [data-gooood-page-share="1"],
4680  .site-header[data-v10-fragment="header"] .header-actions > [data-gooood-page-share="1"],
4681  [data-v10-fragment="header"] .header-actions > [data-gooood-page-share="1"] { display: none !important; }
4682  .v10-candidate-header .header-actions > .header-search,
4683  .site-header[data-v10-fragment="header"] .header-actions > .header-search,
4684  [data-v10-fragment="header"] .header-actions > .header-search { display: inline-flex !important; }
4685}`,document.head.appendChild(l)},r=()=>document.documentElement.lang==="en"?"en":"zh",i=()=>{let l=r()==="en"?"Search":"\u641C\u7D22";document.querySelectorAll(".user-field > .search-action button, .mobile-search-top").forEach(c=>{c.setAttribute("aria-label",l),c.querySelectorAll("span:not(.header-search-icon)").forEach(d=>{d.textContent=l})})},a=()=>{var l;return((l=document.querySelector('link[rel="canonical"]'))==null?void 0:l.href)||`https://www.gooood.cn${location.pathname==="/"?"/":location.pathname}`},s=()=>window.matchMedia("(max-width: 767px)").matches,u=l=>{try{let c=new URL(l,location.href);return(c.hostname==="localhost"||c.hostname==="127.0.0.1")&&(c.hostname="www.gooood.cn",c.port=""),c.protocol="https:",c.hash="",c.href}catch{return a()}},f=l=>{var y;let c=l.closest(".article"),d=c==null?void 0:c.querySelector(".article-text h3 a"),h=c==null?void 0:c.querySelector(".cover img");return{url:u((d==null?void 0:d.href)||a()),title:(d==null?void 0:d.dataset[r()])||(d==null?void 0:d.dataset.zh)||((y=d==null?void 0:d.textContent)==null?void 0:y.trim())||document.title,image:(h==null?void 0:h.currentSrc)||(h==null?void 0:h.src)||""}},g=()=>{var l,c;return{url:a(),title:((l=document.querySelector('meta[property="og:title"]'))==null?void 0:l.content)||document.title,image:((c=document.querySelector('meta[property="og:image"]'))==null?void 0:c.content)||""}},b=l=>l.closest(".article")?f(l):g(),w=(l,c)=>{let d=encodeURIComponent(c.url),h=encodeURIComponent(c.title),y=encodeURIComponent(c.image||"");return{weibo:`https://service.weibo.com/share/share.php?url=${d}&title=${h}${c.image?`&pic=${y}`:""}`,twitter:`https://twitter.com/intent/tweet?url=${d}&text=${h}`,facebook:`https://www.facebook.com/sharer/sharer.php?u=${d}`,pinterest:`https://www.pinterest.com/pin/create/button/?url=${d}${c.image?`&media=${y}`:""}&description=${h}`}[l]||""},S=document.createElement("div");S.className="gooood-share-toast",S.hidden=!0,S.setAttribute("role","status"),document.body.appendChild(S);let M=(l,c=l)=>{clearTimeout(o),S.textContent=r()==="en"?c:l,S.hidden=!1,o=setTimeout(()=>{S.hidden=!0},2600)},x=async l=>{var B;let c=!1;try{if(!((B=navigator.clipboard)!=null&&B.writeText))throw new Error("clipboard unavailable");await navigator.clipboard.writeText(l),c=!0}catch{let I=document.createElement("textarea");I.value=l,I.setAttribute("readonly",""),I.style.cssText="position:fixed;top:0;left:0;width:1px;height:1px;opacity:0;z-index:-1",document.body.appendChild(I),I.focus(),I.select(),I.setSelectionRange(0,l.length);try{c=typeof document.execCommand=="function"&&document.execCommand("copy")}catch{c=!1}I.remove()}
4685if(c){M("\u94FE\u63A5\u5DF2\u590D\u5236","Link copied");return}let d=r(),h=m.querySelector(".gooood-share-manual-copy"),y=m.querySelector("canvas");m.querySelector("#gooood-share-title").textContent=d==="en"?"Copy link":"\u590D\u5236\u94FE\u63A5",m.querySelector(".gooood-share-qr-title").textContent=d==="en"?"Select and copy the link below.":"\u8BF7\u9009\u4E2D\u5E76\u590D\u5236\u4E0B\u65B9\u6B63\u5F0F\u94FE\u63A5",y.hidden=!0,h.hidden=!1,h.value=l,m.dataset.shareUrl=l,m.hidden=!1,document.body.classList.add("gooood-share-open"),setTimeout(()=>{h.focus(),h.select()},0),M("\u6D4F\u89C8\u5668\u9650\u5236\u81EA\u52A8\u590D\u5236\uFF0C\u8BF7\u624B\u52A8\u590D\u5236","Automatic copy is blocked. Please copy manually.")},m=document.createElement("div");m.className="gooood-share-modal",m.hidden=!0,m.innerHTML='<div class="gooood-share-dialog" role="dialog" aria-modal="true" aria-labelledby="gooood-share-title"><button class="gooood-share-close" type="button" aria-label="\u5173\u95ED\u5206\u4EAB">\xD7</button><h2 id="gooood-share-title" data-zh="\u5FAE\u4FE1\u626B\u7801\u5206\u4EAB" data-en="Share on WeChat">\u5FAE\u4FE1\u626B\u7801\u5206\u4EAB</h2><canvas width="240" height="240"></canvas><p class="gooood-share-qr-title"></p><input class="gooood-share-manual-copy" type="text" readonly hidden aria-label="\u6B63\u5F0F\u5206\u4EAB\u94FE\u63A5"><button class="gooood-share-copy" type="button" data-zh="\u590D\u5236\u94FE\u63A5" data-en="Copy link">\u590D\u5236\u94FE\u63A5</button></div>',document.body.appendChild(m);let v=()=>{m.hidden=!0,document.body.classList.remove("gooood-share-open")},mt=async l=>{let c=r();m.querySelectorAll("[data-zh][data-en]").forEach(d=>{d.textContent=d.dataset[c]||d.dataset.zh}),m.querySelector(".gooood-share-qr-title").textContent=l.title,m.dataset.shareUrl=l.url,m.querySelector("canvas").hidden=!1,m.querySelector(".gooood-share-manual-copy").hidden=!0,m.hidden=!1,document.body.classList.add("gooood-share-open");try{await He.default.toCanvas(m.querySelector("canvas"),l.url,{width:240,margin:1,errorCorrectionLevel:"M"})}catch{let h=m.querySelector("canvas"),y=m.querySelector(".gooood-share-manual-copy");h.hidden=!0,y.hidden=!1,y.value=l.url,M("\u4E8C\u7EF4\u7801\u751F\u6210\u5931\u8D25\uFF0C\u8BF7\u4F7F\u7528\u590D\u5236\u94FE\u63A5","QR code failed. Please copy the link.")}},L=(l=null)=>{document.querySelectorAll(".share-action.is-open, [data-gooood-page-share].is-open").forEach(c=>{var d;c!==l&&(c.classList.remove("is-open"),(d=c.querySelector("[data-gooood-share-toggle], :scope > a"))==null||d.setAttribute("aria-expanded","false"))}),l||(t=null)},rt=l=>{let c=b(l);l.querySelectorAll("[data-gooood-share]").forEach(d=>{let h=d.dataset.goooodShare,y=w(h,c);d.href=y||"#share",y?(d.target="_blank",d.rel="noopener noreferrer"):(d.removeAttribute("target"),d.removeAttribute("rel"))}),document.querySelectorAll("[data-gooood-page-share] [data-gooood-share]").forEach(d=>{d.href="#share",d.setAttribute("role","button"),d.removeAttribute("target"),d.removeAttribute("rel")})},N=()=>{document.querySelectorAll(".share-action").forEach(l=>{let c=l.querySelector("button");c&&(c.dataset.goooodShareToggle="1",c.setAttribute("aria-haspopup","true"),c.setAttribute("aria-expanded","false")),l.querySelectorAll(".share-icon").forEach(d=>{let h=["wechat","weibo","twitter","facebook","pinterest","copy-link"].find(y=>d.classList.contains(y));h&&(d.dataset.goooodShare=h==="copy-link"?"copy":h),d.href="#share",d.setAttribute("role","button")})}),document.querySelectorAll("[data-gooood-page-share]").forEach(l=>{let c=l.querySelector(":scope > a, :scope > button");c&&(c.dataset.goooodShareToggle="1",c.setAttribute("aria-haspopup","true"),c.setAttribute("aria-expanded","false"))}),document.querySelectorAll(".share-menu").forEach(l=>{l.querySelectorAll("button").forEach(c=>{var h;let d=((h=c.textContent)==null?void 0:h.trim())||"";d==="\u5FAE\u4FE1"?c.dataset.goooodShareLegacyWechat="1":/复制|Copy/i.test(d)&&(c.dataset.goooodShareCopy="1")})})};m.querySelector(".gooood-share-close").addEventListener("click",v),m.querySelector(".gooood-share-copy").addEventListener("click",()=>x(m.dataset.shareUrl||a())),m.addEventListener("click",l=>{l.target===m&&v()}),document.addEventListener("keydown",l=>{l.key==="Escape"&&(m.hidden||v(),L())});let T=async l=>{let c=b(l),d=l.dataset.goooodShare;if(L(),d==="wechat"&&s())return x(c.url);if(d==="wechat")return mt(c);if(d==="copy")return x(c.url);
4685let h=w(d,c);h&&window.open(h,"_blank","noopener,noreferrer,width=760,height=640")},q=l=>{var h;if(!s())return;let c=l.target,d=(h=c==null?void 0:c.closest)==null?void 0:h.call(c,'[data-gooood-share="copy"], .copy-link, [data-gooood-share-copy]');d&&(l.preventDefault(),l.stopPropagation(),typeof l.stopImmediatePropagation=="function"&&l.stopImmediatePropagation(),L(),x(b(d).url))},V=l=>{var y,B;if(!t)return null;let c=((y=l.changedTouches)==null?void 0:y[0])||((B=l.touches)==null?void 0:B[0]);if(!c)return null;let d=c.clientX,h=c.clientY;return Array.from(t.querySelectorAll("[data-gooood-share]")).find(K=>{let I=K.getBoundingClientRect();return d>=I.left&&d<=I.right&&h>=I.top&&h<=I.bottom})||null},Ft=async(l,c=!1)=>{let d=Date.now();if(c){if(d-e<250)return;e=d}else if(d-e<450)return;let h=l.target.closest("[data-gooood-share]");if(h)return l.preventDefault(),l.stopPropagation(),T(h);let y=l.target.closest("[data-gooood-share-toggle]");if(y){l.preventDefault(),l.stopPropagation();let B=y.closest(".share-action, [data-gooood-page-share]"),K=!B.classList.contains("is-open");rt(B),L(B),B.classList.toggle("is-open",K),y.setAttribute("aria-expanded",String(K)),t=K?B:null;return}t&&!t.contains(l.target)&&L()};document.addEventListener("click",q,!0),document.addEventListener("click",l=>{Ft(l)}),document.addEventListener("touchstart",l=>{var y;let c=l.target,d=((y=c==null?void 0:c.closest)==null?void 0:y.call(c,"[data-gooood-share]"))||V(l);if(!d)return;l.cancelable&&l.preventDefault(),l.stopPropagation();let h=Date.now();h-e<250||(e=h,T(d))},{capture:!0,passive:!1}),document.addEventListener("touchend",l=>{var h,y;let c=l.target,d=((h=c==null?void 0:c.closest)==null?void 0:h.call(c,"[data-gooood-share]"))||V(l);if(d){l.cancelable&&l.preventDefault(),l.stopPropagation();let B=Date.now();if(B-e<250)return;e=B,T(d);return}(y=c==null?void 0:c.closest)!=null&&y.call(c,"[data-gooood-share-toggle]")&&(l.cancelable&&l.preventDefault(),Ft(l,!1))},{capture:!0,passive:!1}),n(),N(),i(),new MutationObserver(()=>{N(),i()}).observe(document.body,{childList:!0,subtree:!0})})();})();
4686</script>
4686
4687</body>
4688</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.