/* ==========================================================================
   Cardiff — Careers page
   Depends on assets/styles.css (Cardiff Design System tokens + webfonts).
   Every value here comes from a DS token; no raw hex except white/black alphas
   over the dark sections, where the DS has no token.

   1. Base
   2. Layout          .page .section .stats .hero .life .cta
   3. Components      .pill .btn .sh-* .card .life__img .filters
                      .role-* .benefit-*
   4. Page nav        .page-nav (anclas de seccion de careers)
   5. Responsive
   ========================================================================== */

/* ==========================================================================
   1. Base
   ========================================================================== */

*{box-sizing:border-box}

/* Height of the fixed site navbar from _includes/newnavbar.html (h-20 = 80px).
   The sticky .page-nav offsets itself by this, and section anchors add it to
   their scroll-margin. careers.js measures [data-nav] at runtime for the same
   thresholds, so this is the fallback and the single value to edit if the
   navbar's height ever changes. */
:root{--site-nav-h:80px}

html{scroll-behavior:smooth}

body{
  margin:0;
  background:var(--white);
  color:var(--ink);
  font-family:var(--font-sans);
  -webkit-font-smoothing:antialiased;
}

/* Scoped to .page so it styles this page's own copy only. The site header and
   footer (from _includes) sit outside .page and colour their links by inheritance
   — and inheritance loses to any rule that matches the <a> itself, whatever its
   specificity, so a bare `a{}` here would repaint the whole footer. :where()
   contributes zero specificity, so these two rules keep exactly the weight they
   had before the scope was added. */
:where(.page) a{color:var(--c-600);text-decoration:none}
:where(.page) a:hover{color:var(--c-700);text-decoration:underline}

/* Anchor targets must clear BOTH bars when jumped to: the fixed site navbar and
   the sticky page nav below it. 72px only ever cleared the page nav, so every
   in-page jump landed with its heading behind the navbar. */
section[id]{scroll-margin-top:calc(var(--site-nav-h, 80px) + 72px)}

/* The blue word inside an ink headline. */
.accent{color:var(--accent-word)}
/* Same role on the dark sections: c-600 fails contrast there, c-500 is the
   large-text-only step the DS reserves for exactly this. */
.accent-on-dark{color:var(--c-500)}

.bg-paper{background:var(--paper)}
.line-btm {border-bottom: 1px solid var(--rule);}

/* Hover lift — from Proposal D, so cards behave the same here as on the home.
   Reusable: put it on any bordered surface that should respond to the cursor.
   Colour is in the transition list so a .lift element that also changes fill on
   hover animates it for free. Declaring transition on the element instead would
   overwrite this one — same specificity, and every card class is declared later
   in the file. Colour runs at the manual's 180ms, not the lift's 400ms. */
.lift{transition:transform var(--motion-slow) var(--ease-standard), box-shadow var(--motion-slow) var(--ease-standard), background-color var(--motion-fast) var(--ease-standard), border-color var(--motion-fast) var(--ease-standard)}
.lift:hover{transform:translateY(-3px);box-shadow:var(--shadow-edge)}


/* ==========================================================================
   2. Layout
   ========================================================================== */

.page{min-height:100vh}

/* Every mid-page section shares one measure and one rhythm. */
.section{width:100%;margin:0 auto;}
.container{max-width:1440px;margin:0 auto;padding:var(--space-24) var(--space-16)}

/* Wrapper grouping a title with its lede — structural only, no styles of its
   own; .sh-title / .sh-lede carry the spacing. */

/* ── Hero ──
   Light section, two columns: copy left, one portrait photograph right. The flex
   weights below come out at roughly 57.5 / 42.5, which is the manual's 7/5
   copy-led split.

   A white surface puts the manual's light-side rules back in play: ink headline,
   coffee body, highlight at 600. Worth recording why this layout returned. The
   intermediate version ran the copy full-width over a darkened photograph, and
   that surface could not carry the accent word — sampling real pixels under it
   at four widths gave 2.16:1 average and 1.13:1 at its lightest, against the
   3:1 large text requires. Raising the scrim to 70% fixed the arithmetic and
   flattened the photograph to texture. Putting the photo in its own column
   solves both: the type sits on white, and the image is never asked to be a
   background. */
#hero{background:var(--white)}
/* No negative margin here any more. It existed so the hero photograph ran up
   behind the transparent page nav; with the photo in a column there is nothing
   to bleed upward, so the padding is the plain visible figure again rather than
   an arithmetic trap every breakpoint had to repeat. */
/* row-reverse, not order. The distinction matters at the stacking breakpoint:
   `order` values keep applying once the axis turns vertical, so they would put
   the photograph above the copy on a phone — a change to the reading order that
   nobody asked for. row-reverse only describes the horizontal axis, and the
   flex-direction:column at 900 replaces it outright, so stacked order stays DOM
   order: copy first, photo second. */
.hero{max-width:1440px;margin:0 auto;padding:var(--space-12) var(--space-16) var(--space-18);display:flex;gap:var(--space-18);align-items:center}
.hero__copy{flex:1.1 1 0;min-width:0}
/* Context sets the highlight value, not the markup: .accent stays "the
   highlighted word" and the surface decides which blue it takes. On white that
   is 600 — the manual's light-surface case. */
#hero .accent{color:var(--c-600)}
.hero__pills{display:flex;gap:var(--space-3);flex-wrap:wrap;margin-bottom:var(--space-7)}
/* 6.1vw hits the original 88px at the 1440px measure and scales down from there,
   matching how .sh-title and .cta__title already work. balance, not pretty:
   centred headings want even line lengths, and the manual asks for text-balance
   on display tiers. */
/* H1+, which the guide labels "Hero headline". No clamp of its own: the token
   is already responsive (56 mobile / 64 desktop) and a clamp here would be a
   second scale competing with the system's. */
.hero__title{margin:0;font-size:var(--type-h1p);line-height:var(--leading-h1p);letter-spacing:-0.045em;font-weight:800;}
/* Capped at 54ch. The cap is what stops the lede tracking the column width — in
   the wide copy column it would otherwise run past 90 characters a line, and the
   manual is explicit that long measures are what make a page feel unedited. */
