motionsites中文站 / Global Talent
Global Talent
aadmin2026-09-06 发布Site模板0 阅读

Global Talent

类型:Site模板 · 分类:未分类 · 收录:2026-09-06 00:58:30 · 源码:会员可见

[hidecontent type="vip1"]
Build a single-page, production-quality marketing landing page called "Atlas — Your compliant global workspace".

Deliver exactly three files: `index.html`, `css/style.css`, `js/script.js`. No build step, no framework, no external JS libraries, no CSS frameworks. Vanilla HTML/CSS/JS only. All photography is remote (CloudFront URLs below); all icons are local SVG files you author from the sources given.

╔═══════════════════════════════════════════════════════════════╗
║ 0. CRITICAL FAILURE MODES — READ BEFORE WRITING ANY CSS       ║
║ Three mistakes will render sections 2 and 3 completely blank.  ║
║ Section 1 will still look perfect, which hides the bug.        ║
╚═══════════════════════════════════════════════════════════════╝

▶ TRAP 1 — `--k` MUST RESOLVE TO A LENGTH (px), NEVER A UNITLESS NUMBER.
  Every dimension in sections 2 and 3 is written `calc(<number> * var(--k))`.
  In CSS, number × length = length ✅, but number × number = number ❌, and a bare
  number is invalid for `height`/`width`, so the whole declaration is DISCARDED.

  CORRECT (divide a length by a UNITLESS number → length):
      --design-w: 1685;                                   /* unitless! no px */
      --page-scale: calc((100vw - 2 * var(--gutter)) / var(--design-w));   /* → px */
  WRONG (divides by a length → unitless ratio → every calc downstream dies):
      --page-scale: calc((100vw - 40px) / 1685px);        /* ✗ NEVER */
      --page-scale: calc(100vw / 1685);                   /* ✗ missing gutter */

  Every redefinition of --k in every media query must ALSO stay length-valued.
  In clamp()/min() this means every branch carries a unit:
      --k: clamp(0.72px, calc((100vw - 2 * var(--tablet-inset)) / 1080), 1px);  ✅
      --k: clamp(0.72, calc(...), 1);                                            ✗
  (Firefox is strictest here; a unitless branch poisons the whole clamp.)

  SELF-CHECK: after writing the CSS, confirm in devtools that the computed value of
  `--k` on `.features` reads like "0.83px" — not "0.83". If it has no unit, stop and
  fix the token before continuing.

▶ TRAP 2 — `.feature__media` AND `.showcase__figure` CONTAIN ONLY ABSOLUTELY
  POSITIONED CHILDREN, SO THEY HAVE NO INTRINSIC HEIGHT.
  If their `height` is missing or invalid they collapse to 0px and the card artwork,
  chips, mini-cards, benefit card and mini-finder all vanish — the section renders as
  bare headings on white, or as nothing at all.
  MANDATORY BELT-AND-BRACES: give each one an `aspect-ratio` fallback IN ADDITION to
  its height, so a zero height is impossible even if a calc fails:
      .feature__media  { height: calc(577.97 * var(--k)); aspect-ratio: 1060.28 / 577.97;
                         min-height: 320px; }
      .showcase__figure{ aspect-ratio: 1060.85 / 675.47; min-height: 260px; }
  Never let either box end up `height: auto` with no aspect-ratio.

▶ TRAP 3 — THE SCROLL REVEAL MUST FAIL OPEN, NEVER FAIL CLOSED.
  All of sections 2 and 3 start at `opacity: 0` — but ONLY while `<html>` carries the
  class `scroll-reveal-ready`. That class is added by JS *after* the IntersectionObserver
  is successfully constructed. If the observer never fires, or the class is added by a
  hardcoded stylesheet rule, or you put the hidden state on the bare selector, both
  sections stay invisible forever.
  RULES, all mandatory:
    a) NEVER write `.feature__media { opacity: 0 }` unqualified. The hidden state must
       always be prefixed `html.scroll-reveal-ready .feature:not(.is-revealed) …`.
    b) `scroll-reveal-ready` is added by JS ONLY, and only after `new IntersectionObserver(…)`
       has returned successfully and `.observe()` has been called on every target.
    c) Bail out of the whole controller (adding nothing) if `IntersectionObserver` is
       missing or reduced motion is on.
    d) Add an unconditional safety net inside the controller: a 3000ms timer that reveals
       everything and removes `scroll-reveal-ready` no matter what the observer did.
       Clear it once all targets have revealed normally.
    e) The default, no-JS, no-class state of sections 2 and 3 is FULLY VISIBLE.

▶ FINAL ACCEPTANCE TEST (run all four before declaring done):
   1. Load the page — all three sections visible, no blank regions.
   2. Disable JavaScript entirely and reload — all three sections still fully visible
      and readable (only the animations and the finder demo are gone).
   3. In devtools confirm `.features` computed `--k` ends in "px", and that
      `.feature__media` and `.showcase__figure` both report a non-zero height.
   4. Check widths 360 / 700 / 900 / 1440 / 2560 — zero horizontal scrollbar at each.

═══════════════════════════════════════════════════════════════
1. CORE ARCHITECTURE — THE SCALE SYSTEM
═══════════════════════════════════════════════════════════════
The design was authored in Figma on a 1685px-wide page. Do NOT reflow the desktop layout
with ordinary responsive techniques. Instead EVERY desktop length is `calc(<figma-number>
* var(--k))`, where --k is the ratio between the space the page actually has and that
1685px canvas. At exactly 1685px --k === 1px and the layout is pixel-identical to Figma;
at any other width the whole composition scales proportionally instead of re-flowing.

Two scales, because the hero and the sections below it are constrained differently:
  --page-scale : respects viewport WIDTH only. Drives features + showcase.
  --hero-scale : additionally respects viewport HEIGHT so the hero fits one screen.
                 Equals --page-scale until the viewport is too short, then height wins.

:root tokens (exact — note which are unitless and which carry px):
  --gutter: 20px;              /* LENGTH */
  --design-w: 1685;            /* UNITLESS — see Trap 1 */
  --section-inset: 10;         /* unitless */
  --section-gap: 150;          /* unitless */
  --media-h: 737;              /* unitless */
  --hero-chrome: 336;          /* unitless — 11 above + 71 below + 180 text + 74 closing */
  --media-min: 675;            /* unitless — shortest media clearing nav + panel + CTA */
  --viewport-h: 100vh;
  --page-scale: calc((100vw - 2 * var(--gutter)) / var(--design-w));
  --hero-scale: min(var(--page-scale),
                    calc(var(--viewport-h) / (var(--media-min) + var(--hero-chrome))));
  --k: var(--page-scale);

Two @supports refinements:
  @supports (height: 1svh) { :root { --viewport-h: 100svh; } }
  @supports (width: 1cqw) {
    body { container-type: inline-size; }
    .page { --page-scale: calc((100cqw - 2 * var(--gutter)) / var(--design-w));
            --hero-scale: min(var(--page-scale),
                          calc(var(--viewport-h) / (var(--media-min) + var(--hero-chrome))));
            --k: var(--page-scale); }
  }
  (Container units exclude the scrollbar, so the page measures space it actually has.)

`.hero` overrides `--k: var(--hero-scale)`. Its photograph is `flex: 1 1 auto` and absorbs
leftover height, so width-fill and height-fill never fight.

Palette:  --white:#ffffff  --black:#000000  --ink:#020202 (hero backdrop)
          --placeholder:#d9d9d9 (avatar fallback fill)
          --glass:rgba(0,0,0,0.1)   --glass-soft:rgba(0,0,0,0.08)
Radii (unitless design units, × --k at each use):
          --radius-media:30 --radius-panel:18 --radius-button:14 --radius-pill:12
          --radius-card:38.34
Type:     --font: 'Figtree','Inter','Helvetica Neue',Arial,sans-serif;
          --track-tight:-0.02em;  --track-display:-0.05em;
Motion:   --ease-panel: cubic-bezier(0.42, 0.02, 0.05, 0.97);

═══════════════════════════════════════════════════════════════
2. FONTS
═══════════════════════════════════════════════════════════════
The design specifies TT Hoves (commercial). Use Figtree — the closest metric match.
Load Figtree weights 400 and 500 ONLY, `font-display: swap`, and preload the 500 weight.
Only those two weights are ever used: 400 for body copy, 500 for everything else.
body { font-synthesis: none; -webkit-font-smoothing: antialiased; overflow-x: hidden; }

