Vista previa en vídeo
GratisHeroAgencia

Contratación tecnológica

El prompt
ID: powering-global-talent-recruitment Category: Recruitment / Staffing Agency Hero Type: hero

Create a single-file HTML+CSS+vanilla-JS hero section with the following exact specifications:

## Tech Stack

* Deliverable filename: `recruitment-hero.html`  
* Plain HTML \+ CSS \+ vanilla JS. No frameworks, no build step.  
* Fonts — literal copy-pasteable block:

\<link rel="preconnect" href="https://fonts.googleapis.com"\>

\<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin\>

\<link href="https://fonts.googleapis.com/css2?family=Epilogue:wght@400;500;700\&family=Geist:wght@400\&display=swap" rel="stylesheet"\>

- Epilogue (400/500) → all body copy, nav, buttons, labels  
- Epilogue 700 → nav-link hover state only (bolder on hover)  
- Geist (400) → every counted/numeric figure ("29K+", "40+", the stat number) — never Epilogue for numbers  
* Global reset:

\*{ margin:0; padding:0; box-sizing:border-box; }

html, body{ width:100%; height:100%; overflow:hidden; background:\#fff; font-family:'Epilogue', sans-serif; color:\#000; }

## Canvas & Scaling

* True fullscreen, edge-anchored page. No fixed design canvas, no `transform:scale()`.  
* Do NOT add `transform:scale(...)` anywhere on this page and do NOT wrap content in a fixed-size `.stage-wrap`/`.stage` pair.  
* `.stage{ position:fixed; inset:0; overflow:hidden; }` is the fullscreen root.  
* Background is a **video**, not a photo: `<video autoplay muted loop playsinline><source src="https://api.promptsites.net/s3/promptsites/previews/2afab0c5-c8b2-4fbd-982c-d000be58907f.mp4" type="video/mp4"></video>` inside `.bg-photo{ position:fixed; inset:0; z-index:0; }`, with `.bg-photo video{ position:absolute; inset:0; width:100%; height:101%; object-fit:cover; }`. `autoplay` requires `muted` — never drop it.  
* Three separate 1px vertical decorative lines, each anchored to match a **real element's edge**, not a shared arbitrary margin:  
  - `.grid-line-left{ left:111px; }` — matches the logo / hero-copy / career-widget left edge  
  - `.grid-line-mid{ left:916px; }` — matches the "worldwide" card's left edge  
  - `.grid-line-right{ right:78px; }` — matches the top-actions icon cluster's right edge AND the "worldwide" card's right edge (both share this exact offset — don't let them drift apart)  
  - Do NOT collapse these into one shared `--edge` token; the right-side elements deliberately sit at a different offset (78px) than the left column (111px).  
* **Right-edge offsets are NOT uniform** across the page: `.top-actions` and `.worldwide-widget` both use `right:78px`; nothing else on the right edge shares that number.  
* The "worldwide" card is **bottom-anchored** (`bottom:0`), not top-anchored — its original design coordinates put its bottom edge flush with the canvas bottom, so pinning it from `top` would misplace it on any viewport taller or shorter than the original 800px design frame.  
* The "BUILD YOUR CAREER" widget is also **bottom-anchored** (`bottom:8px`), for the same reason — it sits almost flush with the bottom of the canvas in the source design.  
* The hero title/copy/button block and the "29K+ Professionals" stat block are **top-anchored** with flat px values — they are NOT tied to the header's height or to each other beyond the fixed offsets given below.

## Design Tokens

\--green: \#005918;

\--peach: \#fee8cc;

\--dark-green: \#206d35;

Font sizes used: 80px (hero h1) / 40px (stat number) / 29.86px (card headline) / 20px / 18px / 13.44px.

## Elements

(background first, then decorative lines, then logo, nav, top-right icons, then hero copy, then the three floating widgets — visual/DOM order)

### 1\. Background video

* Full-bleed, `object-fit:cover`, `autoplay muted loop playsinline`.  
* Asset (promptsites.net, permanent): `https://api.promptsites.net/s3/promptsites/previews/2afab0c5-c8b2-4fbd-982c-d000be58907f.mp4`

### 2\. Decorative lines \+ corner dot

* `.lines-horizontal`: `position:fixed; left:0; top:142.5px; width:1426px; height:559.5px; z-index:1; pointer-events:none;` — a single image asset (`https://api.promptsites.net/s3/promptsites/previews/5535ac7a-dcc1-4b6b-ac7d-b0928048fb0b.png`) drawn at `width:100%; height:100%;`.  
* `.corner-dot`: `position:fixed; left:0; bottom:130px; width:8px; height:8px; background:#fff; z-index:2;`

### 3\. Logo — `position:fixed; left:111px; top:54px; width:62px; height:34px; z-index:10;`

* Asset: `https://api.promptsites.net/s3/promptsites/previews/c7cfe7bd-332b-4a66-b26f-1ee3a3d14630.png`

### 4\. Top nav — `position:fixed; left:313px; top:55px; width:506px; z-index:10;` flex row, `justify-content:center; align-items:center; gap:96px;`

* Four links, `font-size:18px; line-height:32px; letter-spacing:-0.36px; color:#000;`: **About**, **Jobs**, **Industries**, **Blog**.  
* Hover: `transform:scale(1.15); font-weight:700;` (transition 0.2s on both `transform` and `font-weight`). Requires `display:inline-block` on the `<a>` for the scale to apply cleanly, and requires the 700-weight of Epilogue to actually be loaded (see Tech Stack) or the hover jump will be invisible.

### 5\. Top-right icon cluster — `position:fixed; right:78px; top:42px; z-index:10;` flex row, `align-items:center; gap:8px;`

* Search button: `width:58px; height:58px; border-radius:77px; background:#fefefe; backdrop-filter:blur(16.95px);` centers a 24×24px icon (`https://api.promptsites.net/s3/promptsites/previews/e1898a32-fd12-4330-974d-7d9a7c247520.png`).  
  * **Fragile coupling:** the icon itself needs a manual `transform:translate(-1px, -1px)` nudge — the source SVG's magnifying-glass glyph is not visually centered in its own bounding box (the handle skews the visual weight down-right), so pure flex-centering of the container is not enough to make it *look* centered.  
* Profile avatar: `width:58px; height:58px; border-radius:100px; overflow:hidden; background:var(--peach);` filled with a cover-fit photo (`https://api.promptsites.net/s3/promptsites/previews/0148c9a1-a516-43c0-ac0b-d5817ef5a1e2.png`).

### 6\. Hero copy — `position:fixed; left:111px; top:130px; width:514px; z-index:10;`

* **H1**, exact copy: **"Powering Global Talent"** — `font-weight:500; font-size:80px; line-height:93px; letter-spacing:-3.2px; color:#000;`  
* **Paragraph**, exact copy: **"Specialized recruitment for energy, infrastructure, engineering, construction."** — `font-weight:400; font-size:20px; line-height:32px; letter-spacing:-0.4px; width:471px; color:#000;`  
* **Button** "Hire Experts" — `margin-top:20px; width:284px; height:70px; background:var(--green);` centers white text (18px/32px/-0.36px). Starts **hidden** (`opacity:0; transform:translateY(6px);`) and fades in (`.is-visible` class adds `opacity:1; transform:translateY(0);`) — driven by JS, see Interactive Behavior below, NOT a CSS `animation` — the reveal is timed to a JS typing callback, not a fixed delay.  
  * Hover: `background:#000; transform:scale(1.06); box-shadow:0 10px 24px rgba(0,0,0,0.25);`  
  * Hover also triggers a diagonal "shine" sweep: a `::before` pseudo-element (`width:40%; height:100%; background:linear-gradient(120deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.35) 50%, rgba(255,255,255,0) 100%); transform:skewX(-20deg);`) resting at `left:-60%` and animating to `left:130%` on hover (`transition:left 0.55s ease`).

### 7\. "29K+ Professionals" stat — `position:fixed; right:78px; top:178px; width:118px; z-index:10;` flex column, `align-items:center; gap:11px;`

* Number: **Geist**, `font-size:40px; letter-spacing:-1.6px;` — starts at `0K+`, counts up on load (see Interactive Behavior).  
* Label: **Professionals** — Epilogue 18px, `margin-top:5px`.  
* Two overlapping 58×58px circular avatars below (`margin-right:-10px` on the first), backgrounds `var(--dark-green)` and `#fff` respectively, photos at `object-fit:contain`. Assets: `https://api.promptsites.net/s3/promptsites/previews/fdc20386-268b-45b5-9484-ff06b5e620d9.png`, `https://api.promptsites.net/s3/promptsites/previews/04464c3c-0b52-4491-b6bd-a060a9e5ee97.png`.

### 8\. "Hire top professionals \[word\]" card — `position:fixed; right:78px; bottom:0; width:425.75px; height:246.34px; z-index:10; overflow:hidden;`

* Hover: whole card `transform:scale(1.035)` (`transform-origin:bottom right`), cursor pointer. **The drop-shadow on hover goes on `.bg-panel` only, not on this outer card** — see Fragile coupling below.  
* `.bg-panel`: `position:absolute; left:0; top:32.1px; width:425.75px; height:214.24px; background:var(--peach);`  
* `.portrait`: `position:absolute; left:133.94px; top:0; width:283.67px; height:246px; overflow:hidden;` — cover-fit photo, `object-position:center top`. Asset: `https://api.promptsites.net/s3/promptsites/previews/6a64b044-ed1d-41c7-9baa-773278bf733b.png`.  
* `.content`: `position:absolute; left:22.45px; top:53.75px; width:380.11px; height:170.2px;` flex row, `justify-content:space-between; align-items:flex-start;`  
  - Left column (209.02px): headline `"Hire top professionals "` \+ a cycling word (see Interactive Behavior) — `font-size:29.86px; line-height:32.1px; letter-spacing:-1.194px;`, **fixed `height:97px`** (fragile coupling, see below) — then, gap 58.97px below it, a small row: a 6.72px dot icon (`https://api.promptsites.net/s3/promptsites/previews/95ffbf93-f182-4be0-80fa-0ca8d5a9bcab.png`) \+ a counting number ("0+" → "40+", Geist, `font-variant-numeric:tabular-nums; min-width:2ch; text-align:right;`) \+ the word " countries".  
  - Right column (44.79px): a 44.79px play-badge icon (`https://api.promptsites.net/s3/promptsites/previews/676592c3-0b86-412f-9d2b-5e7e0a682f09.png`) \+ the label **"Watch"** below it, centered.

### 9\. "BUILD YOUR CAREER WITH LEADING COMPANIES" widget — `position:fixed; left:111px; bottom:8px; width:118.28px; z-index:10;` flex column, `align-items:center; gap:11px;`

* Photo: `width:118px; height:122px; overflow:hidden;`, cover-fit. Asset: `https://api.promptsites.net/s3/promptsites/previews/1a408a89-eb81-42dd-95a2-65685731bac1.png`.  
* Caption, uppercase, white, `font-size:20px; line-height:22.4px; letter-spacing:-0.4px; text-align:center;`, four lines via typewriter (see Interactive Behavior): **BUILD YOUR / CAREER WITH / LEADING / COMPANIES**.

## Interactive (JS) Behavior

All of the following run once on page load, in parallel unless noted, and every loop below checks `prefers-reduced-motion` and jumps straight to the final resting state if it's set (no cursor blink, no animation, just the finished text/number).

**1\. Hero title \+ subtitle typewriter, sequential** — title types out, and only once it's done does the "Hire Experts" button fade in (`.is-visible`) and the subtitle start typing:

function typeInto(el, speed, onDone){

  var full \= el.getAttribute('data-full');

  if (reduceMotion){ el.textContent \= full; if (onDone) onDone(); return; }

  var i \= 0;

  el.textContent \= '';

  (function step(){

    if (i \<= full.length){ el.textContent \= full.slice(0, i); i++; setTimeout(step, speed); }

    else if (onDone){ onDone(); }

  })();

}

typeInto(titleEl, 45, function(){

  hireBtn.classList.add('is-visible');

  typeInto(subtitleEl, 18);

});

Title and subtitle elements must start as **empty** `<h1 data-full="Powering Global Talent"></h1>` / `<p data-full="...">` — the full copy lives only in `data-full`, never pre-rendered in the tag's text content, or the "typing" reveal does nothing.

**2\. "BUILD YOUR CAREER..." multi-line typewriter — runs in PARALLEL with the title**, not after it:

function typeIntoMultiline(el, speed, onDone){

  var full \= el.getAttribute('data-full'); // uses "|" as the line-break marker, e.g. "BUILD YOUR|CAREER WITH|LEADING|COMPANIES"

  var flat \= full.replace(/\\|/g, '\\n');

  if (reduceMotion){ el.innerHTML \= full.split('|').join('\<br\>'); if (onDone) onDone(); return; }

  var i \= 0; el.innerHTML \= '';

  (function step(){

    if (i \<= flat.length){ el.innerHTML \= flat.slice(0, i).split('\\n').join('\<br\>'); i++; setTimeout(step, speed); }

    else if (onDone){ onDone(); }

  })();

}

typeInto(titleEl, 45, function(){ hireBtn.classList.add('is-visible'); typeInto(subtitleEl, 18); });

typeIntoMultiline(careerEl, 35); // called immediately, NOT inside the title's onDone callback

**3\. Cycling word ("worldwide" → other phrases)** — typewriter-style type/delete loop, cycling forever through `['worldwide', 'across borders', 'without limits', 'at scale']`, no blinking cursor character ever rendered:

var cycleWords \= \['worldwide', 'across borders', 'without limits', 'at scale'\];

// type forward to full word, hold 1800ms, delete backward to empty, move to next word, repeat forever

No trailing punctuation after the cycling word in the sentence — an earlier version had a period after it, which changed the rendered line width per word and made the text visibly jump; the sentence intentionally ends with no ".".

**4\. "29K+" — counts up, then loops forever** (not a one-time animation):

(function loopCount(){

  var current \= 0;

  var timer \= setInterval(function(){

    current++;

    countEl.textContent \= current \+ 'K+';

    if (current \>= 29){

      clearInterval(timer);

      setTimeout(function(){

        countEl.textContent \= '0K+';

        setTimeout(loopCount, 400); // reset and count up again, forever

      }, 2200);

    }

  }, 1100/29);

})();

**5\. "40+ countries" — counts up once** on load (0 → 40), does NOT loop.

## Animations

There are no CSS `@keyframes` in this design — every piece of motion (typewriter reveals, the counters, the button reveal) is JS-driven via `setTimeout`/`setInterval`, not CSS animation. The only CSS transitions are hover states (button shine sweep, nav-link scale, card scale/shadow) and the button's `.is-visible` opacity/transform fade, all listed inline above.

`prefers-reduced-motion: reduce` handling: every JS loop (typewriter, cycling word, both counters) checks it independently at the top of its own function and short-circuits straight to the final value — there is no single global "disable everything" switch; each loop must carry its own check, or it will still play under reduced motion.

## Z-index Layering

1. `.bg-photo` (video) — z-index: 0  
2. `.grid-line` (all three) / `.lines-horizontal` — z-index: 1  
3. `.corner-dot` — z-index: 2  
4. Logo / nav / top-actions / hero / stat-left / worldwide-widget / career-widget — z-index: 10 (all share this layer; DOM order handles their mutual stacking since none overlap except on hover)  
5. `.worldwide-widget:hover` — z-index: 20 (lifted above its siblings only while hovered, so its scale-up doesn't get clipped under an adjacent element)

## Notes

* **Fragile coupling — hover shadow placement on the "worldwide" card.** The hover box-shadow lives on `.bg-panel`, not on the outer `.worldwide-widget`. The card's portrait photo intentionally pokes out above the peach panel (the panel starts 32.1px down from the card's own top edge) — if the shadow were on the outer card instead, it would render as a shadow floating in empty space above the panel, behind the person's head, which looks broken. Keep the shadow scoped to `.bg-panel`.  
* **Fragile coupling — cycling-word headline height.** `.headline` has an explicit `height:97px` and `flex-shrink:0`. Without it, cycling between short words ("at scale") and longer ones ("across borders") changes how many lines the sentence wraps to, which shoves the "40+ countries" row below it up and down every few seconds. The fixed height absorbs that instead.  
* **Fragile coupling — countries counter width.** `#countriesNum` has `min-width:2ch; text-align:right; font-variant-numeric:tabular-nums;` — without it, "0+" (1 digit) vs "40+" (2 digits) shift the word "countries" next to it as the counter climbs.  
* **Fragile coupling — right-edge alignment.** `.top-actions` and `.worldwide-widget` must both stay at exactly `right:78px` — they're visually meant to line up with the rightmost decorative grid line (`right:78px`) and with each other. If one drifts even 1px, the vertical grid line will visibly miss both edges.  
* **Asset hosting:** all image/icon/video assets are hosted on permanent promptsites.net URLs (`https://api.promptsites.net/s3/promptsites/previews/...`). No Cloudinary or Figma temp URLs remain in this spec.

Please ensure the output is a clean, production-ready single HTML file that renders pixel-identically to this spec, filling the entire browser viewport edge-to-edge at any window size with no letterboxing and no canvas scaling — every block must remain correctly pinned to its respective viewport edge via position:fixed.