.hero__lede{margin:var(--space-8) 0 0;font-size:var(--type-base);line-height:1.6;color:var(--coffee);max-width:54ch}
.hero__actions{display:flex;gap:var(--space-4);margin-top:var(--space-10)}
/* Third-party certification badge, so it keeps its own red — an external mark is
   not a brand colour to reconcile. Sized by height like every other logo on the
   page rather than by width, and hung from the photograph's top-right corner,
   straddling the edge so it reads as sitting in front of the image.

   ⚠ The overhang used to have a hard ceiling and no longer does, which is worth
   knowing before anyone raises it. While the copy led the row, the photo sat last
   and the only space beyond its right edge was the page gutter — 64px, 40 below
   1024, 24 below 640 — so crossing it gave the page a horizontal scrollbar. An
   -80px overhang did exactly that once: 16px of overflow, invisible above a
   1440px viewport where the container centres and leaves slack, and present on
   every laptop between 1025 and 1440.

   With the columns reversed the photo leads, so this right edge now faces the
   72px gap between the columns instead of the viewport. The badge is interior:
   there is no overflow to hit, and the real limit became the headline. At 36px it
   crosses 36px of that 72px gap and stops half way. Past 72px it would start
   sitting under the copy column.

   drop-shadow, not box-shadow, and this is not a style preference. The asset is a
   pennant with a chevron point at the bottom and roughly 34px of transparent
   canvas down each side, so its box is not its shape. box-shadow follows the
   box: it would draw a soft rectangle standing clear of the artwork on three
   sides — most visibly a grey edge under the point, where there is nothing to
   cast it. filter: drop-shadow follows the alpha channel, so the shadow traces
   the pennant.
   The geometry is approximated rather than copied: --shadow-float's two layers
   both use a negative spread, which drop-shadow() has no parameter for, so the
   blur is pulled in to compensate and the two layers collapse into one.
   No border-radius: the corners it would round are already transparent. */
.hero__award{position:absolute;right:-36px;top:-24px;z-index:2;filter:drop-shadow(0 6px 14px rgba(15,23,42,0.22))}
.hero__award img{display:block;height:180px;width:auto;margin:0}

/* The photograph column. aspect-ratio holds the slot open before the JPEG
   decodes, so the hero never reflows on load — that is also why this image is
   the one on the page without loading="lazy" and with fetchpriority="high".

   9:11, not 4:5. The manual's instruction is to reuse an established ratio
   before inventing one, and 9:11 is the only portrait ratio it lists. It also
   happens to be the closer fit: the source file is 1069×1318, ratio 0.811,
   against 0.818 for 9:11 and 0.800 for 4:5 — so this crops less than 4:5 would.
   min-height keeps it from collapsing to a letterbox when the copy is short.

   Radius stays --radius-lg for consistency with every other surface on the page.
   The manual specifies 16px for media, which the token scale has no step for;
   that belongs to the radius harmonisation pass, not to one lone slot here. */
.hero__media{flex:0.9 1 0;min-width:0;position:relative;aspect-ratio:9 / 11;min-height:420px}
/* Desktop ceiling. At 9/11 over 540px of width the image came out 660 tall,
   and once the h1 dropped from 88 to 64 it was out of proportion against its
   text column. Desktop only: from 768 to 1023 the max-width:460 holds it, and
   below 640 it has a ceiling of 250 of its own. */
@media (min-width:1024px){.hero__media{max-height:450px}}
.hero__img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;border-radius:var(--radius-lg);display:block}

/* ── Stat band ──
   No outer hairlines: --rule is a warm grey drawn for a chalk band on white, and
   against the tinted band it only muddies the join. The colour change is the
   boundary.

   --stat-rule is local to this band and exists so the divider colour is written
   once. It is needed in two places — border-right here, border-bottom when the
   cells stack at 640 — and those two drifted apart before. */
.stats{background:var(--c-100);--stat-rule:rgba(var(--brand-rgb),0.18)}
.stats__inner{max-width:1440px;margin:0 auto;padding:0 var(--space-16);display:grid;grid-template-columns:repeat(3,minmax(0,1fr))}
/* Inner cells get 40px of gutter, outer edges stay flush with the measure. */
.stat{padding:var(--space-12) var(--space-10)}
.stat:first-child{padding-left:0}
.stat:last-child{padding-right:0}
/* c-600 at 18%, not a white alpha. White alphas are the manual's answer for
   separators on *dark* surfaces, which this band used to be; over c-100 white at
   25% computes to rgb(228,239,254) against a rgb(219,234,254) ground — 1.05:1,
   drawn but not visible, confirmed by sampling the rendered pixels rather than
   trusting the screenshot. 18% of the brand blue lands at 1.256:1, which is
   exactly what --rule measures on white, so this divider reads at the same
   strength as every other one on the page while staying in the band's hue. */
.stat:not(:last-child){border-right:1px solid var(--stat-rule)}
.stat__num{font-size:var(--type-h1);font-weight:800;letter-spacing:-0.04em;line-height:1; color:var(--ink)}
.stat__num--brand{color:var(--c-700)}
.stat__note{margin-top:var(--space-3);font-size:var(--type-sm);color:var(--ink-2)}

/* ── Why Cardiff ── */
/* Full-measure band opening the section. 5:2 gives it presence without pushing
   the header and cards far down; a tighter 3:1 starts decapitating people in a
   group shot. Ratio is declared here rather than baked into the file so the
   crop follows the layout when the viewport narrows. */
/* height:auto is load-bearing — the <img> width/height attributes land as
   presentational hints, and without it the height hint wins over aspect-ratio
   and pins the band to the file's own height at every viewport. */
.card-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-6);margin-top:var(--space-14)}

/* ── Life at Cardiff ── */
.life{display:flex;gap:var(--space-18);align-items:center; margin-top:var(--space-9);}
.life__copy{flex:0.9 1 0;min-width:0}
/* Two columns: the left photo spans both rows, the right two stack. Rows are
   equal so the stacked pair reads as a pair; 220+220+16 keeps the block at the
   same 456px total the previous 240/200 layout had, so the copy column still
   lines up. */
.life__copy .sh-lede {padding-bottom:var(--space-8);}
.life__media{flex:1.1 1 0;min-width:0;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);grid-template-rows:repeat(2,220px);gap:var(--space-4)}
/* Ruled list: a hairline opens every item and one closes the set, so the rules
   read as separators between peers rather than as an underline on each. */
.life-list{border-bottom:1px solid var(--rule)}
.life-item{padding:var(--space-6) 0;border-top:1px solid var(--rule)}
/* The counter sits in its own column, nudged down to meet the cap height of the
   title rather than its baseline. */
/* 28px is the .card-title step, reused rather than inventing a size. */
.life-item__title{grid-column:2;grid-row:1;margin:0;font-size:var(--type-h6);font-weight:700;letter-spacing:-0.03em;line-height:1.15;color:var(--ink)}
.life-item__text{grid-column:2;grid-row:2;margin:var(--space-3) 0 0;font-size:var(--type-sm);line-height:1.6;color:var(--coffee)}

/* ── Open roles ── */
.roles-head{display:flex;align-items:end;justify-content:space-between;gap:var(--space-10);flex-wrap:wrap}

/* ── Closing CTA ── */
/* Ported from the home's #apply section (FinalCTA): full-bleed photo with a
   slow ken-burns drift, one flat tint (no gradient), an oversized numeral
   watermark bleeding off the bottom edge, and the copy centred.
   Three deliberate departures from the source, all because the substrate
   differs — see each rule. --ink-2 stays as the fallback while the photo
   decodes, so the section is never a white flash. */