═══════════════════════════════════════════════════════════════
3. REMOTE IMAGE ASSETS — use these URLs verbatim
═══════════════════════════════════════════════════════════════
HERO VIDEO (10s, silent, loops):
https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260826_125443_3ffe8709-59c1-428c-86c4-8ffa90e4b8d6.mp4
HERO VIDEO POSTER:
https://d2ol7oe51mr4n9.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/b9fe4e1a-0975-4771-98bb-ee87c8482508.png
AVATAR — Ivan K.:
https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260826_130521_b5b53fe3-4384-45c0-9976-04b33f7dcbee.png
AVATAR — Jennifer A.:
https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260826_130521_44261148-84ef-402e-89e6-ce814dfdb002.png
AVATAR — David F.:
https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260826_130521_266e2b6b-299c-4b71-b904-26890402a148.png
AVATAR — fourth (stack only):
https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260826_130521_873837cc-8877-4187-be86-2a60aa2f34ce.png
SUNFLOWER PORTRAIT (feature cards 1 AND 2 — same file, cropped differently):
https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260826_130521_74acdc41-c223-4a2b-9b50-8bf985022b0c.png
SUNFLOWER DUSK (feature card 3):
https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260826_130708_e51acd98-0f33-4aa2-8bc5-0a453a732e97.png
SUNFLOWER CLOUDS (feature card 4):
https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260826_130708_58c53874-8db1-44ec-9073-cc8cf2ecad57.png
OFFICE WINDOW (showcase figure 1):
https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260826_131754_75fc072a-991e-4f75-a2aa-5f8deb71c592.png
OFFICE TEAM (showcase figure 2):
https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260826_130707_5b123fed-335a-492a-bff9-0a48f996226a.png

═══════════════════════════════════════════════════════════════
4. LOCAL SVG ICONS — create these 7 files under assets/svg/
═══════════════════════════════════════════════════════════════
logo-mark.svg (43×43, white circle with a crescent bite — brand mark AND favicon):
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 43 43" width="43" height="43"><path d="M 21.500 0.000 C 33.374 0.000  43.000 9.626  43.000 21.500 C 43.000 33.374  33.374 43.000  21.500 43.000 C 9.626 43.000  0.000 33.374  0.000 21.500 C 0.000 9.626  9.626 0.000  21.500 0.000 Z M 15.246 6.133 C 9.186 8.602  4.914 14.550  4.914 21.497 C 4.914 30.657  12.340 38.083  21.500 38.083 C 28.007 38.083  33.637 34.335  36.354 28.881 C 34.424 29.667  32.314 30.102  30.102 30.102 C 20.942 30.102  13.516 22.676  13.516 13.516 C 13.516 10.863  14.139 8.356  15.246 6.133 Z" fill="#ffffff"/></svg>

search.svg (31×31, white outlined magnifier):
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 31 31" width="31" height="31"><path d="M 26.809 15.199 L 25.309 15.199 C 25.309 20.782  20.782 25.309  15.199 25.309 L 15.199 26.809 L 15.199 28.309 C 22.439 28.309  28.309 22.439  28.309 15.199 L 26.809 15.199 Z M 15.199 26.809 L 15.199 25.309 C 9.615 25.309  5.088 20.782  5.088 15.199 L 3.588 15.199 L 2.088 15.199 C 2.088 22.439  7.958 28.309  15.199 28.309 L 15.199 26.809 Z M 3.588 15.199 L 5.088 15.199 C 5.088 9.615  9.615 5.088  15.199 5.088 L 15.199 3.588 L 15.199 2.088 C 7.958 2.088  2.088 7.958  2.088 15.199 L 3.588 15.199 Z M 15.199 3.588 L 15.199 5.088 C 20.782 5.088  25.309 9.615  25.309 15.199 L 26.809 15.199 L 28.309 15.199 C 28.309 7.958  22.439 2.088  15.199 2.088 L 15.199 3.588 Z" fill="#ffffff"/><path d="M 24.333 22.815 C 23.746 22.230  22.797 22.231  22.212 22.817 C 21.627 23.404  21.628 24.354  22.214 24.939 L 23.274 23.877 L 24.333 22.815 Z M 26.766 29.479 C 27.353 30.064  28.303 30.062  28.888 29.476 C 29.473 28.889  29.471 27.940  28.885 27.355 L 27.826 28.417 L 26.766 29.479 Z M 23.274 23.877 L 22.214 24.939 L 26.766 29.479 L 27.826 28.417 L 28.885 27.355 L 24.333 22.815 L 23.274 23.877 Z" fill="#ffffff"/></svg>

globe.svg (31×31, WHITE latitude/longitude wireframe globe):
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 31 31" width="31" height="31"><path d="M 15.220 4.844 C 9.334 4.844  4.564 9.614  4.564 15.500 C 4.564 21.386  9.334 26.156  15.220 26.156 C 21.106 26.156  25.876 21.386  25.876 15.500 C 25.876 9.614  21.106 4.844  15.220 4.844 Z M 2.626 15.500 C 2.626 8.544  8.264 2.906  15.220 2.906 C 22.176 2.906  27.814 8.544  27.814 15.500 C 27.814 22.456  22.176 28.094  15.220 28.094 C 8.264 28.094  2.626 22.456  2.626 15.500 Z" fill="#ffffff" fill-rule="evenodd"/><path d="M 17.219 3.324 C 17.672 3.040  18.270 3.177  18.554 3.631 C 19.612 5.319  20.377 7.853  20.773 10.759 C 20.986 12.235  21.098 13.828  21.098 15.491 C 21.098 17.152  20.986 18.758  20.773 20.234 C 20.377 23.140  19.612 25.674  18.554 27.363 C 18.270 27.816  17.672 27.953  17.219 27.669 C 16.766 27.385  16.628 26.787  16.912 26.334 C 17.765 24.974  18.475 22.744  18.853 19.969 L 18.854 19.961 C 19.053 18.583  19.160 17.069  19.160 15.491 C 19.160 13.913  19.054 12.411  18.855 11.032 L 18.853 11.025 C 18.475 8.249  17.765 6.019  16.912 4.659 C 16.628 4.206  16.766 3.608  17.219 3.324 Z" fill="#ffffff" fill-rule="evenodd"/><path d="M 13.230 3.324 C 13.683 3.608  13.820 4.206  13.536 4.659 C 12.683 6.022  11.960 8.253  11.582 11.025 L 11.581 11.032 C 11.383 12.410  11.277 13.912  11.277 15.491 C 11.277 17.069  11.383 18.584  11.581 19.961 L 11.583 19.969 C 11.960 22.740  12.683 24.972  13.536 26.334 C 13.820 26.787  13.683 27.385  13.230 27.669 C 12.776 27.953  12.178 27.816  11.894 27.363 C 10.838 25.677  10.060 23.144  9.663 20.234 C 9.450 18.758  9.340 17.152  9.340 15.491 C 9.340 13.829  9.450 12.236  9.663 10.759 C 10.060 7.849  10.838 5.317  11.894 3.631 C 12.178 3.177  12.776 3.040  13.230 3.324 Z" fill="#ffffff" fill-rule="evenodd"/><path d="M 15.218 11.549 C 13.640 11.549  12.138 11.656  10.759 11.855 L 10.752 11.856 C 7.981 12.233  5.747 12.955  4.382 13.800 C 3.927 14.081  3.330 13.941  3.049 13.486 C 2.767 13.031  2.907 12.434  3.362 12.152 C 5.046 11.110  7.576 10.333  10.486 9.937 C 11.962 9.724  13.556 9.612  15.218 9.612 C 16.880 9.612  18.473 9.724  19.949 9.937 C 22.859 10.333  25.375 11.098  27.070 12.138 C 27.526 12.418  27.669 13.014  27.389 13.470 C 27.109 13.926  26.512 14.069  26.056 13.789 C 24.680 12.944  22.457 12.234  19.684 11.856 L 19.676 11.855 C 18.297 11.656  16.795 11.549  15.218 11.549 Z" fill="#ffffff" fill-rule="evenodd"/><path d="M 3.052 17.493 C 3.336 17.040  3.934 16.903  4.387 17.187 C 5.748 18.040  7.979 18.763  10.752 19.140 L 10.759 19.141 C 12.137 19.340  13.639 19.446  15.217 19.446 C 16.796 19.446  18.298 19.340  19.676 19.141 L 19.683 19.140 C 22.458 18.762  24.676 18.052  26.047 17.188 C 26.499 16.903  27.097 17.039  27.383 17.491 C 27.668 17.944  27.532 18.542  27.080 18.827 C 25.380 19.898  22.856 20.663  19.949 21.060 C 18.473 21.273  16.879 21.383  15.217 21.383 C 13.556 21.383  11.963 21.273  10.486 21.060 C 7.575 20.663  5.043 19.885  3.358 18.828 C 2.904 18.544  2.767 17.946  3.052 17.493 Z" fill="#ffffff" fill-rule="evenodd"/></svg>

globe-dark.svg — the SAME 5-path latitude/longitude globe, but viewBox/width/height 25×25
with every fill #000000 and all coordinates scaled to the 25-unit box.