.cta{position:relative;overflow:hidden;padding:var(--space-24) var(--space-16);background:var(--ink-2);color:var(--white); margin-bottom:var(--space-24); /* 2xl, the same as .role-card and .rp-head. It used to say var(--leading-h2-mobile):
     a line-height token used as a radius, which gave 44px by accident. */
  border-radius: var(--radius-2xl);}
.cta__img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:50% center;animation:ctaKenburns 22s ease-in-out alternate infinite}
@keyframes ctaKenburns{0%{transform:scale(1.04) translate(-0.5%,-0.5%)}100%{transform:scale(1.14) translate(0.5%,0.5%)}}
/* (1) Source tint is black/35, calibrated for a bright portrait. This photo is
   an already-dark interior, so 35% flattened it to near-black and threw the
   image away. 20% keeps the wall texture and the warm bulbs readable. */
/* A two-layer veil. Underneath, the system's flat --scrim. On top, a radial
   panel that darkens the text block and fades out before the edges.

   It is needed because the photo has a window at top centre (luminance 0.72)
   directly under the title, and no flat veil reaches the 3:1 large text asks
   for: at .20 it gives 1.68:1 and at .55 it still falls short, while the
   photo's median (0.081) flattens to black. Measured cell by cell across the
   text band, this panel gives 3.40:1 at its worst point.

   If the photo is swapped for one with a dark centre, this layer is spare. */
.cta__tint{position:absolute;inset:0;background:
  radial-gradient(ellipse 150% 100% at 50% 50%,
    rgba(0,0,0,0.55) 0%,
    rgba(0,0,0,0.55) 55%,
    rgba(0,0,0,0) 100%),
  var(--scrim)}
/* (2) Source watermark is the business figure $12.4B+ with a count-up. Here it
   is the founding year, which is what this section's copy actually leans on
   ("Twenty-two years of lending behind you") — a lending volume would be an
   odd brag on a careers page, and careers already prints $12B+ further up. */
.cta__mark{position:absolute;left:0;right:0;bottom:-40px;text-align:center;pointer-events:none;user-select:none;-webkit-user-select:none;opacity:.15;font-size:clamp(11.25rem,28vw,30rem);font-weight:800;letter-spacing:-0.045em;line-height:1}
/* Source drops the watermark further off-edge from lg up (-bottom-10 → -24);
   without that step it sits behind the lede and buttons instead of under them. */
@media (min-width:1024px){.cta__mark{bottom:-96px}}
.cta__inner{position:relative;max-width:1400px;margin:0 auto;text-align:center}
/* (3) Source scales to 144px for "Your next move starts here." This copy is
   longer, so it tops out at 96px to stay on two lines. */
/* This is an <h2>. It used to say var(--leading-h1), a line-height token used
   as a size: that gave 60px, which is no step on the scale. */
.cta__title{margin:0;font-size:var(--type-h1);line-height:0.9;letter-spacing:-0.045em;font-weight:800;text-wrap:balance}
.cta__lede{margin:var(--space-10) auto 0;font-size:var(--type-base);line-height:1.6;color:var(--on-dark);max-width:48ch;text-wrap:pretty}
.cta__actions{margin-top:var(--space-12);display:flex;align-items:center;justify-content:center;gap:var(--space-4);flex-wrap:wrap}
/* Source gave the button a wide blue glow to lift it off the photo; --shadow-brand
   is the DS token for exactly that job, so it stands in for the raw rgba. */
.cta .btn--primary{box-shadow:var(--shadow-brand)}


/* ==========================================================================
   3. Components
   ========================================================================== */

/* ── Pill ── */
.pill{display:inline-flex;align-items:center;gap:8px;padding:7px 15px;border:1px solid var(--rule);border-radius:var(--radius-pill);background:var(--white);font-size:var(--type-xs);font-weight:500;color:var(--coffee);white-space:nowrap}
.pill-dot{width:7px;height:7px;border-radius:var(--radius-full);background:var(--c-600)}
/* Category pill per the manual: c-50 fill, c-700 text, 13px / 600. */
.pill--tint{background:var(--c-50);border-color:var(--c-100);color:var(--c-700);font-weight:600}

/* ── Button — pill, Inter 500, primary darkens 600→700 on hover ── */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;font-family:var(--font-sans);font-weight:500;line-height:1.2;white-space:nowrap;border-radius:var(--radius-pill);cursor:pointer;text-decoration:none;transition:background var(--motion-fast) var(--ease-standard), box-shadow var(--motion-fast) var(--ease-standard), color var(--motion-fast) var(--ease-standard);border:1px solid transparent}
.btn:hover{text-decoration:none}
.btn--lg{padding:14px 28px;font-size:16px}
.btn--primary{background:var(--brand);color:var(--text-on-brand);border-color:transparent}
.btn--primary:hover{background:var(--brand-hover);color:var(--text-on-brand)}
.btn--secondary{background:var(--surface-card);color:var(--text-heading);border-color:var(--border-default)}
.btn--secondary:hover{background:var(--surface-raised);color:var(--text-heading)}

/* ── Section header — no eyebrows: the cardiff.co home never puts a label above
   a heading (it reserves uppercase/tracked type for step counters and footer
   column titles), so sections here open straight on the title. ── */
.sh-title{font-family:var(--font-sans);font-weight:800;letter-spacing:-0.025em;line-height:1.02;margin:0;color:var(--ink);font-size:var(--type-h2);line-height:var(--leading-h2)}
/* H1, "Section title". */
.sh-title--lg{font-size:var(--type-h1);line-height:var(--leading-h1)}
.sh-lede{margin:var(--space-5) 0 0;font-size:var(--type-base);line-height:1.6;color:var(--coffee);max-width:60ch}

/* ── Card — white / 1px rule; tinted = Cardiff 50 fill + 100 border ── */
.card{background:var(--surface-card);border:1px solid var(--rule);border-radius:var(--radius-lg);padding:var(--space-8)}
.card--tinted{background:var(--c-50);border-color:var(--c-100)}
/* Media card — photo flush to the top edge, copy beneath. The padding moves off
   the card and onto the text block so the image can reach the corners, and
   overflow:hidden clips it to the radius. 16:10 is the manual's section-image
   ratio, reused rather than introducing a seventh one.
   Written as .card.card--media, not .card--media: the 640px block sets
   .card{padding:var(--space-6)} further down the file, and at equal specificity that
   would win and put the padding back. */
.card.card--media{padding:0;overflow:hidden;display:flex;flex-direction:column}
.card__img{width:100%;height:auto;aspect-ratio:16 / 10;object-fit:cover;display:block;flex-shrink:0}
.card__text{padding:var(--space-8)}
/* Card category label. Kept where the section eyebrows were dropped: this one
   names which of the three cards you are reading, so it carries meaning rather
   than decorating a heading. */
.card-label{font-size:var(--type-xs);font-weight:600;letter-spacing:.18em;text-transform:uppercase;color:var(--c-700);margin-bottom:var(--space-4)}
.card-title{margin:0 0 var(--space-3);font-size:var(--type-h6);line-height:var(--leading-h6);font-weight:700;letter-spacing:-0.03em;color:var(--ink)}
/* Base S, the 16px prose tier. It used to read --type-base-mobile, which is
   a reference value: its name promises a breakpoint this rule does not have,
   and nothing else in the repo consumed one. */
.card-body{margin:0;font-size:var(--type-base-sm);line-height:var(--leading-base-sm);color:var(--coffee)}
/* Body copy needs the stronger ink to hold up over the tinted fill. */
.card--tinted .card-body{color:var(--ink-2)}


/* ── Life images ──
   The .img-slot placeholder set that used to live here is gone: every slot on the
   page now holds a real photograph, and the dashed stand-ins were the last thing
   referencing it. .life__img--tall kept its rule — it was sharing a selector with
   the placeholder's tall variant, not depending on it. */
.life__img--tall{grid-row:span 2}
/* Grid children, so no absolute positioning — the cell already sizes them. */
.life__img{width:100%;height:100%;object-fit:cover;border-radius:var(--radius-lg);display:block}

/* ── Role filters + list ── */
.filters{display:flex;gap:var(--space-3);flex-wrap:wrap;margin:var(--space-9) 0 var(--space-2)}
.filter{padding:9px 18px;border-radius:var(--radius-pill);font-family:var(--font-sans);font-size:var(--type-sm);font-weight:500;white-space:nowrap;cursor:pointer;background:transparent;color:var(--coffee);border:1px solid var(--rule);transition:background var(--motion-fast) var(--ease-standard), color var(--motion-fast) var(--ease-standard), border-color var(--motion-fast) var(--ease-standard)}
.filter.is-active{background:var(--brand);color:var(--text-on-brand);border-color:var(--brand)}
/* Roles use the manual's testimonial-card construction: white on a rule border,
   24px radius, 32px padding opening to 36px at lg, category pill at the foot,
   three-up from md. Mobile-first, so the grid starts as one column. */
.roles-grid{display:grid;grid-template-columns:1fr;gap:var(--space-6);margin-top:var(--space-6)}
@media (min-width:768px){.roles-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}
/* 24px is the manual's card radius. --radius-lg is still 10px from the
   Foundations scale — pending the radius harmonisation, this one is literal. */
.role-card{display:flex;flex-direction:column;background:var(--white);border:1px solid var(--rule);border-radius:var(--radius-2xl);padding:var(--space-8);text-decoration:none;color:inherit}
@media (min-width:1024px){.role-card{padding:var(--space-9)}}
/* border-color follows the fill: --rule is a warm grey and reads muddy against a
   blue tint, so the whole card becomes one tinted surface on hover. */
.role-card:hover{background-color:var(--c-100);border-color:var(--c-100);text-decoration:none}
/* Card title tier: 22–34px, 800, lh 1.2, -0.045em. */
.role-card__title{margin:0;font-size:var(--type-h6);font-weight:800;letter-spacing:-0.045em;line-height:1.2;color:var(--ink)}
.role-card__meta{margin:var(--space-3) 0 0;font-size:var(--type-sm);line-height:1.5;color:var(--coffee)}
/* A testimonial card aligns its feet with flex-1 on the quote. Roles carry no
   body copy, so margin-top:auto does that job — it keeps the pills on one line
   across the row when a title wraps to two. */
.role-card__foot{margin-top:auto;padding-top:var(--space-6);display:flex;align-items:center;justify-content:space-between;gap:var(--space-3)}
.role-card__arrow{width:18px;height:18px;flex-shrink:0;color:var(--c-600);transition:transform var(--motion-fast) var(--ease-standard)}
.role-card:hover .role-card__arrow{transform:translateX(3px)}
/* Needed explicitly: .role-card sets display:flex, which has the same specificity
   as the UA's [hidden]{display:none} and wins on order, so paginated-out cards
   would stay visible without this. */
.role-card[hidden]{display:none}

/* Changing page or filter swaps the grid's contents, so the incoming cards get
   an entrance instead of appearing instantly — responsive motion, which is what
   the manual allows. Only the arriving page animates: the outgoing one shares no
   cards with it and the grid reflows anyway (6 then 4), so holding the old
   layout to fade it out would buy nothing.

   Keyframes rather than a transition:.lift already owns this element's
   transition property, and a second declaration would replace it.

   No fill-mode, deliberately. With `both` the card holds the 0% frame before the
   animation starts, so anything that stops it from running — a dropped frame
   budget, a stalled event loop — leaves the card stuck at opacity 0. Without a
   fill mode the resting state is the visible one and the animation is purely
   additive: if it never runs, the card is simply there. It also means the
   element's own transform returns on its own afterwards, so a lingering class
   can never block the hover lift. */
@keyframes roleIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.role-card.is-entering{animation:roleIn .28s cubic-bezier(.2,.7,.2,1)}

/* Carousel dots — the manual's pagination device. Active 26×9 in brand blue,
   inactive 9×9 in the newly tokenised grey. */
.dots{display:flex;align-items:center;justify-content:center;gap:var(--space-2);margin-top:var(--space-9)}
.dots[hidden]{display:none}
.dot{width:9px;height:9px;padding:0;border:0;border-radius:var(--radius-pill);background:var(--dot-inactive);cursor:pointer;transition:width var(--motion-fast) var(--ease-standard), background-color var(--motion-fast) var(--ease-standard)}
.dot:hover{background:var(--c-500)}
.dot.is-active{width:26px;background:var(--c-600)}
/* Inter with tabular figures: the count changes as you filter, and without
   them the digits shift width. That is what the mono was giving here. */
.roles-count{font-family:var(--font-sans);font-variant-numeric:tabular-nums;font-size:var(--type-xs);color:var(--mute);letter-spacing:var(--tracking-numeric)}

/* ── Benefits ── */
/* Only the top padding differs here — the section above already supplies that
   gap. Everything else is left to .container on purpose: the id in this selector
   makes it (1,1,0), which outranks every responsive .container override, so
   spelling out the horizontal padding pinned this one section to 64px gutters at
   all widths. On a 390px screen that ate 128px and left the heading and the
   carousel visibly indented past the rest of the page. */