arrow-up-right.svg (21.2067×21.2067, black arrow pointing up-right):
<svg xmlns="http://www.w3.org/2000/svg" viewBox="20.8967 20.8967 21.2067 21.2067" width="21.2067" height="21.2067"><path d="M 32.594 37.593 L 39.195 31.287 L 32.594 24.982 L 31.347 26.185 L 35.801 30.439 L 23.805 30.439 L 23.805 32.136 L 35.801 32.136 L 31.347 36.391 L 32.594 37.593 Z" fill="#000000" fill-rule="evenodd"/></svg>

check-badge.svg (25×25, white scalloped rosette badge enclosing a checkmark):
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 25" width="25" height="25"><path d="M 16.233 10.998 L 11.990 15.242 C 11.843 15.389  11.644 15.472  11.437 15.472 C 11.230 15.472  11.031 15.389  10.885 15.242 L 8.826 13.180 C 8.522 12.874  8.522 12.379  8.827 12.074 C 9.133 11.769  9.627 11.771  9.932 12.075 L 11.438 13.584 L 15.128 9.892 C 15.433 9.587  15.928 9.587  16.233 9.892 C 16.538 10.198  16.538 10.692  16.233 10.998 Z M 21.566 10.506 L 20.838 9.778 C 20.506 9.444  20.324 9.001  20.324 8.531 L 20.324 7.489 C 20.324 5.938  19.061 4.677  17.511 4.677 L 16.467 4.677 C 15.996 4.677  15.553 4.494  15.222 4.163 L 14.481 3.424 C 13.380 2.332  11.597 2.337  10.504 3.435 L 9.778 4.163 C 9.443 4.495  9.001 4.678  8.530 4.678 L 7.487 4.678 C 5.955 4.679  4.705 5.912  4.677 7.439 C 4.676 7.456  4.675 7.473  4.675 7.490 L 4.675 8.529 C 4.675 9.000  4.492 9.442  4.160 9.775 L 3.423 10.513 C 3.422 10.516  3.418 10.517  3.416 10.519 C 2.328 11.622  2.337 13.405  3.434 14.491 L 4.162 15.222 C 4.493 15.554  4.677 15.996  4.677 16.466 L 4.677 17.513 C 4.677 19.063  5.937 20.325  7.487 20.325 L 8.528 20.325 C 9.000 20.326  9.442 20.508  9.774 20.838 L 10.516 21.579 C 11.046 22.105  11.748 22.394  12.494 22.394 L 12.507 22.394 C 13.258 22.391  13.962 22.096  14.489 21.565 L 15.219 20.836 C 15.548 20.509  16.002 20.322  16.465 20.322 L 17.513 20.322 C 19.060 20.322  20.322 19.062  20.325 17.513 L 20.325 16.468 C 20.325 15.999  20.507 15.556  20.837 15.224 L 21.578 14.483 C 22.672 13.383  22.665 11.599  21.566 10.506 Z" fill="#ffffff" fill-rule="evenodd"/></svg>

connector.svg (94×169, white hairline — a vertical spine with three horizontal branches
at top/middle/bottom, like an org-chart bracket):
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -0.5 94 169" width="94" height="169" fill="none"><path d="M 47.000 0.000 L 47.000 -0.500 L 46.500 -0.500 L 46.500 0.000 L 47.000 0.000 Z M 47.000 168.000 L 46.500 168.000 L 46.500 168.500 L 47.000 168.500 L 47.000 168.000 Z M 0.000 84.500 L 0.000 85.000 L 47.000 85.000 L 47.000 84.500 L 47.000 84.000 L 0.000 84.000 L 0.000 84.500 Z M 47.000 84.500 L 47.000 85.000 L 94.000 85.000 L 94.000 84.500 L 94.000 84.000 L 47.000 84.000 L 47.000 84.500 Z M 47.000 84.500 L 47.500 84.500 L 47.500 0.000 L 47.000 0.000 L 46.500 0.000 L 46.500 84.500 L 47.000 84.500 Z M 47.000 0.000 L 47.000 0.500 L 94.000 0.500 L 94.000 0.000 L 94.000 -0.500 L 47.000 -0.500 L 47.000 0.000 Z M 47.000 0.000 L 46.500 0.000 L 46.500 168.000 L 47.000 168.000 L 47.500 168.000 L 47.500 0.000 L 47.000 0.000 Z M 47.000 168.000 L 47.000 168.500 L 94.000 168.500 L 94.000 168.000 L 94.000 167.500 L 47.000 167.500 L 47.000 168.000 Z" fill="#ffffff"/></svg>

═══════════════════════════════════════════════════════════════
5. DOCUMENT HEAD & BOOT SCRIPT
═══════════════════════════════════════════════════════════════
<title>Atlas — Your compliant global workspace</title>
<meta name="description" content="Discover, onboard, and pay compliant remote teams in over 150 countries.">
favicon = assets/svg/logo-mark.svg (type image/svg+xml); preload Figtree 500 woff2.

MANDATORY inline blocking script in <head>, BEFORE the stylesheet link:
  document.documentElement.classList.add('has-js','entrance-pending');
  window.__atlasEntranceFallback = setTimeout(function () {
    document.documentElement.classList.remove('entrance-pending','entrance-playing');
  }, 3500);
This guarantees the hero becomes visible even if the entrance controller never runs.

═══════════════════════════════════════════════════════════════
6. HTML STRUCTURE (exact — reproduce this tree and these class names)
═══════════════════════════════════════════════════════════════
<body> > <main class="page"> containing three <section>s: .hero, .features, .showcase.
`<script src="js/script.js">` at end of body — not deferred, not async.

── SECTION 1: <section class="hero">
  <div class="hero__media">
    <div class="hero__zoom">
      <video class="hero__video" muted loop playsinline preload="metadata"
             poster="[HERO POSTER URL]" aria-hidden="true" tabindex="-1">
        <source src="[HERO VIDEO URL]" type="video/mp4">
      </video>
    </div>
    <div class="hero__scrim"></div>

    <header class="nav">
      <a class="brand" href="#">
        <img class="brand__mark" src="assets/svg/logo-mark.svg" alt="" aria-hidden="true">
        <span class="brand__name">Atlas</span>
      </a>
      <nav class="nav__menu" id="primary-menu" aria-label="Primary">
        <a class="pill nav__link" href="#">Platform</a>
        <a class="pill nav__link" href="#">Use Cases</a>
        <a class="pill nav__link" href="#">Country</a>
        <a class="pill nav__link" href="#">Pricing</a>
        <a class="pill pill--light nav__cta nav__cta--menu" href="#">Request Demo</a>
      </nav>
      <a class="pill pill--light nav__cta" href="#">Request Demo</a>
      <button class="nav__toggle" type="button" aria-controls="primary-menu"
              aria-expanded="false" aria-label="Open navigation menu">
        <span></span><span></span>
      </button>
    </header>

    <div class="finder" id="finder" data-state="results">
      <div class="finder__bar">
        <div class="finder__field">
          <span class="icon-button icon-button--soft" aria-hidden="true">
            <img src="assets/svg/search.svg" alt="">
          </span>
          <input class="finder__input" type="search" id="expert-search"
                 placeholder="Search expert" aria-label="Search expert" autocomplete="off">
          <span class="finder__demo" id="finder-demo" aria-hidden="true">
            <span class="finder__demo-hint" id="demo-hint">Search expert</span>
            <span class="finder__demo-typed" id="demo-typed"></span>
          </span>
        </div>
        <div class="country">
          <button class="country__toggle" type="button" id="country-toggle"
                  aria-haspopup="listbox" aria-expanded="false">
            <img class="country__icon" src="assets/svg/globe.svg" alt="" aria-hidden="true">
            <span class="country__label" id="country-label">Global</span>
          </button>
          <ul class="country__menu" id="country-menu" role="listbox"
              aria-labelledby="country-toggle" hidden>
            <li class="country__option" role="option" tabindex="-1" data-country="Global"  aria-selected="true">Global</li>
            <li class="country__option" role="option" tabindex="-1" data-country="Germany" aria-selected="false">Germany</li>
            <li class="country__option" role="option" tabindex="-1" data-country="Belgium" aria-selected="false">Belgium</li>
          </ul>
        </div>
      </div>

      <div class="finder__roles" id="role-list">
        <button class="pill pill--row role" type="button" aria-pressed="false">UI Designer</button>
        <button class="pill pill--row role" type="button" aria-pressed="false">UX Designer</button>
        <button class="pill pill--row role" type="button" aria-pressed="false">Web Designer</button>
      </div>

      <div class="finder__results">
        3 × <article class="expert" data-country="…"> each:
              <div class="expert__who">[img.avatar]<div class="expert__id">
                <span class="expert__name">…</span><span class="expert__meta">…</span></div></div>
              <div class="expert__terms">
                <span class="expert__rate">…</span><span class="expert__type">…</span></div>
        Rows in order:
          1. Ivan K.     | Germany | "Germany, 5 year exp." | $4,500-$6,000 | Remote
          2. Jennifer A. | Belgium | "Belgium, 4 year exp." | $5,500-$6,500 | In-house
          3. David F.    | Belgium | "Belgium, 4 year exp." | $5,500-$6,000 | In-house
        Then <p class="finder__count">and 50+ expert hired</p>
      </div>
    </div>

    <div class="cta">
      <a class="cta__label" href="#">Get Early Access</a>
      <a class="cta__go" href="#" aria-label="Get Early Access">
        <img src="assets/svg/arrow-up-right.svg" alt="" aria-hidden="true">
      </a>
    </div>
  </div>

  <div class="hero__foot">
    <h1 class="hero__title">Your compliant global workspace</h1>
    <div class="hero__aside">
      <div class="avatar-stack" aria-hidden="true">
        4 × <img class="avatar avatar--ring"> in order: Ivan, David, Jennifer, fourth
      </div>
      <p class="hero__lede">Discover, onboard, and pay compliant remote teams in over 150 countries.</p>
    </div>
  </div>