#benefits .container{padding-top:0}
/* ── Benefits marquee ──
   The mask. overflow:hidden is what makes it a marquee, and it is also what would
   crop a card mid-scale, so the padding is not decoration: at 1.15 a 210px card
   grows to 242px, spilling about 16px off each edge. The 48px of vertical padding
   sits inside the overflow box, so the card grows into room the mask already
   owns. It is deliberately more than the 16px needed — the band wants that air as
   spacing anyway, and it leaves headroom if the scale is dialled up again.

   Splitting the axes is not an option here. overflow-x:hidden with
   overflow-y:visible does not do what it reads like — the spec forces the
   visible axis to compute as auto, so it buys a vertical scrollbar rather than a
   card that escapes. */
.benefits{position:relative;margin-top:var(--space-12);overflow:hidden;padding:var(--space-12) 0}
/* max-content, not 200%: the track is exactly as wide as its two sets, whatever
   they measure, so the -50% in the keyframes always lands on the seam. */
.benefits__track{display:flex;width:max-content;animation:benefitsScroll 30s linear infinite}
.benefits__set{display:flex;gap:var(--space-5);padding-right:var(--space-5)}
/* Three ways to stop it, one per modality: :hover for a mouse, :active for a
   finger, and .marquee-pause for a keyboard — which covers the other two as
   well, and is what WCAG 2.1.1 asks for once 2.2.2 requires the mechanism at
   all.

   :focus-within is deliberately NOT in this list, and the reason is worth
   keeping. It was inert while .benefit held nothing focusable, and the pause
   button is what made it live. A button keeps focus after it is pressed, so
   :focus-within went on pinning paused after is-paused came off: Resume flipped
   the label and moved nothing until focus left the band. A selector that only
   ever added a pause turned into one that prevented a resume. */
.benefits:hover .benefits__track,
.benefits:active .benefits__track{animation-play-state:paused}
/* Translating by half the track puts the copy exactly where the original began. */
@keyframes benefitsScroll{from{transform:translateX(0)}to{transform:translateX(-50%)}}

/* Fixed width, not a grid fraction: a marquee has no column count to divide, and
   a fixed card keeps one set comfortably wider than the container so the mask is
   never showing empty track. */
/* position:relative is load-bearing and belongs here, not on :hover. The two
   overlay pseudo-elements are inset:0 absolute, so they size against the nearest
   positioned ancestor — with the card static at rest they escaped it entirely and
   painted the scrim across the whole section, gaps and all. */
.benefit{position:relative;width:280px;flex-shrink:0;padding:var(--space-8) var(--space-3) var(--space-8) var(--space-3);border:1px solid var(--border-on-dark);border-radius:var(--radius-lg);background-color:var(--ink-2);background-size:cover;background-position:50% 50%;overflow:hidden;isolation:isolate;transition:transform var(--motion-slow) var(--ease-standard), box-shadow var(--motion-slow) var(--ease-standard), border-color var(--motion-slow) var(--ease-standard)}
/* z-index so the grown card paints over its neighbours rather than under
   whichever happens to come later in the source. */
.benefit:hover{transform:scale(1.2);z-index:2;box-shadow:var(--shadow-card);border-color:var(--c-100)}

/* Two stacked layers behind the text, both at z-index:-1 inside the card's own
   stacking context (that is what isolation:isolate buys). Paint order inside a
   stacking context puts the element's own background first, then negative-index
   children, then in-flow content — so the photograph sits at the bottom, these
   two ride over it, and the text stays on top without needing a z-index of its
   own. overflow:hidden on the card is what clips them to the 10px radius;
   pseudo-elements at inset:0 ignore border-radius otherwise.

   background-image cannot be transitioned, which is why the white state is a
   separate layer fading in rather than a swapped image. */
.benefit::before,.benefit::after{content:'';position:absolute;inset:0;z-index:-1;transition:opacity var(--motion-slow) var(--ease-standard)}
/* The manual's standard scrim for text over photography. */
/* A bottom fade, not a flat veil, and the reason is measurable. The name is white
   at rest, and over a flat 5% scrim it failed badly on the bright patches these
   photographs are full of — laptop screens, lit tabletops. Sampling the exact
   pixels behind the text with the name hidden: 28% of them under 3:1 on Medical,
   worst case 1.12:1, against the 3:1 that 21px/700 large text requires.
   Raising the flat scrim would have fixed the numbers and thrown away the bright
   photography that the 5% was chosen for. This darkens only the band the text
   occupies — the name sits between 24% and 39% up from the card's bottom edge —
   and leaves the top at the original 5%, so the image reads as bright as before
   everywhere the eye actually looks at it.
   The manual allows exactly one kind of gradient, "functional bottom fades", and
   holding type legible is what it means by functional. */
.benefit::before{background:linear-gradient(to top,rgba(0,0,0,0.70) 0%,rgba(0,0,0,0.62) 42%,rgba(0,0,0,0.10) 68%,rgba(0,0,0,0.05) 100%)}
.benefit::after{background:var(--white);opacity:0}
.benefit:hover::before{opacity:0}
.benefit:hover::after{opacity:1}

/* One photograph per benefit, 800 x 560 — the card is 280 x 194, so this covers
   the hovered 1.15 at 2x and a 240px card at 3x, with the ratio close enough that
   cover barely crops. Seen only at rest: the white state covers them completely.
   The class stays semantic where the filename is literal — retirement / 401. */
.benefit--medical{background-image:url('/assets/img/careers/benefit-medical.jpg')}
.benefit--dental{background-image:url('/assets/img/careers/benefit-dental.jpg')}
.benefit--vision{background-image:url('/assets/img/careers/benefit-vision.jpg')}
.benefit--retirement{background-image:url('/assets/img/careers/benefit-401.jpg')}
.benefit--pto{background-image:url('/assets/img/careers/benefit-pto.jpg')}
/* Icon tile lifted from the home's Plaid feature rows so both pages share one
   icon treatment: 52px square, c-50 fill, 22px stroke icon in brand blue.
   Tailwind's rounded-xl (12px) snapped to --radius-lg (10px) — the DS card
   radius and the closest token; the 2px is imperceptible at this size. */
/* Every one of these carries two colour states: over the photograph at rest, on
   white once the card is hovered. The chip cannot keep its c-50 ground over a
   photo — a pale blue tile floating on an image reads as a mistake — so it goes
   translucent white and comes back to the token pair on hover. */
/* The icon travels by transform, not by changing its position. Transform is
   outside layout, so it can move without the text below it reflowing, and the two
   states stay a single animatable property — swapping between absolute and static
   would not animate at all.

   The offset is the delta between where flow puts the icon and the 24/24 corner it
   parks in at rest. Flow position IS the card's padding, so: 12px left padding
   means +12 to reach 24, and 32px top padding means −8. The padding changes at
   640, so the delta is restated there. Anyone editing .benefit's padding has to
   redo this arithmetic. */
/* The icon format from the homepage security section: a 52px box
   on c-50, a 22px glyph in c-600. The radius stays on --radius-lg:
   the homepage uses Tailwind's rounded-xl, 12px, and that step is not on the
   repo's ladder. */
.benefit-icon{width:52px;height:52px;flex-shrink:0;border-radius:var(--radius-lg);background:var(--c-50);display:flex;align-items:center;justify-content:center;margin-bottom:var(--space-5);transform:translate(0px,-20px);transition:background-color var(--motion-slow) var(--ease-standard), transform var(--motion-slow) var(--ease-standard)}
.benefit:hover .benefit-icon{background:var(--c-500);transform:none}
/* The colour lives on the svg, not on the chip. It has to: the icons are stroked
   in currentColor, and a colour set on .benefit-icon is what the svg rule below
   overrides — so the chip's own colour never reached the glyph, and the
   transition declared for it was animating nothing while the glyph snapped.
   Glyph at 32 of 52 — the ratio the 640 rule reproduces against its own chip. */
.benefit-icon svg{width:22px;height:22px;display:block;color:var(--c-600);transition:color var(--motion-slow) var(--ease-standard)}
.benefit:hover .benefit-icon svg{color:var(--white)}
/* Visible at rest, so it carries two colours: white over the scrimmed photograph,
   ink once the card resolves to white. No opacity here — the name is on screen
   the whole time and only its position and colour move. */
.benefit-name{font-size:var(--type-base);font-weight:700;letter-spacing:-0.02em;color:var(--white);transform:translateY(14px);transition:transform var(--motion-base) var(--ease-standard), color var(--motion-base) var(--ease-standard)}
/* Two delays, in the order the properties are declared above: the rise waits
   100ms so it still reads as arriving behind the card lighting up, but the colour
   starts immediately and finishes in 250ms against the background's 350ms.
   That ordering is load-bearing. Delay the colour as well and the name stays
   white while the ground turns white underneath it — white on white, invisible
   for a beat in the middle of the transition. Darkening ahead of the background
   means the text is always the darker of the two.
   Both live on :hover rather than the base rule so the exit is immediate; on the
   base they would apply in both directions and the name would lag the pointer. */
.benefit:hover .benefit-name{transform:none;color:var(--ink);transition-delay:.1s,0s}
/* opacity, not display:none. Two reasons, and neither is cosmetic: the note keeps
   its space in the layout, so revealing it cannot change the card's height and
   jolt the whole track; and it stays in the accessibility tree, so someone who
   never hovers still gets the text. display:none would fail both. */
/* Furthest offset and the longest delay, so the two lines arrive as a sequence
   rather than together — the note reads as following the name up. */
.benefit-note{font-size:var(--type-sm);line-height:1.55;color:var(--mute);margin-top:var(--space-2);opacity:0;transform:translateY(18px);transition:opacity var(--motion-base) var(--ease-standard), transform var(--motion-base) var(--ease-standard)}
.benefit:hover .benefit-note{opacity:1;transform:none;transition-delay:.16s}


/* ==========================================================================
   4. Page nav — anclas de seccion de careers

   The header and footer ported from "Cardiff - Proposal D (Standalone)" used
   to live here too. They left on 2026-09-04: the nine pages loading this CSS
   all carry `new_chrome: true`, so the navbar and footer come from the new
   chrome and not one of those rules still applied. If they are ever needed,
   they are in the git history.
   ========================================================================== */

/* ── Row 2: page nav (careers section anchors) ──
   The sticky row, carrying the section anchors only. It used to slide a compact
   Cardiff logo in from the left once stuck; that was dropped when this page moved
   onto the site's own navbar, which keeps the brand present on its own.

   Sticks below that navbar, not at the viewport top. The offset cannot come from
   .page-nav__inner's margin-top: .page-nav has no padding or border, so the margin
   collapses straight out of it. At rest the collapsed margin still places the bar
   correctly — which is why this looked right until you scrolled, and then pinned to
   0 underneath the navbar (fixed, 80px, z-index 50 against this 40).

   At rest the bar has nothing to separate itself from: it sits directly under the
   navbar on the same light ground, so it stays transparent and the two rows read as
   one piece of chrome. Fill, blur and shadow arrive together with .is-stuck, which
   careers.js adds once the page has actually scrolled — not from the bar's own
   position, which reads the same at rest as it does while stuck. The blur rides on
   .is-stuck for the same reason as the rest: a backdrop filter over a flat
   background costs a compositing layer and buys nothing. */
.page-nav{position:sticky;top:var(--site-nav-h);z-index:40;background:transparent;transition:background var(--motion-base) var(--ease-standard), box-shadow var(--motion-base) var(--ease-standard)}
.page-nav.is-stuck{background:rgba(255,255,255,0.92);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:var(--shadow-edge)}
.page-nav__inner{max-width:1440px;margin:var(--space-20) auto 0;padding:0 var(--space-16);height:56px;display:flex;align-items:center}
.page-nav__links{display:flex;align-items:center;gap:var(--space-8);font-size:var(--type-sm);font-weight:500;min-width:0;overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none}
.page-nav__links::-webkit-scrollbar{display:none}
/* Links are dark at every stage now. They briefly ran light (--rule, flipping to
   --coffee on scroll) while the hero was a dark photograph bleeding up behind
   this bar; that arrangement never quite cleared AA — --rule measured 4.41:1 on
   the plate, 0.09 short — and with a white hero the question is moot. The
   transition left on `color` costs nothing and keeps the .is-active swap smooth. */
.page-nav__links a{position:relative;white-space:nowrap;padding:17px 0;color:var(--coffee);transition:color var(--motion-base) var(--ease-standard)}
.page-nav__links a:hover{color:var(--ink);text-decoration:none}
/* Active marker is colour + a rule, never a weight change — swapping weight on
   a 4-item bar makes the links jitter as you scroll past each section. */
.page-nav__links a.is-active{color:var(--ink)}
.page-nav__links a.is-active::after{content:'';position:absolute;left:0;right:0;bottom:-1px;height:2px;background:var(--brand);border-radius:var(--radius-pill)}


/* ==========================================================================
   5. Responsive

   Three steps, reusing the breakpoints the ported chrome already introduced
   rather than inventing a second scale:

     1023  gutters tighten, grids lose a column, and the two side-by-side
           splits (hero, life) stack — folded up from 900 on 2026-09-07 so
           the page changes mode where the Tailwind chrome does
     640   phone: everything single-column, buttons go full width

   Type mostly handles itself — .hero__title, .sh-title and .cta__title are all
   clamp(), so only the fixed sizes need stepping down.
   ========================================================================== */