</section>

── SECTION 2: <section class="features"> — two rows, two cards each
  <div class="features__row features__row--top">
    <article class="feature feature--payroll">
      <div class="feature__media">
        <img class="crop crop--payroll" src="[SUNFLOWER PORTRAIT]" alt="" aria-hidden="true">
        <span class="pill pill--light chip chip--payroll">Global Payroll
          <img class="chip__icon" src="assets/svg/globe-dark.svg" alt="" aria-hidden="true"></span>
        <img class="feature__connector" src="assets/svg/connector.svg" alt="" aria-hidden="true">
        3 × <div class="mini-card mini-card--r1|--r2|--r3">
              <span class="mini-card__who"><img class="avatar avatar--mini" src="[AVATAR]">
                <span class="mini-card__name">NAME</span></span>
              <span class="mini-card__place">PLACE</span></div>
            r1 Ivan K./Germany · r2 Jennifer A./Belgium · r3 David F./Belguim  [sic]
      </div>
      <h3 class="feature__title">Global Payroll Setup</h3>
      <p class="feature__text">Automatic, mult-currency payments made easy</p>  [sic]
    </article>

    <article class="feature feature--onboarding">
      <div class="feature__media">
        <img class="crop crop--onboarding" src="[SUNFLOWER PORTRAIT — same file]" alt="" aria-hidden="true">
        <span class="pill pill--light chip chip--legal">Legal layer</span>
        3 × <span class="pill pill--glass chip chip--labor|--data|--contract">LABEL
              <img class="chip__icon" src="assets/svg/check-badge.svg" alt="" aria-hidden="true"></span>
            labels: "Labor Laws" · "Data Protection" · "Contract"
      </div>
      <h3 class="feature__title">Instant Onboarding</h3>
      <p class="feature__text">Legal-verified templates to hire in 24 hours</p>
    </article>
  </div>

  <div class="features__row features__row--bottom">
    <article class="feature feature--benefits">
      <div class="feature__media">
        <img class="crop crop--cover" src="[SUNFLOWER DUSK]" alt="" aria-hidden="true">
        <div class="benefit-card">
          <div class="benefit-card__person"><img class="avatar" src="[DAVID]" alt="" aria-hidden="true">
            <div class="expert__id"><span class="expert__name">David F.</span>
              <span class="expert__meta">Belgium, 4 year exp.</span></div></div>
          <div class="benefit-card__tags">
            2 × <span class="pill pill--light chip">LABEL
                  <img class="chip__icon" src="assets/svg/globe-dark.svg" alt="" aria-hidden="true"></span>
                labels: "Retirement Benefits" · "Hearth Insurance"  [sic]
          </div>
        </div>
      </div>
      <h3 class="feature__title">Offer competitive benefits</h3>
      <p class="feature__text">Provide pensions and retirement plans. Stand out and attract the best talent. </p>
    </article>

    <article class="feature feature--experts">
      <div class="feature__media">
        <img class="crop crop--cover" src="[SUNFLOWER CLOUDS]" alt="" aria-hidden="true">
        <div class="mini-finder">
          <div class="mini-finder__field">
            <span class="icon-button icon-button--soft" aria-hidden="true">
              <img src="assets/svg/search.svg" alt=""></span>
            <span class="mini-finder__placeholder">Search </span>
          </div>
          <div class="country country--static">
            <img class="country__icon" src="assets/svg/globe.svg" alt="" aria-hidden="true">
            <span class="country__label">Belgium</span></div>
        </div>
      </div>
      <h3 class="feature__title">Access locally-based HR experts</h3>
      <p class="feature__text">Get done-for-you employee lifecycle management</p>
    </article>
  </div>
</section>

── SECTION 3: <section class="showcase">
  <h2 class="showcase__title">Hire anywhere in 24 hours</h2>
  <figure class="showcase__figure">
    <img class="crop crop--cover" src="[OFFICE WINDOW]"
         alt="A team working together in a bright open-plan office"></figure>
  <h2 class="showcase__title showcase__title--second">Experience the competition can’t match</h2>
  <figure class="showcase__figure showcase__figure--second">
    <img class="crop crop--cover" src="[OFFICE TEAM]"
         alt="Colleagues collaborating around a desk in a plant-filled workspace"></figure>
</section>

("can’t" uses a typographic right single quote.)

═══════════════════════════════════════════════════════════════
7. DESKTOP CSS — EXACT VALUES
Notation: every bare number below means `calc(<number> * var(--k))` unless a unit is
shown. Font sizes, gaps, paddings, radii, offsets — all of them. Write the calc() out.
═══════════════════════════════════════════════════════════════
RESET
  *,*::before,*::after { box-sizing: border-box }
  html { text-size-adjust: 100% }
  body { margin:0; background:var(--white); color:var(--black); font-family:var(--font);
         font-weight:400; font-synthesis:none; -webkit-font-smoothing:antialiased;
         overflow-x:hidden }
  img { display:block; max-width:100% }
  [hidden] { display:none !important }
  a { color:inherit; text-decoration:none }
  button,input { font:inherit; color:inherit }
  :focus-visible { outline: calc(2*var(--k)) solid currentColor;
                   outline-offset: calc(2*var(--k)) }
  .page { position:relative; margin-inline:var(--gutter) }

SHARED PRIMITIVES
  .avatar       56×56; border-radius 50%; object-fit cover; background var(--placeholder);
                flex none
  .avatar--ring border calc(3*var(--k)) solid var(--white)
  .pill         inline-flex, centered both axes; height 40; padding 12 / 18; border 0;
                radius --radius-pill; background var(--glass); color white; font-size 16;
                weight 500; line-height 1; letter-spacing --track-tight; nowrap
  .pill--light  background white; color black
  .icon-button  grid place-items center; 63×63; radius --radius-button; flex none
  .icon-button--soft  background var(--glass-soft)
  .icon-button img    31×31
  .crop--cover  width 100%; height 100%; object-fit cover; object-position center

HERO
  .hero        --k: var(--hero-scale); position relative; flex column;
               min-height var(--viewport-h); padding-block 11 / 74
               (min-height not height: on a viewport too short for even the smallest
               usable hero the section grows and the page scrolls rather than clipping)
  .hero__media position relative; flex 1 1 auto; min-height calc(var(--media-min)*var(--k));
               margin-inline calc(var(--section-inset)*var(--page-scale));
               radius --radius-media; overflow hidden; background var(--ink)
  .hero__zoom  absolute inset 0; overflow hidden; transform-origin 50% 42%
               html.continuous-motion .hero__zoom { animation: hero-push 5.2s ease-in-out
                 infinite alternate; will-change: transform }
               @keyframes hero-push { from { transform: scale(1) }
                                      to   { transform: scale(1.238) } }
               The zoom stays DORMANT until the entrance completes (§9).
  .hero__video absolute inset 0; 100%×100%; max-width none; object-fit cover; center
  .hero__scrim absolute inset 0; background var(--ink); opacity .2

NAV
  .nav         absolute; left 26; right 25; top 19; flex row space-between, align center;
               height 43
  .brand       relative 126×43; flex none
  .brand__mark absolute 0,0; 43×43
  .brand__name absolute left 55, top 6; white; font-size 34.08; weight 500;
               line-height .9; letter-spacing --track-display
  .nav__menu   flex; gap 1; width 389; height 40;
               backdrop-filter blur(calc(12.35*var(--k))) + -webkit- prefix
  .nav__link widths by position: 1→96, 2→111, 3→94, 4→85
  .nav__cta    width 140
  .nav__cta--menu, .nav__toggle { display: none }    /* desktop only */
  hover: .nav__link → rgba(0,0,0,.22); .nav__cta → rgba(255,255,255,.86)