/* ── 1023: tablet y abajo ── */
@media (max-width:1023px){
  /* The page nav links scroll horizontally, they do not wrap. */
  .page-nav__inner{padding:0 var(--space-6)}

  .container{padding:var(--space-18) var(--space-10)}
  .hero{padding:var(--space-22) var(--space-10) var(--space-14);gap:var(--space-10)}
  .stats__inner{padding:0 var(--space-10)}
  .stat{padding:var(--space-10) var(--space-7)}
  .life{gap:var(--space-10)}
  /* 3 → 2 and 5 → 3; both leave a short last row, which reads fine on cards. */
  .card-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--space-5);margin-top:var(--space-10)}
  /* Nothing to do for the benefits here any more — a marquee has no column count
     to step down, and the card keeps its fixed width at every width. */
  .cta{padding:var(--space-26) var(--space-10);margin-top:var(--space-18)}

  /* The side-by-side splits (hero, life) stack here. They used to break at
     900; they were folded onto this step on 2026-09-07 so the page changes
     mode where the Tailwind chrome does. */

   .hero__title {text-wrap:balance}
  .hero{flex-direction:column;align-items:stretch}
  .life{flex-direction:column}
  /* The flex:N 1 0 ratios were written for a row. Once the axis turns vertical
     that 0 basis applies to height, so both halves reset to content sizing —
     without this .hero__media collapses to nothing, since its only child is
     absolutely positioned and contributes no in-flow height. */
  .hero__copy,.hero__media,.life__copy,.life__media{flex:0 0 auto}
  /* Capped rather than full-bleed: at 9:11 a full-width photo on an 880px screen
     would stand over 1000px tall and push the whole page below the fold. */
  .hero__media{width:100%;max-width:460px;min-height:0}
  /* Stacked, the photo is capped at 460px and left-aligned, so its right edge
     sits mid-page with nothing but white beside it — an overhang there would have
     the badge floating in empty space rather than crossing an edge. Inside the
     image from here down.
     right, not left, and this is correctness rather than taste: the base rule
     anchors to the right, so adding left here would constrain the box on both
     sides and stretch it. */
  .hero__award{right:16px;top:16px}
}


/* ── 640: phone ── */
@media (max-width:640px){
  /* Three anchors on a phone, not four. All four measure 383px against the 342 a
     390px screen offers, so the strip overflowed by 41px and "Open roles" sat cut
     in half. Dropping "Life here" takes it to roughly 262px, which fits with room
     to spare — and it is the anchor the page can most afford to lose, since the
     section is still there to scroll past. Targeted by href so the markup stays
     one list; the scroll spy only toggles a class and never measures these links,
     so a hidden one costs it nothing.
     Note it is display:none, so this anchor leaves the accessibility tree too —
     the same trade the footer's hidden columns make.
     The mask stays as insurance for the narrowest phones: it fades the container's
     last 28px, so it only dims anything when content actually reaches that edge.
     flex:1 is what makes that true. Without it the container is a flex item sized
     to its content, so "the last 28px of the container" and "the last 28px of the
     text" are the same thing and the final link was permanently dimmed — visible
     in the render even with three links and 56px to spare. Filling the row puts
     the fade on the empty tail, where it does nothing until the strip actually
     overflows, at around 300px. */
  .page-nav__links a[href="#life"]{display:none}
  .page-nav__links{flex:1 1 auto;gap:var(--space-5);}
      .page-nav__inner {gap:var(--space-3);}

  .container{padding:var(--space-14) var(--space-6)}
  .hero{padding:var(--space-8) var(--space-6); flex-direction: column-reverse;}
  .hero__media {max-height: 250px;}
  .hero__lede{margin-top:var(--space-6)}
  /* Position is already handled at 900; this is only the size step down. The
     pennant is narrow, so it takes a taller value than the old square badge did
     to carry comparable weight. */
  .hero__award {right:20px; top:-20px;}
  .hero__award img{height:88px}
  .hero__actions{flex-direction:column;align-items:stretch;margin-top:var(--space-8)}
  .hero__actions .btn{width:100%}

  /* The stat band's dividers switch axis with the layout: vertical rules only
     make sense while the cells sit side by side. */
  .stats__inner{grid-template-columns:1fr;padding:0 var(--space-6)}
  .stat{padding:var(--space-6) 0}
  .stat:not(:last-child){border-right:0;border-bottom:1px solid var(--stat-rule)}
  .stat:first-child{padding-left:0;padding-top:var(--space-8)}
  .stat:last-child{padding-right:0;padding-bottom:var(--space-8)}

  /* 5:2 across a phone column is a 130px strip — too thin to read as a photo,
     so the band deepens instead of scaling down. */
  .card-grid{grid-template-columns:1fr;gap:var(--space-4);margin-top:var(--space-8)}
  .card{padding:var(--space-6)}
  .card__text{padding:var(--space-6)}

  /* One column, so the tall photo stops spanning and each image states its own
     ratio instead of inheriting a fixed row height. */
  .life__media{grid-template-columns:1fr;grid-template-rows:auto}
  .life__img{height:auto;aspect-ratio:3 / 2; max-height: 200px;}
  .life__img--tall{grid-row:auto;aspect-ratio:3 / 4}
  .life-list{margin-top:var(--space-7)}
  .life-item{grid-template-columns:32px minmax(0,1fr);column-gap:var(--space-3);padding:var(--space-5) 0}
  .life-item__text{margin-top:var(--space-2)}

  .filters{gap:var(--space-2);margin:var(--space-6) 0 var(--space-1)}
  .filter{padding:8px 14px}
  .role-card{padding:var(--space-6)}

  /* Narrower card and less mask padding: 1.3 of a shorter card needs less room,
     and 48px of air top and bottom is a lot of empty on a phone. */
  /* 48px of margin plus 32px of padding put 80px of nothing between the heading
     and the first card, and that padding is only there to give the 1.15 hover room
     to grow into — which never happens on a touch screen. 32 + 16 brings the gap
     into line with the 32px the card grids use at this width, and keeps enough
     headroom for the tablet case where a pointer does exist. */
  .benefits{margin-top:var(--space-8);padding:var(--space-4) 0}
  .benefit{width:240px;padding:var(--space-6) var(--space-4)}
  /* Same 12/12 corner as the base rule, derived from this breakpoint's own
     padding: 16px left needs −4 to reach 12, 24px top needs −12. Recompute both
     numbers if .benefit's padding moves — they are a delta, not a position. */
  .benefit-icon{width:44px;height:44px;margin-bottom:var(--space-4);transform:translate(-4px,-12px)}
  /* 27 of 44 reproduces the desktop ratio of 32 of 52; the old 20 left the
     glyph noticeably smaller in its chip than on desktop. */
  /* Same proportion as desktop: the glyph takes 43% of the box. */
  .benefit-icon svg{width:19px;height:19px}

  .cta{padding:var(--space-18) var(--space-6);margin:0px var(--space-6) var(--space-8)}
  .cta__lede{margin-top:var(--space-6)}
  .cta__actions{margin-top:var(--space-8);flex-direction:column;align-items:stretch}
  .cta__actions .btn{width:100%}
  /* clamp's 180px floor is wider than a phone; 34vw keeps the numeral inside
     the viewport instead of being clipped mid-digit. */
  .cta__mark{font-size:34vw;bottom:-16px}
}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  .page-nav{transition:none}
  .lift{transition:none}
  .lift:hover{transform:none}
  .cta__img{animation:none}
  /* The benefits marquee is exactly what this media query exists for: motion that
     starts on its own and never stops. Stopping the animation alone is not enough
     — the track would freeze mid-slide with most of the cards behind the mask, so
     the whole thing reverts to the static grid it replaced. The duplicate set has
     to go with it, or the five benefits would read twice. */
  .benefits{overflow:visible;padding:0}
  .benefits__track{animation:none;display:block;width:auto}
  .benefits__set{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:var(--space-3);padding-right:0}
  .benefits__set[aria-hidden="true"]{display:none}
  /* Only the movement goes. The photograph-to-white swap and the note appearing
     are state changes, not motion, so they still happen — just instantly. */
  .benefit,.benefit::before,.benefit::after,.benefit-icon,.benefit-icon svg,.benefit-name,.benefit-note{transition:none}
  .benefit{width:auto}
  .benefit:hover{transform:none}
  .benefit-icon,.benefit-name,.benefit-note{transform:none}
  .benefit:hover .benefit-name,.benefit:hover .benefit-note{transition-delay:0s}
}

/* Mobile: of the three Life images only the middle one stays. Stacked they add
   up to a lot of scrolling before the next section, and all three say the same
   thing — a team at work.

   The one that stays is marked, not the ones that go: add or remove an image
   and the rule still holds.

   display:none and not opacity: all three are loading="lazy", so one that never
   becomes visible is never downloaded either. Mobile saves the two files.

   Note: between 768 and 1023 all three are still stacked, because the
   two-column grid only exists from 1024 up. If the scrolling is too much there
   as well, this block moves up to max-width:1023px. */
@media (max-width:767px){
  .life__img:not(.life__img--primary){display:none}
}

/* ── Orden de secciones en movil ───────────────────────────────────────────
   Why - Roles - Life - Benefits, instead of the DOM's Why - Life - Benefits -
   Roles. The openings move up: they are what most people come for, and on a
   narrow screen they sat three sections of scrolling away.

   Safe with flex because .section carries no vertical margin — the rhythm
   comes from .container's padding — so there are no gaps to double up.

   The DOM order does not change, so the tab order and the reading order of
   un lector de pantalla siguen siendo Why - Life - Benefits - Roles. Para
   independent sections like these that is acceptable; if one depended on the
   previous to make sense, the markup would have to be reordered, not the CSS. */
@media (max-width:767px){
  .page{display:flex; flex-direction:column}
  /* The space above the bar moves from the child to the nav itself. With .page
     in flex the margins no longer collapse outward, so the __inner's margin-top
     would stay inside the nav's box: 136px tall with the first 80
     transparent, and the hero showing through there once it sticks. As a flex
     item margin it is real space and the box measures just the bar again. */
  .page-nav{margin-top:var(--space-20)}
  .page-nav__inner{margin-top:0}
  .page-nav{order:1}
  #hero     {order:2}
  .stats    {order:3}
  #why      {order:4}
  #roles    {order:5}
  #life     {order:6}
  #benefits {order:7}
  .cta      {order:8}

  /* The nav follows suit. It needs display:flex because all of its styling
     lives in min-width:1024 and down here its links are inline anchors. */
  .page-nav__links{display:flex; align-items:center}
  .page-nav__links a[href="#why"]     {order:1}
  .page-nav__links a[href="#roles"]   {order:2}
  .page-nav__links a[href="#life"]    {order:3}
  .page-nav__links a[href="#benefits"]{order:4}
}

/* ── Marquee pause control ──────────────────────────────────────
   Hidden until it takes focus, the way a skip link is. A mouse already pauses
   the band by hovering and a finger by holding, so the keyboard is the only
   modality that was without a mechanism — and the only one that needs a
   control. This way nobody else carries a button they will never press.

   Not display:none, which cannot be focused and so would hide the control from
   the very people it exists for. The clip technique keeps it in the tree and in
   the tab order while taking it out of the picture.

   It reveals over the band rather than pushing it down: the container clips its
   overflow, so a control that appeared in normal flow would shift every card
   the moment someone tabbed to it. */
.marquee-pause{
  position:absolute;
  width:1px; height:1px;
  margin:-1px; padding:0; border:0;
  overflow:hidden;
  clip-path:inset(50%);
  white-space:nowrap;
}
.marquee-pause:focus{
  width:auto; height:auto;
  margin:0;
  clip-path:none;
  top:var(--space-2); left:var(--space-2);
  z-index:3;
  padding:var(--space-2) var(--space-4);
  border-radius:var(--radius-pill);
  background:var(--ink);
  color:var(--white);
  font-family:var(--font-sans);
  font-size:var(--type-xs);
  font-weight:var(--weight-semibold);
  line-height:1;
  cursor:pointer;
  outline:2px solid var(--c-600);
  outline-offset:2px;
}

@media (prefers-reduced-motion:reduce){
  /* The band is a static grid here, so there is no motion to stop and the
     control would be a tab stop that does nothing. */
  .marquee-pause{display:none}
}
.benefits.is-paused .benefits__track{animation-play-state:paused}

/* ---- Scroll reveal ------------------------------------------------------
   Documented in the design system under Motion. The group is what gets
   observed; its children carry the sequence, and the delay is a custom
   property the script sets from each one's position, so nothing here or in the
   markup names a duration.

   The zero default matters: a child the script never reached still transitions
   instead of waiting forever.

   Note there is a second copy of these rules on the page already, inherited
   from the homepage's compiled styles: same 20px, same 0.9s, same curve, but
   no transition-delay, so the stagger would be silently dropped if it won.
   It does not - it sits in an inline <style> near the top of the document and
   this sheet is linked below it, so equal specificity is settled by order.
   Thin ground to stand on, which is why it is written down here. */
.reveal{
  opacity:0;
  transform:translateY(20px);
  transition:opacity var(--reveal-dur, .9s) var(--ease-standard),
             transform var(--reveal-dur, .9s) var(--ease-standard);
  transition-delay:var(--reveal-delay, 0ms);
}
.reveal.in{opacity:1; transform:none}

/* Without the script the class is never added, so the page would be blank
   below the hero. .js is set by an inline script in the head, which means a
   bundle that fails to load cannot hide the content. */
html:not(.js) .reveal{opacity:1; transform:none}

@media (prefers-reduced-motion:reduce){
  .reveal{transition:none; opacity:1; transform:none}
}