TALENT PANEL — four resizable states
  Heights (design units) via [data-state]:
    collapsed    83 = 10+63+10                        search row only
    suggestions 223 = 10+63+10+130+10                 + role list
    results     388 = 10+63+10+295+10                 + result list   [--results-top: 83]
    full        528 = 10+63+10+130+10+295+10          both            [--results-top: 223]
  Visibility: collapsed hides .finder__roles AND .finder__results; suggestions hides
  .finder__results; results hides .finder__roles; full shows both.
  .finder      --finder-h: 388; --results-top: 83;
               --finder-half: calc(var(--finder-h) * var(--k) / 2);
               absolute; left calc(50% + 8*var(--k));
               top: clamp(calc(82*var(--k) + var(--finder-half)),
                          calc(100% * 339 / var(--media-h)),
                          calc(100% - 159*var(--k) - var(--finder-half)));
               width 541; height calc(var(--finder-h)*var(--k));
               radius --radius-panel; background var(--glass);
               backdrop-filter blur(calc(16.85*var(--k))); overflow hidden;
               transform translate(-50%,-50%);
               transition: height var(--finder-dur,600ms) var(--ease-panel),
                           top    var(--finder-dur,600ms) var(--ease-panel);
               (Held by its CENTRE — 8 units right of the media centre line, 46% down —
                so it keeps its place however the photograph is shaped. The clamp stops
                the full panel climbing into the nav or sliding past the CTA.)
  .finder__bar    absolute 10,10; flex space-between align center; 521×63
  .finder__field  relative flex align center; gap 20; 340×63
  .finder__input  width 257; border 0; padding 0; background none; white; font-size 26;
                  weight 500; line-height 1; --track-tight; appearance none
                  ::placeholder white opacity .4; hide ::-webkit-search-cancel-button
  .country        relative; flex none
  .country__toggle, .country--static  flex align center; gap 11; 149×31; padding 0 16;
                  border 0; background none; cursor pointer
  .country__icon  31×31 flex none
  .country__label white; 26 / 500 / 1; --track-tight
  .country__menu  absolute right 0, top 41; z-index 2; margin 0; padding 6;
                  list-style none; width 180; radius --radius-pill;
                  background rgba(0,0,0,.55); backdrop-filter blur(calc(16.85*var(--k)))
  .country__option padding 9 / 12; radius 8; white; 18/500/1; --track-tight; pointer
                  hover or [aria-selected=true] → rgba(255,255,255,.16)
  .finder__roles  absolute left 10, top 83; flex column; gap 5; width 519
  .pill--row      width 519; justify-content flex-start; cursor pointer
                  .role:hover rgba(0,0,0,.16); .role[aria-pressed=true] rgba(255,255,255,.2)
  .finder__results absolute left 10, top calc(var(--results-top)*var(--k));
                  flex column align center; gap 5; width 519;
                  transition top var(--finder-dur,600ms) var(--ease-panel)
  .expert         flex space-between align center; 519×80; padding 12 / 18;
                  radius --radius-pill; background var(--glass)
  .expert__who    flex align center; gap 13
  .expert__id / .expert__terms  flex column; gap 6 — .expert__terms align flex-end
  .expert__name / .expert__rate  white 20/500/1 --track-tight
  .expert__meta / .expert__type  white 16/400/1 --track-tight
                  .expert__meta opacity .5 · .expert__type opacity .6
  .finder__count  margin 0; padding 10 0; white 20/500/1 --track-tight

CTA
  .cta          absolute left 50%; bottom 76; flex; 252×63; transform translateX(-50%)
  .cta__label, .cta__go  grid place-items center; height 63; radius --radius-button;
                background white; color black
  .cta__label   width 189; font-size 19; weight 500; --track-tight
  .cta__go      width 63 · .cta__go img 21.2067×21.2067
  hover both → rgba(255,255,255,.86)

HERO FOOT
  .hero__foot   relative; flex none; height 180; margin-top 71
  .hero__title  absolute left 57, top 0; width 757; margin 0; font-size 100; weight 500;
                line-height .9; letter-spacing --track-display
  .hero__aside  absolute right 35, top 17; width 437
  .avatar-stack relative; height 56; children absolute top 0 at left 0 / 48 / 95 / 143
  .hero__lede   width 437; margin 43 0 0; font-size 25; weight 400; line-height 1.1;
                letter-spacing --track-display

FEATURES  (authored on a 1186.5px artboard; all numbers below already multiplied by
           1685 / 1186.5 = 1.420143 to sit on the same 1685 page)
  .features     display grid; row-gap 70;
                padding-top calc(var(--section-gap) * var(--page-scale));
                padding-inline calc(var(--section-inset) * var(--page-scale));
                padding-bottom 70
  .features__row display grid; min-width 0
  .features__row--top    grid-template-columns minmax(0,1060.28fr) minmax(0,457.29fr);
                         column-gap 25.44
  .features__row--bottom grid-template-columns minmax(0,774.44fr) minmax(0,738.47fr);
                         column-gap 30.06
  .feature      min-width 0
  .feature__media  position relative; width 100%;
                   height calc(577.97 * var(--k));
                   aspect-ratio: 1060.28 / 577.97;   ← Trap 2 safety net
                   min-height: 320px;                ← Trap 2 safety net
                   radius --radius-card; overflow hidden
  .feature__title  margin-block 39 0; font-size 37.48; weight 500; line-height .9;
                   --track-display; white-space nowrap
  .feature__text   margin-block 17 0; font-size 21.1; weight 400; line-height 1.1;
                   --track-tight; opacity .6; white-space nowrap

  Oversized Figma crops (absolute, max-width none — these deliberately overflow and are
  clipped by the media box; they are NOT object-fit images on desktop):
  .crop--payroll     absolute; left -247.27;  top -385.32; width 1380.29; height 1725.35
  .crop--onboarding  absolute; left -1055.85; top -210.19; width 1513.36; height 1891.70

  Floating chrome (all absolute inside .feature__media):
  .chip          gap 19.88; height 69.59; padding 17.04 / 25.56; radius 17.04;
                 font-size 22.72     (composes on top of .pill)
  .chip__icon    35.5×35.5; flex none
  .pill--glass   background var(--glass); white;
                 backdrop-filter blur(calc(30.11*var(--k)))
  .chip--payroll   left 149.85  top 254.67  width 242.84
  .chip--legal     left 149.12  top 120.71  width 157.64  height 56.81
  .chip--labor     left 117.88  top 213.02  width 220.12
  .chip--data      left  96.58  top 299.65  width 262.73
  .chip--contract  left 130.66  top 386.28  width 195.98
  .feature__connector  left 405.48  top 168.75 (=169.46 less the .71 stroke overhang)
                       width 133.49  height 239.99
  .mini-card     absolute left 557.43; flex space-between align center; 353.79×91.89;
                 padding 13.78 / 20.68; radius 13.78; background var(--glass);
                 backdrop-filter blur(calc(39.92*var(--k)))
                 tops: --r1 121.17 · --r2 242.93 · --r3 365.74
  .mini-card__who  flex align center; gap 14.93
  .avatar--mini    64.33×64.33
  .mini-card__name / __place  white 22.97/500/1 --track-tight nowrap
  .benefit-card  absolute left 199.56, top 150.25; flex column; gap 34.08;
                 413.26×298.23; padding 17.04 / 25.56; radius 17.04;
                 background var(--glass); backdrop-filter blur(calc(38.56*var(--k)))
  .benefit-card__person  flex align center; gap 18.46
                 its .avatar 79.53² · .expert__id gap 8.52
                 .expert__name 28.4 · .expert__meta 22.72
  .benefit-card__tags    flex column align flex-start; gap 11.36
                 its .chip { position: static }
  .mini-finder   absolute left 68.47, top 223.14; flex space-between align center;
                 603.56×117.87; padding 14.2; radius 25.56; background var(--glass);
                 backdrop-filter blur(calc(23.93*var(--k)))
  .mini-finder__field  flex align center; gap 28.4; 313.85×89.47
  .mini-finder .icon-button  89.47² radius 19.88 · its img 44.02²
  .mini-finder__placeholder  white opacity .4; 36.92/500/1 --track-tight
  .country--static  238.58×44.02; gap 15.62; padding 0 22.72; cursor default
                 its .country__icon 44.02² · its .country__label 36.92

SHOWCASE (base = absolute Figma placement; overridden at ≥1024px and below 1081px)
  .showcase          position relative; height calc(2387.26 * var(--k))
  .showcase__title   absolute left 69.59, top 274.09; width 624.86; margin 0;
                     font-size 96.85; weight 500; line-height .9; --track-display
  .showcase__title--second   left 71.01  top 1330.67  width 1062.27
  .showcase__figure  absolute left 71.01, top 521.19; width 1060.85; height 675.47;
                     margin 0; radius --radius-card; overflow hidden;
                     aspect-ratio 1060.85 / 675.47; min-height 260px   ← Trap 2
  .showcase__figure--second  left 72.43  top 1577.78

  @media (min-width: 1024px)  — the two stories sit side by side:
    .showcase → display grid; grid-template-columns repeat(2, minmax(0,1fr));
      grid-template-areas 'title-one title-two' / 'figure-one figure-two';
      grid-template-rows auto auto; column-gap 40; row-gap 42; height auto;
      padding-block calc(var(--section-gap)*var(--page-scale)) 120;
      padding-inline calc(var(--section-inset)*var(--page-scale));
    all four children → position static; width 100%
    .showcase__title  grid-area title-one; font-size 72
    .showcase__title--second  grid-area title-two
    .showcase__figure grid-area figure-one; height auto;
                      aspect-ratio 1060.85 / 675.47    ← keeps height non-zero
    .showcase__figure--second grid-area figure-two

═══════════════════════════════════════════════════════════════
8. RESPONSIVE ARCHITECTURE
The proportional desktop composition stays active down to 1080px. Below that its scaled
type and controls become too small for touch, so each section adopts an INTRINSIC layout.
Reminder: every --k redefinition below must stay LENGTH-valued in every clamp branch.
═══════════════════════════════════════════════════════════════
── TABLET: @media (min-width:700px) and (max-width:1080px)
.page  --tablet-inset: clamp(16px,2.5vw,28px);
       --tablet-section-gap: clamp(72px,10vw,108px);
       margin-inline: var(--tablet-inset)
.hero  --k: clamp(0.72px, calc((100vw - 2*var(--tablet-inset)) / 1080), 1px);
       min-height auto; padding-block 10px var(--tablet-section-gap)
.hero__media  flex none; min-height 0; height clamp(720px,90svh,820px);
       margin-inline 0; radius clamp(20px,3vw,30px)
.nav   left/right clamp(18px,3vw,28px); top clamp(16px,2.4vw,24px); height 48px
.brand 126×43px · .brand__mark 43×43px · .brand__name left 55px top 6px font-size 34px
.nav > .nav__cta { display: none }
.nav__toggle → SHOWN: position relative; z-index 4; grid place-content center; gap 7px;
       48×48px; padding 0; border 0; radius 14px; background var(--glass); color white;
       backdrop-filter blur(14px); cursor pointer
       its spans: 22×2px; radius 999px; background currentColor;
         transition transform 240ms var(--ease-panel)
       [aria-expanded=true] → first span translateY(4.5px) rotate(45deg);
                              last  span translateY(-4.5px) rotate(-45deg)   (X)
.nav__menu → dropdown: absolute; z-index 3; right 0; top 58px; display grid; gap 6px;
       width min(320px, calc(100vw - 2*var(--tablet-inset) - 36px)); height auto;
       padding 8px; radius 18px; background rgba(0,0,0,.28); backdrop-filter blur(22px);
       box-shadow 0 18px 42px rgba(0,0,0,.14); opacity 0; visibility hidden;
       transform translateY(-8px) scale(.98); transform-origin top right;
       transition opacity 220ms var(--ease-panel), transform 220ms var(--ease-panel),
                  visibility 220ms
       .nav__menu.is-open → opacity 1; visibility visible; transform none
.nav__link (plus `.nav__link:nth-child(n)` to beat the desktop width rules) and
.nav__cta--menu → display flex; justify-content flex-start; width 100%; min-height 48px;
       height auto; padding 14px 16px; radius 12px; font-size 16px
       .nav__cta--menu → justify-content center; margin-top 2px
.finder  left 50%; top 46%; width min(calc(541*var(--k)), calc(100% - 48px))
.cta     bottom clamp(36px,6vw,60px)
.hero__foot  display grid; columns minmax(0,1.55fr) minmax(240px,0.7fr); align-items start;
       column-gap clamp(32px,6vw,72px); height auto; margin-top clamp(48px,7vw,72px);
       padding-inline clamp(18px,4vw,44px)
.hero__title, .hero__aside → position static; width auto
.hero__title font-size clamp(58px,8.5vw,82px); line-height .9
.hero__aside padding-top 8px
.hero__lede  width auto; margin-top 30px; font-size clamp(18px,2.3vw,24px)
.features  --k: clamp(0.64px, calc((100vw - 2*var(--tablet-inset)) / 1080), 0.94px);
       gap clamp(56px,8vw,84px); padding 0 0 var(--tablet-section-gap)
.features__row  gap clamp(18px,2.5vw,28px)
.features__row--top     columns minmax(0,1.45fr) minmax(310px,0.75fr)
.features__row--bottom  columns repeat(2, minmax(0,1fr))
.feature  container-type: inline-size;  then per-card container-relative --k so the card
       interiors keep their design-unit geometry (note: LENGTH-valued):
         .feature--payroll    > * { --k: min(1px, calc(100cqw / 1060.28)) }
         .feature--onboarding > * { --k: min(1px, calc(100cqw / 457.29)) }
         .feature--benefits   > * { --k: min(1px, calc(100cqw / 774.44)) }
         .feature--experts    > * { --k: min(1px, calc(100cqw / 738.47)) }
.feature__media  height clamp(390px,53vw,540px); radius clamp(24px,4vw,38px)
.feature__title  margin-top clamp(24px,3.5vw,38px); font-size clamp(29px,3.8vw,38px);
                 white-space normal
.feature__text   margin-top 14px; font-size clamp(17px,2.15vw,21px); white-space normal
.showcase  --k: clamp(0.68px, calc((100vw - 2*var(--tablet-inset)) / 1080), 0.94px);
       same 2-column grid/areas as ≥1024px; column-gap clamp(20px,3vw,34px);
       row-gap clamp(28px,4vw,42px); height auto; padding 0 0 var(--tablet-section-gap);
       children static width 100%; .showcase__title font-size clamp(48px,6.5vw,66px);
       .showcase__figure height auto; aspect-ratio 1060.85/675.47

── NARROW TABLET: @media (min-width:700px) and (max-width:860px)
.hero__foot  grid-template-columns 1fr; row-gap 38px
.hero__aside display grid; columns 190px minmax(0,1fr); align center; gap 28px;
             padding-top 0
.hero__lede  margin 0
.features__row--top, .features__row--bottom → grid-template-columns 1fr
.features__row gap 56px
.feature__media height min(66vw, 520px)
.feature--onboarding .crop--onboarding { left -230.96%; top -36.37%; width 330.96%;
                                         height auto }
.feature--onboarding .chip { transform: translateX(calc((100cqw - 457.29px) / 2)) }
.showcase  grid-template-columns 1fr; areas 'title-one'/'figure-one'/'title-two'/'figure-two';
           row-gap 36px
.showcase__title--second margin-top 34px

── MOBILE: @media (max-width:699px)
.page  --mobile-inset: clamp(12px,4vw,20px);
       --mobile-section-gap: clamp(64px,18vw,88px); margin-inline var(--mobile-inset)
.hero  --k: 1px;   ← note the unit
       min-height auto; padding-block 8px var(--mobile-section-gap)
.hero__media flex none; min-height 0; height clamp(640px,88svh,760px);
       margin-inline 0; radius clamp(18px,6vw,26px)
.nav   left/right 16px; top max(14px, env(safe-area-inset-top)); height 46px
.brand 112×40px · mark 40×40px · name left 51px top 6px font-size 31px
.nav__toggle as tablet but 46×46px, spans 21×2px
.nav__menu top 56px; width min(300px, calc(100vw - 2*var(--mobile-inset) - 32px));
       background rgba(0,0,0,.3); box-shadow 0 18px 42px rgba(0,0,0,.16)
.finder left 50%; top 45%; width calc(100% - 24px); radius 16px
       FIXED pixel heights replace the scaled ones:
         collapsed 72px · suggestions 218px · results 344px · full 490px
.finder__bar left/top 8px; width calc(100% - 16px); height 56px
.finder__field gap 12px; width min(58%,230px); height 56px
.finder .icon-button 48×48px radius 12px · its img 24×24px
.finder__input, .finder__demo font-size clamp(16px,4.5vw,19px)
.finder__input width calc(100% - 60px) · .finder__demo left 60px top 18px
.country__toggle gap 7px; width auto; min-width 104px; height 36px; padding 0 8px
.country__icon 25×25px · .country__label clamp(15px,4vw,18px)
.country__menu top 40px; width 150px; padding 6px
.country__option min-height 42px; padding 12px 10px; font-size 15px
.finder__roles, .finder__results  left 8px; top 72px; gap 4px; width calc(100% - 16px)
.finder[data-state='full'] .finder__results { top: 218px }
.pill--row justify flex-start; width 100%; height 42px; padding 12px 14px; font-size 15px
.expert width 100%; height 76px; padding 10px 12px
.expert__who gap 10px · .expert .avatar 44×44px · .expert__id/.expert__terms gap 5px
.expert__name/.expert__rate clamp(13px,3.6vw,15px)
.expert__meta/.expert__type clamp(11px,3vw,13px)
.finder__count padding 9px 0; font-size 14px
.cta bottom max(24px, env(safe-area-inset-bottom)); 224×56px
.cta__label/.cta__go height 56px · .cta__label width 168px font-size 17px
.cta__go width 56px · its img 20×20px
.hero__foot display grid; gap clamp(34px,9vw,48px); height auto;
       margin-top clamp(42px,11vw,58px); padding-inline clamp(4px,2vw,10px)
.hero__title, .hero__aside → static; width auto
.hero__title max-width 11ch; font-size clamp(44px,12.2vw,68px); line-height .91
.hero__aside grid; columns 178px minmax(0,1fr); align center; gap clamp(18px,5vw,28px)
.avatar-stack height 50px · its avatars 50×50px · lefts 0 / 42px / 84px / 126px
.hero__lede width auto; margin 0; font-size clamp(16px,4.4vw,20px); line-height 1.15
.features display grid; gap clamp(52px,14vw,72px); padding 0 0 var(--mobile-section-gap)
.features__row grid-template-columns 1fr; gap clamp(48px,13vw,68px)
.feature min-width 0; container-type inline-size
.feature__media height clamp(330px,94vw,480px); radius clamp(24px,8vw,34px)
.feature__title margin-top clamp(24px,7vw,34px); font-size clamp(28px,8vw,38px); normal wrap
.feature__text  margin-top 13px; font-size clamp(17px,4.7vw,21px); normal wrap
IMPORTANT — the oversized Figma crops are neutralized on mobile:
  .feature__media > .crop { inset 0; width 100%; height 100%; max-width none;
                            object-fit cover }
  .feature--payroll    .crop--payroll    { object-position: 30% center }
  .feature--onboarding .crop--onboarding { object-position: 73% center }
.chip height 46px; padding 12px 15px; radius 13px; font-size 14px · .chip__icon 23×23px
.chip--payroll left 18px; top 30px; width auto
.feature__connector left 31%; top 104px; 58×108px
.mini-card left 43%; width 53%; height 62px; padding 9px 10px; radius 11px
       tops 88px / 160px / 232px · __who gap 8px · .avatar--mini 38×38px
       name/place clamp(11px,3vw,13px)
.chip--legal left 50%; top 30px; width auto; height 44px; transform translateX(-50%)
.chip--labor/.chip--data/.chip--contract left 50%; width auto; translateX(-50%)
       tops 98px / 158px / 218px
.benefit-card left 7%; top 48px; gap 20px; width 86%; height auto; padding 16px;
       radius 15px · __person gap 14px, its avatar 58×58px, name 20px, meta 15px
       __tags gap 9px, its chips max-width 100%, height 44px, font-size 13px
.mini-finder left 5%; top 50%; width 90%; height 76px; padding 10px; radius 18px;
       transform translateY(-50%) · __field gap 12px width 48% height 56px
       its icon-button 56×56px radius 13px, img 27×27px · placeholder 20px
.country--static gap 8px; width auto; height 34px; padding 0 8px
       its icon 28×28px · its label 18px
.showcase single-column grid (areas title-one/figure-one/title-two/figure-two); gap 0;
       height auto; padding 0 0 var(--mobile-section-gap); children static width 100%
.showcase__title max-width 10ch; font-size clamp(44px,12vw,66px); line-height .92
.showcase__title--second max-width 13ch; margin-top var(--mobile-section-gap)
.showcase__figure height auto; margin-top clamp(30px,8vw,42px); aspect-ratio 4/3;
       radius clamp(24px,8vw,34px)

── EXTRA-NARROW: @media (max-width:360px)
.hero__aside grid-template-columns 1fr; gap 24px
.finder__field width calc(100% - 106px)
.expert__meta max-width 98px
.mini-card left 39%; width 58% · its name/place font-size 10px

═══════════════════════════════════════════════════════════════
9. ONE-TIME ENTRANCE ANIMATION  (hero only)
═══════════════════════════════════════════════════════════════
Deliberately FINITE: two paint frames establish the start state, CSS resolves one
overlapping sequence, then every entrance class/timer/listener is removed. Only after
completion do the ambient hero zoom and the finder demo begin.

Participants: .brand, .nav__link, .nav > .nav__cta, .nav__toggle, .finder, .cta,
.hero__title, .avatar-stack, .hero__lede.

START — `html.entrance-pending`:
  all participants opacity 0
  .brand translateY(calc(-8*var(--k)))
  .nav__link, .nav > .nav__cta, .nav__toggle translateY(calc(-6*var(--k)))
  .hero__title clip-path inset(100% 0 0 0) + translateY(calc(18*var(--k)))
  .finder clip-path inset(5% 0 5% 0 round calc(var(--radius-panel)*var(--k)))
          + translate(-50%,-50%) scale(.98)
  .cta translateX(-50%) translateY(calc(10*var(--k))) scale(.985)
  .avatar-stack translateY(calc(8*var(--k))) scale(.97); transform-origin left center
  .hero__lede translateY(calc(10*var(--k)))
  mobile ≤699px overrides: title translateY(12px); finder translate(-50%,-50%) scale(.99);
    cta translateX(-50%) translateY(7px)
Add `will-change: opacity, transform` to participants under BOTH .entrance-pending and
.entrance-playing.

PLAY — `html.entrance-playing` transitions (duration / --ease-panel / delay):
  .brand            opacity 560ms @80ms   · transform 680ms @80ms
  .nav__link        opacity 460ms         · transform 580ms
        :nth-child stagger delays → 1:130ms · 2:170ms · 3:210ms · 4:250ms
  .nav > .nav__cta  opacity 480ms @280ms  · transform 600ms @280ms
  .nav__toggle      opacity 480ms @130ms  · transform 600ms @130ms
  .hero__title      opacity 680ms @180ms  · transform 900ms @180ms · clip-path 900ms @180ms
  .finder           opacity 720ms @390ms  · transform 920ms @390ms · clip-path 920ms @390ms
  .cta              opacity 520ms @710ms  · transform 700ms @710ms
  .avatar-stack     opacity 500ms @610ms  · transform 680ms @610ms
  .hero__lede       opacity 560ms @720ms  · transform 720ms @720ms

CONTROLLER (IIFE #1 in script.js):
  calm = matchMedia('(prefers-reduced-motion: reduce)')
  Gate on Promise.race([document.fonts.ready, 250ms timeout]) so fallback font metrics are
  never revealed but a slow font never stalls the entrance; fall through to playEntrance
  on both resolve and reject, and call it directly if document.fonts is unavailable.
  playEntrance(): if calm.matches → completeEntrance() immediately. Otherwise subscribe to
  calm changes, then double-requestAnimationFrame → add 'entrance-playing', remove
  'entrance-pending', set a 1700ms completion timer.
  completeEntrance() is idempotent: clear both timers (including
  window.__atlasEntranceFallback), remove both classes, set root.dataset.entrance =
  'complete', dispatch CustomEvent 'atlas:entrance-complete', unsubscribe.

═══════════════════════════════════════════════════════════════
10. FINDER DEMO LOOP + INTERACTIVE CONTROLS  (IIFE #2)
═══════════════════════════════════════════════════════════════
A 5.2s looping "someone is searching" demo the visitor can take over.
Constants: QUERY='Designer'; LOOP=5200; TYPE_STEP=58ms/char; ENTRY=780.
Bail out entirely (`return`) if `#finder` is absent.

Timeline (ms from loop start), driven by requestAnimationFrame — NOT setInterval:
     0  hide all experts + count (remove .is-revealed)
    70  size('collapsed', 667)
   350  hint(true)                    — restore placeholder, fade out typed text
  1060  type()                        — type "Designer" char by char
  1380  size('suggestions', 900)
  1620  reveal role 1
  1790  reveal role 2
  1960  reveal role 3
  2850  hide all roles
  3200  size('results', 1520)
  3370  reveal expert 1
  3570  reveal expert 2
  3770  reveal expert 3
  4270  reveal count
        …wraps at 5200.
`size(state, duration)` sets `--finder-dur: <duration>ms` on the panel and then assigns
`panel.dataset.state`, so each resize gets its own bespoke duration.

Reveal styling:
  .finder .role, .finder .expert, .finder__count
       → transition opacity 180ms linear, transform 180ms linear
  …same three with .is-revealed
       → transition opacity 420ms var(--ease-panel), transform 420ms var(--ease-panel)
  .finder.is-demo .role/.expert/.finder__count → opacity 0; transform scale(.9)
  .finder.is-demo …is-revealed                 → opacity 1; transform none

Typing effect: the real <input> is hidden (`.finder.is-demo .finder__input {opacity:0}`)
and a fake overlay shown instead (`.finder:not(.is-demo) .finder__demo {display:none}`).
  .finder__demo  absolute left 83, top 18.5; display block; white-space pre;
                 pointer-events none; 26/500/1 --track-tight; white
  .finder__demo-hint, .finder__demo-typed  absolute 0,0; white-space pre
  .finder__demo-hint  opacity .4; transition opacity 300ms linear; .is-hidden → opacity 0
  .finder__demo-typed transition opacity 300ms linear; .is-out → opacity 0
  .finder__demo-typed .char  opacity 0; transition opacity 120ms linear;
                             .char.is-in → opacity 1
type() appends one `<span class="char">` per letter and schedules `.is-in` at
index * 58ms. type(true) renders every char already `.is-in`.

Takeover: 'pointerdown', 'focusin', 'keydown' on the panel → stopDemo(): cancel the rAF,
clear timers, remove .is-demo, set panel.dataset.userOwned='true', type(true),
size('full', 420) — so every control in the design stays reachable.

Ambient motion gating:
  enableAmbientMotion()  → add 'continuous-motion' to <html> (starts hero-push) and call
                           video.play() with a caught rejection
  disableAmbientMotion() → remove the class; video.pause()
  applyMotionPreference(fromEntrance): if calm.matches → stop the loop, clear timers,
    remove .is-demo, disableAmbientMotion(), type(true), size('full', 0), return.
    Otherwise return early unless root.dataset.entrance === 'complete', then
    enableAmbientMotion() + startDemo(fromEntrance).
  Call it once on load, again on 'atlas:entrance-complete' ({once:true}), and on every
  calm change.
  startDemo(fromEntrance): no-op if already running or userOwned. Add .is-demo. From the
    entrance → jump straight to the results state and resume(0); otherwise → quiet
    collapsed state and resume(ENTRY).

Visibility: IntersectionObserver threshold 0.15 on the panel pauses the rAF loop when it
scrolls out of view and resumes from ENTRY when it returns.

Real filtering (independent of the demo):
  state = { query: '', country: 'Global' }
  input 'input' → update query → applyFilters()
  applyFilters(): hide any role whose text doesn't contain the query; hide any expert
  unless (country === 'Global' || expert.dataset.country === country) AND the text matches.
  Use the `hidden` property.
  Roles: clicking toggles aria-pressed exclusively (clear all, then set the clicked one
  unless it was already pressed).
  Country listbox: toggle opens/closes via the `hidden` attribute + aria-expanded;
  choosing an option updates the label and aria-selected, closes the menu, refocuses the
  toggle, and re-filters. Close on outside click and on Escape (restoring focus).

═══════════════════════════════════════════════════════════════
11. TABLET NAVIGATION CONTROLLER  (IIFE #3)
═══════════════════════════════════════════════════════════════
Desktop links stay the source of truth; this only changes how they're exposed below
1080px. Bail if .nav, .nav__toggle or #primary-menu is missing.
responsiveMenu = matchMedia('(max-width:1080px)').
setMenu(open, restoreFocus): toggle `.is-open`, set aria-expanded, swap aria-label
between 'Open navigation menu' / 'Close navigation menu', refocus the toggle when
closing with restoreFocus. Toggle click flips it. Clicking any <a> inside closes it.
'pointerdown' outside .nav closes it (only while the media query matches). Escape closes
and restores focus. On media-query change, force-close when back above the breakpoint.

═══════════════════════════════════════════════════════════════
12. SCROLL CHOREOGRAPHY  (IIFE #4)  — see Trap 3, this must fail OPEN
═══════════════════════════════════════════════════════════════
One-time only: each element is unobserved after revealing, so nothing replays on
scroll-back.

Controller order — do not deviate:
  1. Collect targets: all `.feature`, all `.showcase__title`, all `.showcase__figure`.
  2. If there are no features and no titles → return.
  3. If `!('IntersectionObserver' in window) || calm.matches` → return WITHOUT ever
     adding `scroll-reveal-ready`. (Sections stay visible — correct.)
  4. Construct the observer: threshold 0.16, rootMargin '0px 0px -10% 0px'.
  5. NOW add `scroll-reveal-ready` to <html>.
  6. observe() every .feature and every .showcase__title.
  7. Start the mandatory 3000ms safety net (Trap 3d): reveal everything, disconnect,
     remove `scroll-reveal-ready`. Clear this timer when all targets reveal normally.
  Revealing a title also reveals its paired `.showcase__figure` by index.
  When all targets are done, wait 1400ms, then remove `scroll-reveal-ready` and
  unsubscribe — leaving zero residual will-change.
  Also revealAll() immediately if reduced motion switches on mid-session.

Stagger variable:
  .feature, .showcase__title, .showcase__figure { --scroll-order: 0 }
  .feature:nth-child(even), .showcase__title--second, .showcase__figure--second
                                                    { --scroll-order: 1 }

Feature scene — hidden state, ALWAYS prefixed
`html.scroll-reveal-ready .feature:not(.is-revealed)`:
  .feature__media  opacity 0; clip-path inset(9% 0 0 0 round calc(var(--radius-card)*var(--k)));
                   transform translateY(calc(18*var(--k))) scale(.985)
  .feature__title  opacity 0; clip-path inset(0 0 100% 0);
                   transform translateY(calc(11*var(--k)))
  .feature__text   opacity 0; transform translateY(calc(9*var(--k)))
Revealed transitions under `html.scroll-reveal-ready .feature.is-revealed`
(every delay adds `var(--scroll-order) * 90ms`):
  .feature__media  opacity 720ms · transform 920ms · clip-path 920ms @ order*90ms
  .feature__title  opacity 560ms · transform 720ms · clip-path 720ms @ 150ms + order*90ms
  .feature__text   opacity 520ms · transform 680ms                  @ 260ms + order*90ms
  (mobile ≤699px: hidden media transform becomes translateY(14px) scale(.99))

Interior choreography — each element gets its own `--inside-delay`, local to its card,
so every scene reads as a single action:
  payroll:    connector 250 · chip--payroll 320 · mini-card r1 390 · r2 460 · r3 530
  onboarding: chip--legal 280 · chip--labor 360 · chip--data 440 · chip--contract 520
  benefits:   benefit-card 280 · __person 390 · tags .chip:first 480 · :last 560
  experts:    mini-finder 300 · icon-button 410 · placeholder 470 · country--static 540
  each written `calc(<n>ms + var(--scroll-order) * 90ms)`
Interior hidden states (same `:not(.is-revealed)` prefix):
  .chip--payroll        opacity 0; translateX(calc(-14*var(--k)))
  .feature__connector   opacity 0; clip-path inset(50% 0 50% 0)   ← draws out from centre
  .mini-card            opacity 0; translateX(calc(18*var(--k)))
  .feature--onboarding .chip  opacity 0; translateY(calc(10*var(--k)))
  .benefit-card         opacity 0; translateY(calc(14*var(--k))) scale(.985)
  .benefit-card__person and .benefit-card__tags .chip
                        opacity 0; translateY(calc(8*var(--k)))
  .mini-finder          opacity 0; translateY(calc(12*var(--k))) scale(.985)
  .mini-finder .icon-button and .mini-finder__placeholder
                        opacity 0; translateX(calc(-8*var(--k)))
  .country--static      opacity 0; translateX(calc(8*var(--k)))
Interior revealed transition: opacity 460ms + transform 640ms, both @ var(--inside-delay);
the connector instead uses opacity 420ms + clip-path 620ms @ var(--inside-delay).

Showcase story:
  hidden title  → opacity 0; translateY(calc(15*var(--k)))
  hidden figure → opacity 0; clip-path inset(10% 0 0 0 round calc(var(--radius-card)*var(--k)));
                  translateY(calc(20*var(--k))) scale(.985)
                  (mobile ≤699px: translateY(16px) scale(.99))
  revealed title  → opacity 620ms + transform 820ms @ order*100ms
  revealed figure → opacity 760ms + transform 980ms + clip-path 980ms @ 190ms + order*100ms

═══════════════════════════════════════════════════════════════
13. REDUCED MOTION  @media (prefers-reduced-motion: reduce)
═══════════════════════════════════════════════════════════════
  *, *::before, *::after { transition: none !important; animation: none !important }
  Every entrance participant under .entrance-pending → opacity 1; clip-path none;
  transform none — EXCEPT .finder keeps translate(-50%,-50%) and .cta keeps
  translateX(-50%), since those are layout, not animation.
  Every scroll-reveal target → opacity 1; clip-path none; transform none;
  will-change auto.
  JS additionally: no ambient zoom, video paused, finder parked in the 'full' state with
  the query already typed, scroll observer never starts. Toggling the OS setting
  mid-session must take effect live in BOTH directions.

═══════════════════════════════════════════════════════════════
14. QUALITY BAR
═══════════════════════════════════════════════════════════════
- Zero horizontal overflow from 320px to 2560px.
- Every backdrop-filter carries a -webkit-backdrop-filter twin.
- Keyboard: focus-visible outlines, Escape closes both menus, focus returns to triggers,
  the finder demo yields to the user on first focus or keypress.
- The page renders correctly and stays fully readable with JavaScript disabled.
- Preserve the source typos verbatim — they are in the original design:
  "mult-currency", "Belguim", "Hearth Insurance".
- Semantic HTML: one <h1>; <h2> for showcase headlines; <h3> for feature titles;
  decorative images `alt="" aria-hidden="true"`; showcase images get real alt text.
- Before finishing, run all four checks in §0 FINAL ACCEPTANCE TEST.
[/hidecontent]
← 返回首页