/* ═══════════════════════════════════════════════════════════════
   SECTIONS — every page section's own styling (header, hero, why,
   specialties, hiring-os, industries, expertise, certifications,
   stories, UK-visit, salary calculator, resources, CTA, footer)
   Rebuilt 2026-10-01 — see css/tokens.css header for context.
   ═══════════════════════════════════════════════════════════════ */




  ul{ margin:0; padding:0; list-style:none; }




  h1,h2,h3,h4{ margin:0; font-family:var(--display); letter-spacing:-.01em; }




  p{ margin:0; }





  /* reveal-on-scroll: visible (opacity:1) by DEFAULT — content must never depend on JS to be
     seen. Hiding only activates once JS has (a) wired up the IntersectionObserver and (b)
     double-rAF-confirmed the initial paint, at which point it adds .reveal-armed to <html>. A
     2s watchdog also force-reveals anything not yet revealed, so a slow/failed observer can
     never leave content permanently blank (this exact failure was caught in QA: a full-page
     screenshot rendered whole sections empty because opacity:0 was the pre-JS default). */
  .reveal{ opacity:1; translate:0 0; transition:opacity .7s var(--ease), translate .7s var(--ease); }




  html.reveal-armed .reveal{ opacity:0; translate:0 24px; }




  html.reveal-armed .reveal.is-in{ opacity:1; translate:0 0; }





  /* ---------- buttons ---------- */
  /* Colours measured (see :root); pill radius measured (--bs-border-radius-pill); padding/size
     visually matched to the reference screenshot (button internals are behind a closed shadow root). */
  .btn{
    position:relative; overflow:hidden;
    display:inline-flex; align-items:center; justify-content:center; gap:.5rem;
    padding:.85rem 1.7rem; border-radius:var(--radius-pill); font-weight:700; font-size:.9375rem;
    border:1.5px solid transparent; transition:background .2s var(--ease), border-color .2s, box-shadow .2s, transform .2s;
    white-space:nowrap;
  }




  /* sheen sweep on the solid CTAs (bug report: "not interactive") — a light diagonal highlight
     that crosses the button on hover, on top of the existing colour-shift + press states */
  /* z-index intentionally omitted: ::before is inserted before the button's real text/icon
     content, so with equal (auto) stacking it paints underneath that content automatically —
     no need to wrap the label in a span just to re-layer it above the sheen. */
  .btn--brand::before, .btn--teal::before{
    content:''; position:absolute; inset:0;
    background:linear-gradient(115deg, transparent 30%, rgba(255,255,255,.35) 45%, transparent 60%);
    transform:translateX(-120%); transition:transform .6s var(--ease);
  }





  /* redesigned from plain small-caps text into a pill badge (bug report: "important section &
     content are not highlighted") — every section now opens with a visibly distinct marker
     instead of copy that blended into the body text colour scale.
     Enlarged + given a hover state (bug report: "Make Section Title large & update the design
     and placement... so it looks professional... when we hover on this title then they should
     be highlighted with different color. Make all title's design, font, size same for all
     section" — the seven titles named: Our comprehensive expertise, Why Alliance, What We Do,
     Success Stories, Let's Talk, "UK · Local & Global Recruitment", IT Outsource). Those seven
     were three different components before this pass: five used .eyebrow correctly, but the
     hero's "UK · Local & Global Recruitment" badge had its own separate, differently-sized
     .hero__kicker (14px, translucent-glass pill) and "Let's Talk" was a stray <p> instead of
     <span> (harmless here since it isn't inside .sec-head, but still inconsistent with the
     other six). All seven now render from this one rule: .hero__kicker removed entirely, the
     hero badge and "Let's Talk" converted to the same <span class="eyebrow[ eyebrow--on-dark]">
     markup as the other five. */
  .eyebrow{
    display:inline-flex; align-items:center; gap:.55rem; width:fit-content;
    font-weight:700; font-size:.9375rem; letter-spacing:.06em; text-transform:uppercase;
    color:var(--primary); margin-bottom:1.1rem;
    background:var(--bg-secondary); border:1px solid rgba(58,37,156,.14); border-radius:999px;
    padding:.55rem 1.15rem .55rem .85rem;
    transition:color .2s var(--ease), background .2s var(--ease), border-color .2s var(--ease);
  }




  /* bug report: "Title's Background color should be highlighted not Title color. Reduce the
     intensity little bit of hovering effect" — the previous version shifted the text (and dot
     marker) from primary-purple to secondary-blue on hover, which is a colour swap on the title
     itself, not a background highlight. Text and dot now stay exactly as they are at rest; only
     the pill's own fill/border move on hover, and at a more moderate strength (a light tint,
     not a saturated accent colour) than the previous version. */
  .eyebrow:hover{ background:rgba(58,37,156,.1); border-color:rgba(58,37,156,.24); }




  /* #9ACDE7: tint of --secondary (#1E8FC9, measured off the logo wordmark) -> white, 55% — for
     legible contrast on dark surfaces; reused everywhere a light-on-dark accent is needed. */
  .eyebrow--on-dark{ color:#fff; background:rgba(255,255,255,.1); border-color:rgba(255,255,255,.22); }





  /* ================= HEADER ================= */
  /* white sticky bar — measured: no dark header anywhere in the reference DOM */
  .site-header{
    position:sticky; top:0; z-index:100; background:rgba(255,255,255,.97);
    backdrop-filter:blur(8px); border-bottom:1px solid transparent;
    transition:box-shadow .25s var(--ease), border-color .25s;
  }




  .site-header.is-scrolled{ box-shadow:0 4px 20px rgba(26,17,70,.08); border-bottom-color:var(--border); }





  /* fix (bug report: header title/links not properly aligned): nav links were wrapping onto a
     second line at ordinary desktop widths because flex items shrink and reflow text by default;
     `flex:1` on .nav__links also let gaps balloon unevenly. Nav links now size to their natural
     content width and never wrap; .nav__right carries the auto-margin that pins it to the edge,
     so the row reads logo — links — [space] — phone/CTAs, evenly, at any width above the
     mobile breakpoint. */
  /* max-width raised past the sitewide .wrap cap (1240px), specifically and permanently for the
     header: merging the utility links into .nav__right (per explicit ask: "place with Post a
     Vacancy & Hire Talent if professional") needs real room for 5 groups — 2 utility links, phone,
     2 buttons — measured at 1424px required vs 1240px available before touching this value. Unlike
     the earlier attempt, this isn't paired with any viewport-width hide: the row is simply wider
     at every desktop size, and collapses to the burger menu at the existing 1020px breakpoint like
     the rest of the nav. A header row spanning wider than the page's content cap is a common,
     legitimate pattern (the nav owns its own layout), not a hack — confirmed it still reads as
     one clean aligned bar, not two competing widths, via screenshot.
     1460 -> 1530 (spacing/responsive audit, this pass): adding the "Meet Us" link (for the UK
     Visit section) in a later pass pushed natural content width from ~1424px to 1521px without
     this value being revisited, which silently reintroduced the exact overflow this comment
     describes fixing — confirmed via nav.scrollWidth (1521) vs clientWidth (1460) at 1440-1550px
     viewports, a real 60px clip, not a guess. Raised the cap again by the same measure-first
     approach rather than shrinking gaps to compensate, which started to look visibly cramped
     before it even closed the gap. Burger breakpoint (1300px, below) still collapses to mobile
     well before this width, so nothing here affects any viewport under 1300px. */
  /* ARAUK-3: 1530 -> 1700. Same measure-first pattern as the two prior bumps logged above: the
     mega-menu rebuild lengthened several trigger labels ("Services"->"Recruitment Solutions",
     "Sectors"->"Industries", plus the new "Insights & Resources" + "Soon" badge and promoting
     "Job Seekers" out of the old micro-link row into a full nav__links item) even after removing
     the old nav__utility row entirely. Measured nav.scrollWidth (1656-1680 depending on viewport,
     clamp() gaps near their max) vs the old 1530 cap -- a real ~130-150px clip, not a guess.
     Burger breakpoint (1540px, responsive.css) still collapses to mobile below this width, so
     nothing here affects any viewport under 1540px; raised above the new breakpoint too (next
     comment). */
  /* 1700 -> 1800 (client feedback 2026-10-21, bolder/larger nav font -- see .nav__links a comment
     below and responsive.css's matching 1699->1799 compact-tier comment for the measurements).
     This cap only bounds how wide the row grows on very wide screens; it was raised to stay paired
     with the new compact-tier threshold rather than leaving it narrower than the row's own new
     natural content width. */
  .nav{ display:flex; align-items:center; gap:clamp(1.25rem,2.8vw,2.75rem); padding-block:.9rem; max-width:1800px; }




  .nav__logo{ flex-shrink:0; display:flex; align-items:center; }




  .nav__logo img{ height:36px; width:auto; display:block; }




  .nav__links{ display:flex; align-items:center; gap:clamp(1.1rem,1.7vw,1.85rem); flex-shrink:0; }




  /* client feedback 2026-10-21 (Reed.co.uk reference screenshot): links read too thin/small vs a
     reference nav with a bolder, larger typeface and less empty-looking space between items.
     .9rem/600 -> 1rem/700. Font-size change shifts the nav's real content width, so every
     breakpoint tuned earlier today (1699/1365/1179px, responsive.css) was re-measured against this
     new size the same way as always -- nav.scrollWidth vs clientWidth, cap removed, swept across
     each tier -- before shipping; see responsive.css's own breakpoint comment for the result. */
  .nav__links a{
    font-size:1rem; font-weight:700; color:var(--ink); position:relative; padding:.3rem 0;
    display:flex; align-items:center; gap:.3rem; white-space:nowrap; flex-shrink:0; line-height:1;
  }




  .nav__links a::after{
    content:''; position:absolute; left:0; right:100%; bottom:-2px; height:2px; background:var(--primary);
    transition:right .25s var(--ease);
  }




  .nav__links a:hover{ color:var(--primary); }




  .nav__links a:hover::after{ right:0; }




  .nav__links a.is-active{ color:var(--primary); }




  .nav__links a.is-active::after{ right:0; }




  .nav__links svg{ width:10px; height:10px; opacity:.6; }




  .has-drop{ position:relative; }




  .drop{
    position:absolute; top:calc(100% + 14px); left:50%; transform:translateX(-50%);
    background:#fff; border:1px solid var(--border); border-radius:var(--radius-sm); box-shadow:0 20px 50px rgba(26,17,70,.14);
    padding:.6rem; min-width:250px; opacity:0; visibility:hidden; translate:0 8px;
    transition:opacity .2s var(--ease), translate .2s var(--ease), visibility .2s;
  }




  .has-drop:hover .drop, .has-drop:focus-within .drop{ opacity:1; visibility:visible; translate:0 0; }




  .drop a::after{ display:none; }




  .drop a{ display:block; padding:.6rem .8rem; border-radius:8px; font-weight:500; font-size:.875rem; }




  .drop a:hover{ background:var(--bg-secondary); color:var(--secondary); }




  /* ARAUK-3: mega-panel variant for the Recruitment Solutions (7) / Industries (8) dropdowns —
     a single column at that length runs taller than the viewport on some laptops; 2 columns keeps
     every item visible without scrolling, same hover/trigger mechanics as .drop.
     Left-anchored, not centered (client bug report 2026-10-21, screenshot of Recruitment Solutions'
     left column cut off at the viewport edge): .drop's base rule centers the panel under its trigger
     (left:50%; translateX(-50%)), which this file's own 1179-1365px "deep-compact" nav tier (added
     earlier the same day) made unsafe -- it tightens the gaps before Recruitment Solutions, the
     leftmost trigger, so its centered 460px panel's left edge goes negative (measured: -23px at
     1180px viewport). Anchoring the panel's left edge to the trigger's left edge instead removes the
     centering math entirely, so it can never extend further left than the trigger itself -- verified
     with getBoundingClientRect() at 1180/1366/1440/1800px for both mega triggers: left edge never
     negative, right edge never exceeds the viewport (460px plus the trigger's own position always
     left room on the right at every one of these widths, since both triggers sit in the left half of
     the nav row). */
  .drop--mega{ min-width:460px; left:0; transform:none; display:grid; grid-template-columns:repeat(2,1fr); gap:.1rem .5rem; }




  /* ARAUK-46: "View All Industries" footer row inside the Industries mega-dropdown — the real
     dedicated industries.html hub (16 industry pages, shipped ARAUK-38) wasn't linked from the
     header anywhere before this; the existing 8 category items are untouched (pre-existing,
     out of scope for this ticket). Spans both grid columns, divider-style so it reads as a
     distinct "see everything" row, not a 9th category. Reused unchanged by ARAUK-78 for the
     Recruitment Solutions dropdown's own new "View All Solutions" row. */
  .drop a.drop__view-all{
    grid-column:1 / -1; margin-top:.3rem; padding-top:.7rem; border-top:1px solid var(--border);
    font-weight:700; color:var(--secondary);
  }




  /* ARAUK-3's "Insights & Resources" non-clickable "Soon" preview (.nav__soon-trigger,
     .nav__soon-badge, .drop__soon-item, .drop__soon-note) is removed here. ARAUK-75 already
     wired this link to the new real blog listing site-wide but left this CSS orphaned; ARAUK-78
     (2026-11-03) turns it into a real working dropdown (Blog + About Us) using the ordinary
     .has-drop/.drop/.drop a rules already above, and removes the dead CSS with it. */




  .nav__right{ display:flex; align-items:center; gap:1rem; flex-shrink:0; margin-left:auto; }




  /* ARAUK-3: .nav__utility (Job Seekers / Franchise Inquiry micro-link row) removed — Job Seekers
     is now a full top-level nav__links item per the approved taxonomy; Franchise Inquiry isn't in
     that taxonomy and was dropped from the header (its #contact destination is still reachable via
     Contact Us). Dead CSS removed with it rather than left orphaned. */




  .nav__utility a:hover{ color:var(--primary); }




  /* ARAUK-78: .nav__phone (the plain-text phone link that used to sit in .nav__right) removed
     with its HTML — the new .util-bar above the header (next block) now carries the phone
     number, so this read as a duplicate CTA inside an already-busy nav row. Dead CSS removed
     with it rather than left orphaned, same pattern as the ARAUK-3 .nav__utility removal above. */




  /* ================= UTILITY BAR (ARAUK-78, 2026-11-03) =================
     Owner's direct chat request, with a reference screenshot: a thin strip above the main
     header carrying a UK flag + phone number + a divider + social icons. Built fresh with this
     site's own tokens (--secondary for the top accent border, --bg-secondary for the fill) —
     NOT the orphaned rp-topbar clone in css/job-seekers-header.css, which was a literal copy of
     the live production site's header built in an earlier session and then explicitly
     superseded because the team wanted this site to keep its own header design. */
  .util-bar{
    background:var(--bg-secondary); border-bottom:1px solid var(--border);
    border-top:2px solid var(--secondary);
  }
  .util-bar__inner{
    display:flex; align-items:center; gap:.9rem; padding-block:.4rem; min-height:0;
  }
  .util-bar__phone{
    display:flex; align-items:center; gap:.4rem; font-weight:700; font-size:.8125rem; color:var(--ink);
  }
  .util-bar__phone:hover{ color:var(--secondary); }
  .util-bar__phone svg{ width:13px; height:13px; color:var(--secondary); flex-shrink:0; }
  .util-bar__flag{ font-size:.95rem; line-height:1; }
  .util-bar__divider{ width:1px; height:14px; background:var(--border); flex-shrink:0; }
  .util-bar__social{ display:flex; align-items:center; gap:.65rem; margin-left:auto; }
  .util-bar__social a{
    display:flex; align-items:center; justify-content:center; width:24px; height:24px;
    border-radius:50%; color:var(--ink-tertiary); transition:color .2s, background .2s;
  }
  .util-bar__social a:hover{ color:#fff; background:var(--secondary); }
  .util-bar__social svg{ width:12px; height:12px; }
  @media (max-width:640px){
    .util-bar__social{ display:none; }
    .util-bar__inner{ justify-content:center; }
  }




  .nav__burger{
    display:none; width:40px; height:40px; align-items:center; justify-content:center;
    border-radius:8px; border:1px solid var(--border); flex-shrink:0;
  }




  .nav__burger span{ display:block; width:18px; height:1.6px; background:var(--ink); position:relative; transition:background .2s; }




  .nav__burger span::before,.nav__burger span::after{
    content:''; position:absolute; left:0; width:18px; height:1.6px; background:var(--ink);
    transition:transform .25s var(--ease), top .25s var(--ease);
  }




  .nav__burger span::before{ top:-6px; }




  .nav__burger span::after{ top:6px; }




  .nav__burger[aria-expanded="true"] span{ background:transparent; }




  .nav__burger[aria-expanded="true"] span::before{ top:0; transform:rotate(45deg); }




  .nav__burger[aria-expanded="true"] span::after{ top:0; transform:rotate(-45deg); }





  .mob-panel{
    display:none; border-top:1px solid var(--border); background:#fff;
    max-height:0; overflow:hidden; transition:max-height .3s var(--ease);
  }




  .mob-panel.is-open{ max-height:80vh; overflow-y:auto; }




  .mob-panel__inner{ padding:1.25rem clamp(1.25rem,4vw,2.5rem) 1.75rem; display:flex; flex-direction:column; gap:.25rem; }




  .mob-panel a{ padding:.85rem 0; border-bottom:1px solid var(--border); font-weight:600; font-size:.95rem; }




  /* ARAUK-3's .mob-panel__soon (mobile-panel equivalent of the old "Soon" preview) is removed
     here — ARAUK-78 replaced it with a real "Blog" link, styled by the ordinary .mob-panel a
     rule already above. Dead CSS removed with its HTML. */




  .mob-panel .btn{ margin-top:1rem; }





  /* ================= HERO ================= */
  /* Rebuilt again as a full-bleed photo + scrim (roberthalf.com's actual pattern), replacing the
     split-panel layout from the previous pass. That split was a genuine fix for a real alignment
     bug at the time (see git history), but the user asked explicitly for RH's hero look, and RH's
     is a single full-width photo with a dark scrim the text sits on top of — not a hard two-column
     seam. Measured the reference honestly before rebuilding: extract_design.py on the hero host
     element (`rhcl-block-full-width-hero`) came back with no background of its own — the photo is
     painted inside a closed shadow root, unreachable by any selector-based tool (same wall hit on
     the CTA buttons in an earlier pass). Fell back to sampling RH's own screenshot
     (files/qa/2026-09-28-roberthalf-ref/roberthalf-full.png) point-by-point along two horizontal
     rows instead: the scrim is fully opaque from the left edge to ~45% of the hero's width, then
     transitions through ~90%, and is STILL a medium-dark grey even at 90% — never fully clears to
     bright photo. That's a much heavier, later reveal than a typical "diagonal gradient" hero, and
     is why the scrim below is opaque for so much longer than it might look like it needs to be. */
  .hero{
    position:relative; overflow:hidden; min-height:min(88vh,720px);
    display:flex; align-items:center; color:#fff; background:var(--surface-dark); padding-block:0;
  }




  .hero__img{
    position:absolute; inset:0; width:100%; height:100%; object-fit:cover; object-position:66% 30%;
  }




  .hero__scrim{
    position:absolute; inset:0;
    /* stops placed at the measured breakpoints (opaque to ~45%, transition to ~90%, never fully
       clear) using --surface-dark's own rgb triple so the scrim reads as Alliance's brand colour */
    background:
      linear-gradient(100deg,
        rgba(var(--surface-dark-rgb),.97) 0%,
        rgba(var(--surface-dark-rgb),.95) 45%,
        rgba(var(--surface-dark-rgb),.62) 68%,
        rgba(var(--surface-dark-rgb),.34) 90%,
        rgba(var(--surface-dark-rgb),.4) 100%),
      linear-gradient(0deg, rgba(var(--surface-dark-rgb),.5) 0%, rgba(var(--surface-dark-rgb),0) 32%);
  }




  /* fix (bug report: "content is in centre, move to left side"): .hero__content shares its
     element with .wrap, which sets `margin-inline:auto` for the page's normal centred containers.
     .hero is a flex row with this as its only child, and a flex item's auto margins absorb all
     free space before `justify-content` ever applies — so even though `justify-content` defaults
     to flex-start, the auto margins were splitting the leftover width evenly on both sides and
     visually centring the whole text block instead of pinning it to the left edge. Zeroing the
     inline margins here (padding-inline from .wrap is kept, so the left gutter still lines up
     with the header logo above it) removes that centring without touching `.wrap` globally. */
  /* positioned between the left edge and true centre (bug report: "content... between left &
     centre side"): the previous pass zeroed the inline margin to kill an auto-margin centring
     bug, which correctly pinned it flush-left — this pushes it back off the edge by a responsive
     amount (clamp, not a fixed px) without reintroducing the old auto-margin centring, so it
     still stays left of the photo's midpoint at every viewport width rather than snapping to 50%. */
  /* content column widened + repositioned against a reference screenshot the user attached
     (files/chat-uploads/chat-ceae2d05545b.png, a clean 1920x1080 capture of roberthalf.com/us/en
     with no cookie-banner obstruction) — sampled with design-clone/tools/sample_image.py rather
     than eyeballed. Point-sampled the page/chrome boundary (browser chrome ends, page starts, at
     y=108) then the headline's left text edge: white glyph pixels first appear at x=165 of the
     1920px-wide image, i.e. 8.6% of viewport width — this file's previous 7rem (112px) cap at
     1920px was noticeably tighter than that. Also sampled the headline's own text row: "Anything's
     possible" runs a wide, confident column (glyphs still present well past x=900) — this file's
     old `max-width:11ch` on the h1 forced an artificially narrow 3-line wrap unrelated to that
     proportion, so it's removed below in favour of the wider container. */
  .hero__content{
    position:relative; z-index:2; max-width:760px; margin-inline:0;
    padding-block:clamp(3.5rem,10vh,6rem); padding-left:clamp(1rem,8.6vw,11rem);
  }




  /* .hero__kicker removed: "UK · Local & Global Recruitment" now uses the shared
     .eyebrow.eyebrow--on-dark component (see its definition above) instead of its own
     separate, differently-sized pill, per "make all title's design, font, size same for all
     section" — it just needed margin-bottom to match the hero's own spacing rhythm. */
  .hero__content .eyebrow{ margin-bottom:1.5rem; }




  .hero h1{
    /* size/line-height kept from the roberthalf.com measurement (68px / 1.2). Weight bumped from
       300 to 700 (Sora, not RH's unavailable licensed face) — user feedback: the light weight
       read as thin/flat rather than confident on a lead-gen hero. Copy is Alliance's own real,
       short headline ("Most trusted recruitment agency" — verbatim from their homepage). */
    font-size:clamp(2.4rem,3.6vw,4rem); line-height:1.1; font-weight:700;
    text-align:left; margin-bottom:0;
  }




  .hero h1 b{ font-weight:800; color:#fff; }




  /* was 1.1875rem — bumped for "increase the font of details in hero section" */
  .hero__sub{ font-size:1.375rem; line-height:1.55; color:rgba(255,255,255,.86); max-width:32rem; margin-top:1.5rem; margin-bottom:2.3rem; font-weight:400; }




  /* margin-bottom removed: .hero__ctas is now the last element in .hero__content, since the
     "Looking for a job instead?" link below it was removed (bug report: "Remove Looking for a
     job instead? See open roles"). .hero__seeker's own rules removed too -- nothing on the page
     uses that class any more. */
  .hero__ctas{ display:flex; flex-wrap:wrap; gap:1rem; align-items:center; }





  /* ================= SECTION CONNECTORS (seam) ================= */
  /* Fix for "sections feel disconnected / too much dead space": every region below carries a
     slim brand-gradient seam at its top edge, so the page reads as one stitched sequence
     instead of flat colour blocks separated by blank gaps.
     Bug report (this pass): "remove background color of cursor when we hover to any section.
     Make it standard cursor" -- removed both hover-triggered background-colour effects that had
     accumulated across several passes: the page-wide cursor-tracked glow (a fixed full-viewport
     layer following the pointer) and .section-tint (a flat per-section highlight-on-hover).
     Neither exists any more, in CSS, HTML or JS -- hovering a section now does nothing to its
     background, and the pointer itself was never overridden to a custom icon in the first place
     (checked: only ordinary `cursor:pointer` on real buttons/links, which is correct and
     untouched). The static top seam stays -- it's not a hover effect, just a permanent divider. */
  .glow-region{ position:relative; overflow:hidden; }







  /* ================= SECTION SHELL ================= */
  /* tightened page-wide (bug report: "use space very little on page") — was clamp(3.25rem,6vw,5.25rem) */
  section{ padding-block:clamp(2.5rem,4.5vw,4rem); }




  .sec-head{ text-align:center; max-width:640px; margin-inline:auto; margin-bottom:clamp(1.5rem,3vw,2rem); position:relative; z-index:1; }




  .sec-head .eyebrow{ justify-content:center; }




  .sec-head h2{
    /* bug report (this pass): "Header title of each section make small compare to current size
       so each section will look perfect with minimum scrolling" — the previous pass's 68px/800
       treatment (see the size history in the comment this replaces) made each section taller
       than it needed to be. Pulled back well below even the ORIGINAL 56px roberthalf.com-
       measured baseline, to a deliberately compact max of 40px, while keeping the bold weight
       and tight letter-spacing/line-height from the last pass so it still reads as a confident
       display heading rather than body text that just got bigger — "smaller" and "still
       professional" both apply here, not smaller-and-plain. .sec-head's max-width pulled back
       680px -> 640px and its own bottom margin tightened to match, since a smaller heading no
       longer needs the wider column the 68px version was given room to wrap in. */
    font-size:clamp(1.5rem,2.4vw,2.5rem); line-height:1.15; font-weight:800; letter-spacing:-.015em; color:var(--ink);
  }




  /* running chapter numbers on the remaining main content sections — "identify each & every
     part" at a glance while scrolling. #reach ("Where We Place Talent") was removed from this
     page in a later pass, dropped from this list accordingly — the sequence renumbers itself
     to stay contiguous (01/02/03) rather than skip the missing first number. */
  .sec-head p{ margin-top:1rem; font-size:1.0625rem; color:var(--ink-secondary); line-height:1.65; }





  .carousel-nav{ display:flex; align-items:center; gap:1rem; justify-content:center; margin-top:2.5rem; }




  .carousel-nav button{
    width:42px; height:42px; border-radius:50%; border:1.5px solid var(--border); background:#fff;
    display:flex; align-items:center; justify-content:center; transition:border-color .2s,background .2s;
    color:var(--link); /* measured: actions-floating-action-label */
  }




  .carousel-nav button:hover:not(:disabled){ border-color:var(--link); background:var(--bg-secondary); }




  .carousel-nav button:disabled{ opacity:.35; cursor:not-allowed; }




  .carousel-nav svg{ width:16px; height:16px; }




  .carousel-dots{ display:flex; gap:.45rem; }




  .carousel-dots button{ width:7px; height:7px; border-radius:50%; background:var(--border); padding:0; transition:background .2s, width .2s; }




  .carousel-dots button.is-active{ background:var(--primary); width:20px; border-radius:4px; }





  /* ---- reach cards (carousel) ---- */
  .reach{ background:var(--bg-primary); }




  .reach__track{
    display:flex; gap:1.5rem; overflow-x:auto; scroll-snap-type:x mandatory; padding-bottom:.5rem;
    scrollbar-width:none;
  }




  .reach__track::-webkit-scrollbar{ display:none; }




  .reach__card{
    scroll-snap-align:start; flex:0 0 min(340px,84vw); border-radius:var(--radius-lg); overflow:hidden;
    border:1px solid var(--border); background:#fff; transition:box-shadow .3s var(--ease), translate .3s var(--ease);
  }




  .reach__card:hover{ box-shadow:0 24px 48px rgba(26,17,70,.12); translate:0 -4px; }




  .reach__art{
    height:188px; position:relative; display:flex; align-items:center; justify-content:center;
    background:var(--surface-dark); overflow:hidden;
  }




  /* fix (bug report: "artifacts on image... make image more appealing"): two real problems here.
     (1) the giant translucent step numeral was absolutely positioned over the photo's bottom-right
     corner, where it collided with actual photo content (a person's shoulder) and read as a
     rendering glitch rather than a number — moved to a small, deliberate label in the card body
     instead (see .reach__step below), nowhere near the photo. (2) `mix-blend-mode:multiply` at
     .86 opacity plus a grayscale filter was darkening and muddying the photos rather than tinting
     them — multiply can only ever darken, so on top of an already-moody interior photo it crushed
     the shadows toward black. Switched to `mix-blend-mode:color`, which recolours the photo's hue
     while preserving its own luminance/detail — the standard technique for a vivid brand-tinted
     "duotone" look instead of a flattened dark one — and dropped the grayscale filter so the
     photos keep their natural colour and warmth. */
  .reach__art-img{
    position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
    filter:saturate(1.08) contrast(1.03);
  }




  .reach__art::before{
    content:''; position:absolute; inset:0; mix-blend-mode:color; opacity:.65;
    background:linear-gradient(145deg, var(--primary) 0%, var(--secondary) 100%);
  }




  .reach__art::after{
    content:''; position:absolute; inset:0;
    background:
      linear-gradient(0deg, rgba(var(--surface-dark-rgb),.45) 0%, transparent 48%),
      radial-gradient(circle at 82% 12%, rgba(255,255,255,.24), transparent 55%);
  }




  /* replaces the old .reach__num overlay — a small step label in the card body, in the same
     "— 0N" numbering language already used on the section eyebrows elsewhere on the page. The
     icon badge (.reach__art-badge — a location pin / globe / star over each photo) was removed
     per bug report: "remove star, global & location symbol from the image", so .reach__art no
     longer needs an svg-sizing rule either. */
  .reach__step{
    display:block; font-weight:700; font-size:.8125rem; letter-spacing:.08em; color:var(--link);
    margin-bottom:.5rem;
  }




  .reach__body{ padding:1.6rem 1.6rem 1.8rem; }




  .reach__body h3{ font-size:1.15rem; font-weight:600; color:var(--ink); margin-bottom:.6rem; }




  .reach__body p{ font-size:.9375rem; color:var(--ink-secondary); line-height:1.6; margin-bottom:1rem; }




  .reach__link{ font-size:.8125rem; font-weight:700; color:var(--link); display:inline-flex; align-items:center; gap:.35rem; }




  .reach__link svg{ width:12px; height:12px; transition:translate .2s; }




  .reach__link:hover{ color:var(--secondary); }




  .reach__link:hover svg{ translate:3px 0; }





  /* ================= INDUSTRIES WE SERVE =================
     Renamed and recontented from "Our Recruitment Specialisms" (bug report: "change the section
     to Industries We Serve... show different industry names instead of solutions... industries
     we are servings with details instead of recruitment profiles").
     The previous section already established (Pass 15 memory) that Alliance's live site has no
     dedicated "industries by sector" page. Checked again for THIS pass specifically, since the
     ask is now explicitly about industries rather than services: alliancerecruitmentagency.co.uk
     doesn't have a sectors landing page, but it DOES have several of its own published blog posts
     that each name real industries Alliance discusses recruiting for, with real supporting detail
     -- fetched four of them (recruitment-services-uk-for-high-demand-industries-2026,
     top-industries-hiring-leeds-2026, industries-driving-permanent-staffing-manchester, and
     cross-checked against industry-specific-recruitment-services-uk-what-employers-should-know)
     and combined the eight distinct named industries that appear consistently across them:
     Technology & IT, Finance & Professional Services, Healthcare & Life Sciences, Engineering &
     Manufacturing, Construction & Real Estate, Logistics & Supply Chain, Education & Training,
     Retail & E-commerce. Each card's description and example roles are drawn from that same
     published content (roles from the posts' own "Top Paying Jobs" lists where given, or the
     specific role-types named in the surrounding text where they weren't) -- copy-edited for
     grammar/flow only, no claim invented that Alliance's own blog doesn't already make.
     Layout: a full-width intro/stat banner (.industry-banner, not part of the card grid's column
     system, so the grid itself stays a clean, evenly-divisible 4-column x 2-row for exactly 8
     cards -- no spanning-tile remainder math this time) followed by the 8 industry cards. Same
     "highlighted" card treatment (gradient icon badge, top accent bar) carried over from the
     previous version of this section for visual consistency with the rest of the page. */
  #industries .eyebrow::after{ content:none; }




  .industry-banner{
    position:relative; overflow:hidden; border-radius:var(--radius-lg);
    background:linear-gradient(150deg, var(--surface-dark) 0%, var(--primary) 130%);
    padding:1.75rem 2rem; margin-bottom:1.1rem;
    display:flex; align-items:center; justify-content:space-between; gap:1.5rem; flex-wrap:wrap;
  }




  .industry-banner::before{
    content:''; position:absolute; inset:0; opacity:.5; pointer-events:none;
    background:radial-gradient(480px circle at 90% 15%, rgba(154,205,231,.32), transparent 70%);
  }




  .industry-banner__text{ position:relative; color:#fff; }




  .industry-banner__text b{
    display:block; font-family:var(--display); font-weight:800; font-size:clamp(1.375rem,2.2vw,1.75rem);
  }




  .industry-banner__text span{ display:block; color:rgba(255,255,255,.78); font-size:.9375rem; margin-top:.35rem; }




  .industry-banner .btn{ position:relative; flex-shrink:0; }




  .industry-grid{ display:grid; grid-template-columns:repeat(4,1fr); gap:1.1rem; }




  .industry-card{
    position:relative; overflow:hidden;
    background:linear-gradient(160deg, var(--bg-primary) 0%, #fff 55%);
    border:1px solid var(--border); border-radius:var(--radius-lg);
    padding:1.4rem; transition:box-shadow .25s var(--ease), translate .25s var(--ease), border-color .25s var(--ease);
  }




  .industry-card::before{
    content:''; position:absolute; top:0; left:0; right:0; height:4px;
    background:linear-gradient(90deg, var(--primary), var(--secondary));
  }




  .industry-card:hover{ box-shadow:0 20px 40px rgba(58,37,156,.14); translate:0 -4px; border-color:rgba(58,37,156,.28); }




  .industry-card__icon{
    width:44px; height:44px; border-radius:13px; display:flex; align-items:center; justify-content:center;
    background:linear-gradient(145deg, var(--primary) 0%, var(--secondary) 100%);
    box-shadow:0 10px 20px -4px rgba(58,37,156,.4); margin-bottom:.9rem;
  }




  .industry-card__icon svg{ width:19px; height:19px; color:#fff; }




  .industry-card h3{ font-size:1rem; font-weight:700; color:var(--ink); font-family:var(--display); line-height:1.3; }




  .industry-card p{ font-size:.8125rem; color:var(--ink-secondary); line-height:1.55; margin-top:.5rem; }




  .industry-card__roles{ display:flex; flex-wrap:wrap; gap:.4rem; margin-top:.9rem; }




  .industry-card__roles span{
    font-size:.6875rem; font-weight:600; color:var(--ink-tertiary); background:var(--bg-secondary);
    padding:.3rem .55rem; border-radius:var(--radius-pill); border:1px solid var(--border);
  }




  /* bug report: "add 'Find more details' in every block of Industries We Serve section" */
  .industry-card__link{
    font-weight:700; font-size:.8125rem; color:var(--primary); display:inline-flex; gap:.4rem;
    align-items:center; margin-top:1.1rem;
  }




  .industry-card__link svg{ width:12px; height:12px; transition:translate .2s; }




  .industry-card__link:hover{ color:var(--secondary); }




  .industry-card__link:hover svg{ translate:3px 0; }





  /* ================= WHY ALLIANCE ================= */
  .why{ background:var(--white); }




  /* .why__grid / .why__heading h2 / .why__heading p removed: the heading now uses the shared
     .sec-head/.sec-head h2/.sec-head p rules like every other section (universal header style),
     instead of its own left-aligned two-column layout. .stats is a full-width row now that it's
     no longer sharing a grid row with the heading column. */
  .stats{ display:grid; grid-template-columns:repeat(4,1fr); gap:1.25rem; padding-top:.4rem; }




  /* card-ified (was a bare border-left rule) so every stat reads as its own distinct, hoverable
     unit — "content placed so we can identify each part" — consistent with the reach/story cards */
  .stat{
    border:1px solid var(--border); border-left:3px solid var(--primary); border-radius:14px;
    padding:1.25rem 1.4rem; background:#fff;
    transition:box-shadow .25s var(--ease), translate .25s var(--ease), border-color .25s var(--ease);
  }




  .stat:hover{ box-shadow:0 16px 32px rgba(58,37,156,.12); translate:0 -3px; border-color:rgba(58,37,156,.3); }




  .stat strong{
    /* bug report: "important content not highlighted" — stat numbers were 600-weight solid
       indigo at a modest size; these are the single most persuasive proof points on the page
       and deserve to read as the section's focal point, not blend into the surrounding card
       text. Bumped weight, size, and added a two-tone gradient fill (measured colour pair
       --primary/--secondary, not a new hue) so each number reads as a headline. */
    display:block; font-family:var(--display); font-weight:800; font-size:clamp(2.5rem,4.2vw,3.25rem); line-height:1.05;
    letter-spacing:-.02em;
    background:linear-gradient(120deg, var(--primary), var(--secondary));
    -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent; color:var(--primary);
  }




  .stat span{ display:block; margin-top:.65rem; font-size:.875rem; color:var(--ink-secondary); line-height:1.5; }





  .why__pillars{
    margin-top:clamp(2.25rem,4.5vw,3.5rem); display:grid; grid-template-columns:repeat(3,1fr); gap:1.5rem;
    padding-top:clamp(2.25rem,4.5vw,3.5rem); border-top:1px solid var(--border);
  }




  /* redesigned (bug report: "use proper artifacts or section to highlight" these three) — they
     were plain white cards with a pale flat-tint icon, easy to skim past. Now: a brand-gradient
     top accent bar marks each as a distinct highlighted unit, the background carries a faint
     gradient wash instead of flat white, the icon sits in a solid gradient badge (white icon on
     primary->secondary, not a pale tint) so it reads as a deliberate feature marker, and a
     numbered label ("01/02/03") matches the same "— 0N" language already used on the reach cards
     and section eyebrows elsewhere on the page — one consistent highlight system, not a one-off. */
  .pillar{
    position:relative; overflow:hidden; padding:1.8rem 1.7rem;
    border:1px solid var(--border); border-radius:var(--radius-lg);
    background:linear-gradient(160deg, var(--bg-primary) 0%, #fff 55%);
    transition:box-shadow .25s var(--ease), translate .25s var(--ease), border-color .25s var(--ease);
  }




  .pillar::before{
    content:''; position:absolute; top:0; left:0; right:0; height:4px;
    background:linear-gradient(90deg, var(--primary), var(--secondary));
  }




  .pillar:hover{ box-shadow:0 20px 40px rgba(58,37,156,.14); translate:0 -4px; border-color:rgba(58,37,156,.28); }




  .pillar__top{ display:flex; align-items:flex-start; justify-content:space-between; margin-bottom:1.3rem; }




  .pillar__icon{
    width:52px; height:52px; border-radius:14px;
    background:linear-gradient(145deg, var(--primary) 0%, var(--secondary) 100%);
    display:flex; align-items:center; justify-content:center;
    box-shadow:0 10px 22px -4px rgba(58,37,156,.45);
  }




  .pillar__icon svg{ width:23px; height:23px; color:#fff; }




  .pillar__step{ font-weight:700; font-size:.8125rem; letter-spacing:.08em; color:var(--ink-tertiary); }




  .pillar h3{
    /* size/weight kept from the original roberthalf.com measurement (22px/27.5px, SemiBold);
       colour is var(--ink), now a logo-derived shade — see :root — not RH's #151A1E. */
    font-size:1.375rem; font-weight:600; color:var(--ink); margin-bottom:.55rem;
  }




  .pillar p{ font-size:.9375rem; color:var(--ink-secondary); line-height:1.6; }





  /* ================= SPECIALTIES (tabs) ================= */
  .specialties{ background:var(--bg-secondary); }




  .tabbar{
    display:flex; gap:clamp(1.25rem,3vw,2.25rem); overflow-x:auto; border-bottom:1px solid var(--border);
    margin-bottom:clamp(2.5rem,5vw,3.5rem); scrollbar-width:none;
  }




  .tabbar::-webkit-scrollbar{ display:none; }




  .tab{
    padding:.9rem .1rem 1.1rem; font-weight:700; font-size:.9375rem;
    color:var(--ink-tertiary); white-space:nowrap; border-bottom:2.5px solid transparent; margin-bottom:-1px;
    transition:color .2s;
  }




  .tab:hover{ color:var(--ink); }




  .tab[aria-selected="true"]{ color:var(--primary); border-bottom-color:var(--primary); }





  .tabpanel{ display:none; }




  .tabpanel[data-active]{ display:block; }




  .tabpanel__grid{ display:grid; grid-template-columns:1.05fr .95fr; gap:clamp(2.5rem,6vw,4.5rem); align-items:center; }




  .tabpanel h3{ font-size:1.6rem; font-weight:600; color:var(--ink); margin-bottom:.9rem; }




  .tabpanel__desc{ font-size:1.0625rem; color:var(--ink-secondary); line-height:1.65; margin-bottom:1.8rem; }




  .tabpanel__roles-label{ font-size:.75rem; font-weight:800; letter-spacing:.1em; text-transform:uppercase; color:var(--ink-tertiary); margin-bottom:.9rem; }




  .tabpanel__roles{ display:grid; grid-template-columns:1fr 1fr; gap:.65rem 1.5rem; margin-bottom:1.7rem; }




  .tabpanel__roles li{ font-size:.9375rem; font-weight:600; color:var(--link); position:relative; padding-left:1rem; }




  .tabpanel__roles li::before{ content:'—'; position:absolute; left:0; color:var(--link); opacity:.6; }




  .tabpanel__link{ font-weight:700; font-size:.9375rem; color:var(--primary); display:inline-flex; gap:.4rem; align-items:center; }




  .tabpanel__link:hover{ color:var(--primary-hover); }




  .tabpanel__link svg{ width:13px; height:13px; }





  /* ================= IMAGE QUALITY PASS (this pass) =================
     Full-site image audit per request for "high-quality, crystal-clear, professional
     imagery... not generic stock photography". Reviewed every photo on the page (hero,
     all 5 specialty-tab collages, video thumbnails, blog/resources cards) rather than
     replacing on assumption. Most were already solid from earlier passes -- hero, Temp &
     Contract, RPO and IT tabs, blog cards and video thumbnails all held up. Found exactly
     one real weak spot: a flat, plain-background passport-photo-style headshot (no
     environmental context, stiff lighting) that turned out to be reused in TWO unrelated
     slots -- confirmed via the base64 data itself sharing an identical tail, not just a
     visual guess -- as both the Executive Search tab's main portrait AND the HR
     Consultancy tab's overlap portrait (so the same uncredited "person" was playing two
     different, unrelated roles on the page). Replaced both, with two DIFFERENT people
     this time (not one photo doing double duty): .collage__a in #panel-exec now
     assets/exec-portrait.webp (confident office portrait, real glass-office environment,
     Unsplash, free licence), .collage__b in #panel-hr now assets/hr-portrait.webp (warm,
     modern SME-office portrait with desk/plants in frame, same licence). Both chosen for
     real environmental context and natural lighting rather than flat studio backdrops,
     consistent with the rest of this page's photography. Book-a-meeting / UK Visit
     section (#uk-visit) deliberately left untouched per explicit instruction. ================= */
  .collage{ position:relative; height:clamp(280px,34vw,380px); }




  .collage img{
    position:absolute; border-radius:var(--radius-lg); object-fit:cover;
    box-shadow:0 30px 60px rgba(58,37,156,.18), 0 4px 12px rgba(26,17,70,.08);
  }




  .collage__a{ width:62%; height:88%; top:0; left:0; }




  .collage__b{ width:46%; height:56%; bottom:0; right:0; border:6px solid #fff; }




  .collage__dot{ position:absolute; width:110px; height:110px; border-radius:50%; background:var(--bg-accent); opacity:.16; top:-24px; right:14%; z-index:0; }





  /* ================= STORIES (testimonials) ================= */
  .stories{ background:var(--white); }




  .stories__grid{ display:flex; gap:1.75rem; overflow-x:auto; scroll-snap-type:x mandatory; scrollbar-width:none; }




  .stories__grid::-webkit-scrollbar{ display:none; }




  .story{
    scroll-snap-align:start; flex:0 0 min(420px,86vw); border:1px solid var(--border); border-radius:var(--radius-lg);
    padding:2.2rem; display:flex; flex-direction:column; gap:1.5rem; transition:box-shadow .3s var(--ease), translate .3s var(--ease);
  }




  .story:hover{ box-shadow:0 20px 44px rgba(26,17,70,.1); translate:0 -3px; }




  .story__topic{ font-size:1.2rem; font-weight:400; line-height:1.5; color:var(--ink); font-style:italic; }




  .story__who{ display:flex; align-items:center; gap:.9rem; }




  .story__avatar{
    width:44px; height:44px; border-radius:50%; background:linear-gradient(135deg,var(--primary),var(--secondary));
    display:flex; align-items:center; justify-content:center; color:#fff; font-weight:700; flex-shrink:0; font-size:.9rem;
  }




  .story__who strong{ display:block; font-size:.9375rem; }




  .story__who span{ display:block; font-size:.8125rem; color:var(--ink-secondary); margin-top:.15rem; }




  .story__play{ margin-left:auto; display:flex; align-items:center; gap:.35rem; font-size:.8125rem; font-weight:700; color:var(--primary); flex-shrink:0; }




  .story__play:hover{ color:var(--primary-hover); }




  .story__play svg{ width:12px; height:12px; }





  /* ================= RESOURCES (new section, structure modelled on an attached reference
     image -- an Adecco resources grid: image + tag + title + "Read More"). The reference's own
     article titles ("Adecco - on the Labour Horizon - Q1 2024" literally names that company) are
     Adecco's real published content, not Alliance's, so weren't copied -- same discipline as the
     Industries/Specialisms sections above. Used three of Alliance's own real, currently-published
     blog posts instead (fetched live from alliancerecruitmentagency.co.uk/blog): real titles,
     real publish dates, real category, and each post's own real featured image (downloaded
     directly from Alliance's CMS, resized 1920x1080 -> 800x450/WEBP q78 to keep the embed
     reasonable -- still their real photography/title-card design, not a placeholder). Cards link
     out to the real, live article URLs on Alliance's own domain. */
  .resources-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:1.5rem; }




  .resource-card{
    background:#fff; border:1px solid var(--border); border-radius:var(--radius-lg); overflow:hidden;
    display:flex; flex-direction:column; transition:box-shadow .3s var(--ease), translate .3s var(--ease);
  }




  .resource-card:hover{ box-shadow:0 20px 40px rgba(58,37,156,.14); translate:0 -4px; }




  .resource-card__media{ aspect-ratio:16/9; background:var(--bg-secondary); }




  .resource-card__media img{ width:100%; height:100%; object-fit:cover; display:block; }




  .resource-card__body{ padding:1.5rem; display:flex; flex-direction:column; flex:1; }




  .resource-card__tag{
    align-self:flex-start; font-size:.6875rem; font-weight:700; letter-spacing:.04em; text-transform:uppercase;
    color:var(--primary); background:var(--bg-secondary); border:1px solid rgba(58,37,156,.14);
    padding:.3rem .65rem; border-radius:var(--radius-pill); margin-bottom:.9rem;
  }




  .resource-card h3{ font-size:1.0625rem; font-weight:700; color:var(--ink); font-family:var(--display); line-height:1.35; }




  .resource-card__meta{ font-size:.75rem; color:var(--ink-tertiary); margin-top:.6rem; }




  .resource-card__link{
    margin-top:auto; padding-top:1.25rem; font-weight:700; font-size:.8125rem; color:var(--primary);
    display:inline-flex; gap:.4rem; align-items:center;
  }




  .resource-card__link svg{ width:12px; height:12px; transition:translate .2s; }




  .resource-card__link:hover{ color:var(--secondary); }




  .resource-card__link:hover svg{ translate:3px 0; }





  /* ================= CLOSING CTA ================= */
  .cta-band{ background:var(--surface-dark); color:#fff; text-align:center; position:relative; overflow:hidden; }




  .cta-band::before{
    content:''; position:absolute; inset:0;
    /* seam bar (see .glow-region::before) folded in as a 4th layer, since this element already
       needs its own ::before for the radial backdrop and a second rule would just overwrite it */
    background:
      linear-gradient(90deg, var(--secondary), var(--primary)) top / 100% 3px no-repeat,
      radial-gradient(circle at 15% 20%, rgba(30,143,201,.28), transparent 45%),
      radial-gradient(circle at 85% 80%, rgba(58,37,156,.4), transparent 50%);
  }




  .cta-band__inner{ position:relative; z-index:1; max-width:640px; margin-inline:auto; }




  .cta-band h2{ font-size:clamp(2rem,4.3vw,3rem); font-weight:700; line-height:1.2; margin-bottom:1rem; }




  .cta-band p{ font-size:1.0625rem; color:rgba(255,255,255,.78); margin-bottom:2.2rem; }




  .cta-band .hero__ctas{ justify-content:center; margin-bottom:0; }





  /* ================= FOOTER ================= */
  /* footer dark bg = var(--surface-dark), the logo-derived midnight violet (see :root) — not
     RH's raw near-black. RH's own footer element returned a transparent computed background on
     measurement (a wrapper div, not the painted layer), so a dark surface here was always a
     design decision, never a direct colour read from either reference. */
  .site-footer{ background:var(--surface-dark); color:rgba(255,255,255,.72); padding-top:clamp(2.75rem,5.5vw,4rem); }




  .footer__grid{ display:grid; grid-template-columns:1.3fr repeat(3,1fr); gap:2.5rem; padding-bottom:2.25rem; border-bottom:1px solid rgba(255,255,255,.14); }




  .footer__brand-logo{ background:#fff; border-radius:10px; padding:.5rem .7rem; display:inline-flex; margin-bottom:1.3rem; }




  .footer__brand-logo img{ height:30px; width:auto; }




  .footer__brand p{ font-size:.875rem; line-height:1.65; max-width:22rem; margin-bottom:1.4rem; color:rgba(255,255,255,.6); }




  .footer__contact{ display:flex; flex-direction:column; gap:.6rem; margin-bottom:1.5rem; }




  .footer__contact a{ font-size:.875rem; font-weight:600; color:#fff; display:flex; align-items:center; gap:.55rem; }




  .footer__contact a:hover{ color:#9ACDE7; }




  .footer__contact svg{ width:14px; height:14px; color:#9ACDE7; flex-shrink:0; }




  .footer__soc{ display:flex; gap:.7rem; }




  .footer__soc a{ width:36px; height:36px; border-radius:50%; border:1px solid rgba(255,255,255,.18); display:flex; align-items:center; justify-content:center; transition:background .2s, border-color .2s; }




  .footer__soc a:hover{ background:var(--primary); border-color:var(--primary); }




  .footer__soc svg{ width:15px; height:15px; color:#fff; }




  .footer__col h4{ font-size:.75rem; font-weight:800; letter-spacing:.1em; text-transform:uppercase; color:rgba(255,255,255,.85); margin-bottom:1.2rem; }




  .footer__col ul{ display:flex; flex-direction:column; gap:.75rem; }




  .footer__col a{ font-size:.875rem; color:rgba(255,255,255,.62); }




  .footer__col a:hover{ color:#fff; }




  .footer__bottom{ display:flex; flex-wrap:wrap; gap:1.2rem; align-items:center; justify-content:space-between; padding-block:1.25rem; font-size:.8125rem; color:rgba(255,255,255,.5); }




  .footer__legal{ display:flex; gap:1.5rem; flex-wrap:wrap; }




  .footer__legal a:hover{ color:#fff; }





  /* back to top */
  .totop{
    position:fixed; right:1.5rem; bottom:1.5rem; z-index:90; width:46px; height:46px; border-radius:50%;
    background:var(--surface-dark); color:#fff; display:flex; align-items:center; justify-content:center;
    box-shadow:0 10px 30px rgba(26,17,70,.35); opacity:0; visibility:hidden; translate:0 12px;
    transition:opacity .25s var(--ease), translate .25s var(--ease), visibility .25s, background .2s;
  }




  .totop.is-visible{ opacity:1; visibility:visible; translate:0 0; }




  .totop:hover{ background:var(--primary); }




  .totop svg{ width:18px; height:18px; }





  /* ================= PORTED FROM nextgen-dark/index.html =================
     Four pieces brought over verbatim in content, re-themed in CSS to this file's
     own measured tokens (--primary/--secondary/--ink/--bg-secondary/--border/
     --surface-dark etc.) rather than nextgen-dark's parallel token set, so this
     stays one coherent design system instead of two palettes stitched together.
     Class names kept identical to the source file where there was no naming
     collision (confirmed via grep against this file before reusing them) so the
     structure stays traceable back to where it came from. This whole block, and
     the matching HTML/JS below, exist ONLY in this roberthalf-style-v2 copy —
     the original roberthalf-style/index.html was never touched. ========== */

  /* ---- stat ticker (source: nextgen-dark's hero-adjacent sliding ticker) ---- */
  .ticker-strip{ border-top:1px solid var(--border); border-bottom:1px solid var(--border); background:var(--bg-secondary); overflow:hidden; padding:.9rem 0; }




  .ticker-track{ display:flex; width:max-content; animation:ticker-slide 30s linear infinite; }




  .ticker-strip:hover .ticker-track{ animation-play-state:paused; }




  .ticker-item{ display:flex; align-items:center; gap:.6rem; padding:0 1.75rem; font-size:.875rem; font-weight:700; color:var(--ink-secondary); white-space:nowrap; }




  .ticker-item__sep{ width:6px; height:6px; border-radius:50%; background:var(--secondary); flex-shrink:0; }




  .ticker-item b{ color:var(--primary); font-family:var(--display); font-weight:800; }




  @keyframes ticker-slide{ from{ transform:translateX(0); } to{ transform:translateX(-50%); } }





  /* ---- "Trusted By Leading Brands And Startups". Originally ported with a placeholder
     strip (the mockup's own named logos -- Wipro/Fujitsu/Benetton/Chanel/Parle -- were
     never confirmed as real Alliance clients, so they were replaced with neutral
     "Client Logo" chips pending the real files). 2026-10-02: the client supplied 12 real
     logos directly in chat; see .brand-card below for the tile treatment. ---- */
  .brand-strip{ background:#fff; border-bottom:1px solid var(--border); padding:2rem 0; }




  .brand-strip__cap{ text-align:center; font-size:.75rem; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:var(--ink-tertiary); margin-bottom:1.4rem; }




  .brand-marquee{ overflow:hidden; -webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent); mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent); }




  .brand-track{ display:flex; align-items:center; width:max-content; gap:4rem; animation:ticker-slide 26s linear infinite; }




  .brand-strip:hover .brand-track{ animation-play-state:paused; }




  /* Real client logos (added 2026-10-02): a small rounded card per logo rather than a
     bare image + grayscale/opacity filter. 4 of the 12 supplied source files carry a
     solid baked-in background (not transparent) -- bare-floating those next to
     transparent-background logos in the old filter treatment would read as random
     floating color rectangles, so every logo gets the same neutral card frame instead,
     at full color (the grayscale-by-default/colour-on-hover filter doesn't make sense
     once a card already frames each mark). object-fit:contain + a fixed card height
     keeps the row visually even despite the very different source aspect ratios. */
  .brand-card{
    display:flex; align-items:center; justify-content:center;
    height:88px; width:200px; flex-shrink:0; padding:.85rem 1.35rem;
    background:#fff; border:1px solid var(--border); border-radius:12px;
    box-shadow:0 1px 3px rgba(11,6,32,.06);
  }
  .brand-card img{ max-height:100%; max-width:100%; width:auto; height:auto; object-fit:contain; }

  /* Community Case Management's source file is a white mark on a transparent
     background -- invisible on the card's white fill, so this one variant uses the
     site's own dark-navy surface token instead, which also matches the un-carded dark
     sections elsewhere on the page rather than an arbitrary grey. */
  .brand-card--dark{ background:var(--surface-dark); border-color:var(--surface-dark); }





  /* ---- IT Outsource promo band (source: nextgen-dark's "Access Top-Tier Remote IT
     Talent" promo-banner). Re-themed onto --surface-dark + the same radial-glow
     recipe .cta-band already uses on this page, instead of nextgen's own gradient
     token stack, so it reads as this page's dark-section pattern, not a foreign one. ---- */
  .promo-banner{ background:var(--surface-dark); color:#fff; position:relative; overflow:hidden; }




  /* bug report: "IT Outsource section image is not fetched from nextgen-dark's IT Outsource
     section background image" -- correct: nextgen-dark's <img class="promo-bg"> element sits
     inside a promo-banner section, base64-embedded, but my own earlier grep-based reading of
     that file always piped through `grep -v base64` to avoid pulling huge image lines into
     context -- which silently filtered out the one line that mattered here, so the image was
     never noticed or ported. Confirmed by extracting its data URI directly and diffing the
     decoded bytes against nextgen-dark/assets/hero-banner.webp -- byte-identical, a real NYC
     skyline-at-night photo (1920x500), not a placeholder. */
  .promo-banner img.promo-bg{
    position:absolute; inset:0; width:100%; height:100%; object-fit:cover; z-index:0;
    filter:saturate(1.1) brightness(.8);
  }




  .promo-banner::before{
    /* HEIGHT BUG FOUND + FIXED (Hiring OS pass): this ::before was rendering as a 3px sliver
       at the very top of the section, not a full-cover scrim, even though `inset:0` looks like
       it should cover the whole box. Root cause: .glow-region::before (defined earlier in this
       file, for the unrelated thin top seam bar used on every other section) sets
       `height:3px` on the SAME generated pseudo-element, since this section carries both
       classes. `inset` is a shorthand for top/right/bottom/left only -- it does not include
       height -- so that earlier height:3px was never overridden. With top, bottom (via
       inset:0) AND an explicit height all present, the box is over-constrained and the spec
       has `bottom` lose, keeping height:3px. Net effect: the dark scrim gradient painted onto
       a 3px strip, i.e. was never visible as a scrim at all -- confirmed via
       getComputedStyle(...,'::before').height === '3px' before this fix. Invisible with the
       inherited NYC-night photo because that source image was already dark everywhere on its
       own; exposed the moment a brighter photo (assets/hiring-os-banner.webp) went in and the
       top-left corner was unreadably bright. Fix: explicit height:auto below, so inset:0's
       implied top+bottom sizing wins instead of the leaked height:3px. (z-index:1, up from the
       original 0, is kept too -- harmless and correct once this element actually covers the
       box: img.promo-bg is z-index:0, so the now-full-size scrim needs to sit above it and
       below .promo-inner's z-index:1 content.) */
    content:''; position:absolute; inset:0; height:auto; z-index:1;
    background:
      linear-gradient(90deg, var(--secondary), var(--primary)) top / 100% 3px no-repeat,
      /* left-to-right dark scrim over the photo, tuned from this page's own --surface-dark/
         --primary tokens (not nextgen's separate raw hex) so text stays legible over the
         photo's brighter areas -- same legibility-first approach nextgen-dark itself uses on
         this exact section, verified by screenshotting nextgen-dark's live render first rather
         than assuming a stacking order from reading the CSS alone. */
      linear-gradient(100deg, rgba(26,17,70,.93) 15%, rgba(38,25,101,.78) 55%, rgba(58,37,156,.5) 100%);
  }




  .promo-inner{ position:relative; z-index:1; max-width:600px; padding-block:clamp(3rem,7vw,5.25rem); }




  .promo-inner h2{ color:#fff; font-size:clamp(1.75rem,3.6vw,2.5rem); margin-top:.9rem; font-weight:700; line-height:1.2; }




  /* .promo-feats / .promo-inner p removed: this section's content was replaced per the attached
     reference image (bug report: "change the content of IT Outsource section to as per attached
     Image's details") — a checklist instead of a feature-chip row + description paragraph. */
  .promo-checklist{ margin-top:1.5rem; display:flex; flex-direction:column; gap:1rem; }




  .promo-checklist li{ display:flex; align-items:flex-start; gap:.85rem; }




  .promo-checklist__icon{
    flex-shrink:0; width:30px; height:30px; border-radius:9px; background:#fff;
    display:flex; align-items:center; justify-content:center; margin-top:.1rem;
  }




  .promo-checklist__icon svg{ width:14px; height:14px; color:var(--primary); }




  .promo-checklist li span:last-child{ color:rgba(255,255,255,.92); font-size:1rem; line-height:1.5; }




  .promo-inner__actions{ display:flex; flex-wrap:wrap; gap:.85rem; margin-top:1.75rem; }




  /* .promo-float (the two floating stat callouts, "10x Faster hiring speed"/"40% Cost savings")
     removed along with the rest of the old IT-outsourcing-specific content — those two numbers
     were specific to that copy and don't carry over to the new "Consulting Solutions" content
     from the reference image, which doesn't show any equivalent floating stat. Rather than
     invent new numbers with nothing backing them, removed the component entirely. */

  /* ---- "Our comprehensive expertise" bento grid (source: nextgen-dark's #expertise
     section). Card shell reuses this page's own hover/shadow recipe (brand-tinted
     rgba shadow + translateY lift, same as .pillar/.reach__card/.story) instead of
     nextgen's separate --shadow-sm/--shadow-lg tokens (which don't exist on this
     page). #expertise is deliberately NOT added to the running "— 0N" chapter-number
     counter (#reach/#why/#specialties/#stories) since it sits before that sequence
     starts and would otherwise render "— 00". ---- */
  .expertise-grid{ display:grid; grid-template-columns:repeat(6,1fr); gap:1.1rem; }




  .expertise-card{
    background:#fff; border:1px solid var(--border); border-radius:var(--radius-lg);
    padding:1.6rem; position:relative; overflow:hidden;
    transition:box-shadow .3s var(--ease), translate .3s var(--ease);
  }




  .expertise-card:hover{ box-shadow:0 20px 40px rgba(58,37,156,.14); translate:0 -4px; }




  .expertise-card h4{ font-size:1rem; display:flex; align-items:center; gap:.55rem; font-weight:700; font-family:var(--font); color:var(--ink); }




  .expertise-card h4 .ic{ width:30px; height:30px; border-radius:9px; display:flex; align-items:center; justify-content:center; flex-shrink:0; background:rgba(58,37,156,.06); color:var(--primary); }




  .ex-span-4{ grid-column:span 4; }




  .ex-span-2{ grid-column:span 2; }




  .ex-span-6{ grid-column:span 6; }





  .svc-chip-grid{ display:flex; flex-wrap:wrap; gap:.5rem; margin-top:1rem; }




  .svc-chip-grid span{ font-size:.78rem; font-weight:600; color:var(--primary); background:rgba(58,37,156,.06); border:1px solid rgba(58,37,156,.14); padding:.45rem .8rem; border-radius:var(--radius-pill); }





  .place-chip-list{ margin-top:1rem; display:flex; flex-wrap:wrap; gap:.5rem; }




  .place-chip-list span{ font-size:.78rem; font-weight:600; color:var(--ink-secondary); background:var(--bg-secondary); padding:.45rem .75rem; border-radius:var(--radius-pill); border:1px solid var(--border); }





  /* bug report: "remove salary calculator from Our comprehensive expertise & make new
     section as per attachment" -- the calc-controls/calc-row/calc-output rules below are
     unchanged (still used, now by .salary-calc__tool instead of the old small bento card),
     just retargeted off the #expertise id since the calculator no longer lives inside that
     section. */
  .calc-controls{ display:flex; flex-direction:column; gap:.9rem; margin-top:1.1rem; }




  .calc-row{ display:flex; gap:.6rem; }




  .calc-row select{ flex:1; min-width:0; background:var(--bg-secondary); border:1px solid var(--border); color:var(--ink); padding:.7rem .75rem; border-radius:10px; font-size:.85rem; font-family:inherit; }




  .calc-slider-label{ display:flex; justify-content:space-between; font-size:.78rem; color:var(--ink-secondary); font-weight:600; }




  .calc-controls input[type=range]{ width:100%; accent-color:var(--primary); height:4px; }




  .calc-output{ margin-top:1.1rem; padding:1.25rem; border-radius:14px; background:linear-gradient(120deg,var(--surface-dark),var(--primary)); text-align:center; }




  .calc-output .figure{ font-family:var(--display); font-size:clamp(1.5rem,3.2vw,2rem); font-weight:700; color:#fff; }




  .calc-output .cap{ font-size:.6875rem; color:rgba(255,255,255,.7); text-transform:uppercase; letter-spacing:.1em; margin-top:.4rem; }





  /* ================= MEET OUR FOUNDERS (UK Visit, 15-30 Nov) -- new section, added per
     request. Two stops given directly: "Cardiff" (15-23 Nov) and "Wales" (24-30 Nov).
     Flagged to the client that Cardiff is itself in Wales, so those two labels overlap as
     written -- confirmed back as intentional ("they visits cardiff and wales not other
     city's"), so both are kept verbatim. To make that read sensibly rather than as a
     contradiction, the copy leans on a real fact already on this page: Alliance's own HQ is
     14 Museum Pl, Cardiff (see footer) -- so "Cardiff" is framed as HQ meetings in the first
     window, "Wales" as the team on the road for regional visits in the second. Social-proof
     stat reuses this page's own measured hero figure (12,000+ businesses supported, see #why)
     rather than inventing a new number. Booking form is a front-end mock (own IIFE at the
     bottom of the file, same prevent-default + success-state pattern as the rest of this
     file's interactive pieces) -- wire to a real backend/CRM before launch, same caveat as
     every other form on this project.
     Background, v2 (client approved adding a Cardiff Castle photo, with the instruction that
     the existing layout/design must not change): originally this section used an abstract
     grid/dot CSS texture (no photo). Replaced that with a real photo using the EXACT same
     <img>+scrim pattern already proven on this page's own .hero -- real <img class="visit__img">
     + real <div class="visit__scrim"> as actual DOM siblings (not a ::before pseudo-element)
     with the identical gradient recipe (--surface-dark-rgb stops at 0/45/68/90/100%) copied
     from .hero__scrim verbatim, so it reads as the same design system, not a new one. This
     deliberately avoids redoing .hero's own history on this file: an earlier pass on this
     project (.promo-banner / Hiring OS section) tried to layer a scrim via a shared
     ::before -- .glow-region's own ::before sets height:3px for its thin top seam bar, and
     since `inset:0` doesn't touch `height`, that 3px leaked through and silently collapsed the
     whole scrim to a sliver. Using real elements here (same as .hero already does) sidesteps
     that bug class entirely rather than re-triggering it with a second photo.
     Image: assets/cardiff-castle.webp, downloaded from Unsplash (free licence, no attribution
     required). Not confirmed via Unsplash's own text metadata (that only stated "Cardiff, UK"),
     but visually unambiguous -- the shell-keep-on-a-motte silhouette with the Welsh flag and
     dragon is Cardiff Castle's internationally-recognised profile, found via an Unsplash search
     specifically scoped to "cardiff castle". object-position favours the castle itself (right
     two-thirds of frame) over open sky, so it survives the crop at every breakpoint; the scrim
     still darkens that same left zone .visit__copy's text already needed, so legibility is
     unchanged from before the photo was added. ================= */
  .visit{ background:var(--surface-dark); color:#fff; position:relative; overflow:hidden; }




  .visit__img{
    position:absolute; inset:0; width:100%; height:100%; object-fit:cover; object-position:78% 38%;
  }




  .visit__scrim{
    position:absolute; inset:0;
    background:
      linear-gradient(100deg,
        rgba(var(--surface-dark-rgb),.97) 0%,
        rgba(var(--surface-dark-rgb),.95) 45%,
        rgba(var(--surface-dark-rgb),.62) 68%,
        rgba(var(--surface-dark-rgb),.34) 90%,
        rgba(var(--surface-dark-rgb),.4) 100%),
      linear-gradient(0deg, rgba(var(--surface-dark-rgb),.5) 0%, rgba(var(--surface-dark-rgb),0) 32%);
  }




  .visit .wrap{ position:relative; z-index:1; }




  /* ARAUK-76 follow-up: the GHL booking widget (css/sections.css .visit-card) renders its
     own fields in a cramped single column until it has real width to lay them out in pairs
     (its own internal breakpoint, not ours) -- the old 1.05fr/.95fr two-up split never gave it
     that, so every page showed the narrow/stacked "Enter details" form instead of the wide
     landscape layout GHL's widget uses when it has room. Stacking copy above a full-width card
     (bounded only by .wrap's 1240px) gives the widget enough width to lay out in pairs. */
  .visit__grid{
    display:grid; grid-template-columns:1fr; gap:clamp(2rem,4vw,3rem);
    align-items:start; padding-block:clamp(3.5rem,7vw,5.5rem);
  }





  .visit__copy h2{ font-size:clamp(1.75rem,3.4vw,2.75rem); font-weight:800; letter-spacing:-.015em; line-height:1.15; margin-top:.9rem; }




  .visit__copy p{ margin-top:1.1rem; font-size:1.0625rem; color:rgba(255,255,255,.72); line-height:1.7; max-width:38rem; }





  .visit__stops{ display:flex; flex-wrap:wrap; gap:.9rem; margin-top:1.75rem; }




  .visit-stop{
    display:flex; align-items:flex-start; gap:.7rem;
    background:rgba(255,255,255,.055); border:1px solid rgba(255,255,255,.14);
    border-radius:var(--radius-sm); padding:.9rem 1.15rem; min-width:200px;
  }




  .visit-stop__ic{
    width:34px; height:34px; border-radius:10px; flex-shrink:0; margin-top:1px;
    background:rgba(154,205,231,.16); color:#9ACDE7;
    display:flex; align-items:center; justify-content:center;
  }




  .visit-stop b{ display:block; font-size:.9375rem; font-weight:700; color:#fff; }




  .visit-stop span{ display:block; font-size:.8125rem; font-weight:700; color:#9ACDE7; margin-top:.15rem; }





  .visit__meta{ display:flex; align-items:center; flex-wrap:wrap; gap:.7rem; margin-top:1.75rem; font-size:.875rem; color:rgba(255,255,255,.55); }




  .visit__meta strong{ color:#fff; }




  .visit__meta .dot{ width:3px; height:3px; border-radius:50%; background:rgba(255,255,255,.3); flex-shrink:0; }




  .visit__alt{ margin-top:1.1rem; font-size:.875rem; color:rgba(255,255,255,.55); }




  .visit__alt a{ color:#9ACDE7; font-weight:600; border-bottom:1px solid rgba(154,205,231,.4); padding-bottom:1px; }




  .visit__alt a:hover{ border-bottom-color:#9ACDE7; }





  .visit-card{
    background:rgba(255,255,255,.055); border:1px solid rgba(255,255,255,.14);
    border-radius:var(--radius-lg); padding:clamp(1.75rem,3vw,2.5rem);
    box-shadow:0 40px 90px -30px rgba(0,0,0,.55);
  }




  .visit-card h3{ font-size:1.375rem; font-weight:700; color:#fff; letter-spacing:-.01em; }




  .visit-field{ margin-top:1.1rem; }




  .visit-field label{
    display:block; font-size:.75rem; font-weight:700; letter-spacing:.03em;
    color:rgba(255,255,255,.55); margin-bottom:.4rem; text-transform:uppercase;
  }




  .visit-field input, .visit-field select, .visit-field textarea{
    width:100%; font-family:inherit; font-size:.9375rem; color:#fff;
    background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.16);
    border-radius:10px; padding:.75rem .9rem; transition:border-color .2s, background .2s;
  }




  .visit-field input::placeholder, .visit-field textarea::placeholder{ color:rgba(255,255,255,.32); }




  .visit-field select{ color-scheme:dark; }




  .visit-field input:focus, .visit-field select:focus, .visit-field textarea:focus{
    outline:none; border-color:#9ACDE7; background:rgba(255,255,255,.1);
  }




  .visit-field textarea{ resize:vertical; min-height:72px; }




  .visit-row{ display:grid; grid-template-columns:1fr 1fr; gap:1rem; }




  .visit-card__note{ font-size:.75rem; color:rgba(255,255,255,.42); margin-top:.9rem; text-align:center; line-height:1.5; }




  .visit-card__success{ display:none; text-align:center; padding:1.25rem 0; }




  .visit-card__success strong{ display:block; font-size:1.25rem; font-weight:700; color:#fff; margin-bottom:.5rem; }




  .visit-card__success p{ font-size:.9375rem; color:rgba(255,255,255,.65); line-height:1.6; }




  .visit-card.is-sent .visit-card__form{ display:none; }




  .visit-card.is-sent .visit-card__success{ display:block; }





  /* ================= SALARY CALCULATOR (own section now, structure modelled on an attached
     reference: left column a "Free tool" eyebrow + headline + copy + CTA, right column the
     live calculator card -- role/location selects, a years-of-experience slider and a dark
     gradient output banner. Reuses the exact same #calcRole/#calcRegion/#calcExp/
     #calcExpLabel/#calcFigure markup + JS that used to live in the small "Our comprehensive
     expertise" bento card -- the estimate logic is unchanged, only pulled into its own full
     section and restyled to the reference's two-column layout. Still a rough, banded
     estimate from a small fixed table, not a live market-data feed -- same caveat as before,
     just now more prominent, so worth being honest about it here too. ================= */
  .salary-calc{ display:grid; grid-template-columns:1fr 1fr; gap:clamp(2rem,5vw,4rem); align-items:center; }




  .salary-calc__copy h2{ font-size:clamp(1.5rem,2.4vw,2.5rem); line-height:1.15; font-weight:800; letter-spacing:-.015em; color:var(--ink); }




  .salary-calc__copy p{ margin-top:1rem; font-size:1.0625rem; color:var(--ink-secondary); line-height:1.65; max-width:30rem; }




  .salary-calc__copy .btn{ margin-top:1.75rem; }




  .salary-calc__tool{
    background:#fff; border:1px solid var(--border); border-radius:var(--radius-lg);
    padding:2rem; box-shadow:0 20px 50px -20px rgba(58,37,156,.18);
  }





  /* Certifications & Achievements, redesigned (bug report: "add details as per attachment but
     change the design as per relevant to our theme"). The attachment was a competitor's real
     awards section (laurel-wreath badges captioned "Fortune® World's Most Admired Companies",
     "Great Place To Work UK's Best Workplaces", etc.) -- those are that company's own accolades,
     not Alliance's, so copying the specific award names would have been fabricating credentials
     for Alliance rather than adapting a reference. Took the STRUCTURE instead (badge + award name
     + year, plus a closing CTA) and filled it with Alliance's own six real certification/award
     badges -- already embedded in this file, sourced and verified in an earlier pass -- with each
     one's name and year read directly off the badge image itself (the "10 Most Reliable HR
     Solution Providers" ring badge, HR Asia Readers' Choice 2022, ISO 9001 Certified, Alliance's
     own 16th-anniversary mark, GoodFirms Top Staffing Firm, and Recruiter Awards 2023 Highly
     Commended). Restyled fully in this page's own system -- circular badge tray on
     --bg-secondary, Libre Franklin caption type, primary/secondary accent ring -- rather than the
     reference's laurel-wreath motif, which is that other company's specific visual identity, not
     a structural pattern worth copying. */
  .cert-intro{ color:var(--ink-secondary); font-size:.9375rem; line-height:1.6; margin-top:.5rem; max-width:38rem; }




  .cert-grid{ display:grid; grid-template-columns:repeat(6,1fr); gap:1.25rem; margin-top:1.75rem; }




  .cert-item{ text-align:center; }




  .cert-item__badge{
    width:68px; height:68px; margin-inline:auto; border-radius:50%; background:var(--bg-secondary);
    border:1px solid var(--border); box-shadow:0 0 0 4px rgba(58,37,156,.07);
    display:flex; align-items:center; justify-content:center; padding:.6rem;
  }




  .cert-item__badge img{ width:100%; height:100%; object-fit:contain; }




  .cert-item b{ display:block; font-size:.75rem; font-weight:700; color:var(--ink); margin-top:.75rem; line-height:1.3; font-family:var(--display); }




  .cert-item span{ display:block; font-size:.6875rem; color:var(--ink-tertiary); margin-top:.2rem; }




  .cert-cta{ margin-top:1.75rem; }






  /* ================= SUCCESS STORIES: Client Story / Candidate Story toggle =================
     Restructured again per explicit request: instead of two separate sections (Pass 2/3) or
     click-to-open-modal cards (Pass 4), this is now ONE section with a top-level [Client Story]/
     [Candidate Story] toggle, and each story type displays its content directly on the page as
     two stacked sub-sections -- Messages on top, Video below -- rather than behind a click. The
     previous modal system is removed entirely; nothing here still depends on it. ---- */
  .story-toggle{ display:flex; gap:.6rem; justify-content:center; margin-bottom:2rem; }




  .story-toggle button{
    padding:.7rem 1.5rem; border-radius:var(--radius-pill); font-size:.9375rem; font-weight:700;
    border:1.5px solid var(--border); color:var(--ink-secondary); transition:all .2s;
  }




  .story-toggle button.is-active{ background:var(--primary); color:#fff; border-color:transparent; }




  .story-toggle button:not(.is-active):hover{ border-color:var(--primary); color:var(--primary); }




  .story-panel[hidden]{ display:none; }




  .story-sub{ margin-top:2.25rem; }




  .story-sub:first-child{ margin-top:0; }




  .story-sub__head{ display:flex; align-items:center; gap:.65rem; margin-bottom:1.25rem; }




  .story-sub__head h3{ font-size:1.125rem; font-weight:700; color:var(--ink); font-family:var(--display); }




  .story-sub__head .ic{
    width:32px; height:32px; border-radius:9px; background:rgba(58,37,156,.06); color:var(--primary);
    display:flex; align-items:center; justify-content:center; flex-shrink:0;
  }




  .msg-grid, .video-grid{ display:grid; grid-template-columns:repeat(4,1fr); gap:1.1rem; }




  .msg-card{
    background:#fff; border:1px solid var(--border); border-radius:var(--radius-lg); padding:1.4rem;
    transition:box-shadow .3s var(--ease), translate .3s var(--ease);
  }




  .msg-card:hover{ box-shadow:0 20px 40px rgba(58,37,156,.14); translate:0 -4px; }




  .msg-card p{ font-size:.875rem; color:var(--ink); line-height:1.6; font-style:italic; min-height:4.8em; }




  .msg-card__who{ margin-top:1rem; padding-top:.9rem; border-top:1px solid var(--border); }




  .msg-card__who b{ display:block; font-size:.875rem; font-weight:700; color:var(--ink); }




  .msg-card__who span{ display:block; font-size:.75rem; color:var(--ink-tertiary); margin-top:.1rem; }




  .video-card{
    background:#fff; border:1px solid var(--border); border-radius:var(--radius-lg); overflow:hidden;
    transition:box-shadow .3s var(--ease), translate .3s var(--ease);
  }




  .video-card:hover{ box-shadow:0 20px 40px rgba(58,37,156,.14); translate:0 -4px; }




  .video-card__media{ aspect-ratio:4/3; position:relative; }




  .video-card__media img{ width:100%; height:100%; object-fit:cover; display:block; }




  .video-card__badge{
    position:absolute; top:.6rem; left:.6rem; width:26px; height:26px; border-radius:50%;
    background:rgba(11,6,32,.55); color:#fff; display:flex; align-items:center; justify-content:center;
  }




  /* Real, playable testimonial -- a YouTube iframe (client-supplied embed code) rather than
     a click-to-load thumbnail; an earlier click-to-play version was replaced per client
     request citing a design issue. iframe width/height attributes aren't set in the markup
     (YouTube's default embed snippet hardcodes a fixed px size, which would overflow this
     grid's column); sized responsively via CSS to fill the card instead.
     --vertical: for a YouTube Shorts embed (9:16) -- was Lucila's video, removed 2026-10-05
     per "remove all video testimonial from client side", kept as a class for any future
     Shorts testimonial.
     --wide: for a standard landscape YouTube embed (16:9) -- Malik's client-spotlight video,
     the sole remaining client video testimonial as of 2026-10-05. */
  .video-card--vertical .video-card__media{ aspect-ratio:9/16; }
  .video-card--wide .video-card__media{ aspect-ratio:16/9; }
  .video-card__media iframe{ width:100%; height:100%; border:0; display:block; }




  /* video-grid--single: the client-video grid now holds exactly one real testimonial
     (2026-10-05) -- without this, the lone .video-card would sit in column 1 of an empty
     4-column grid (repeat(4,1fr)), stretched to a quarter-width card instead of reading as
     a deliberate single feature. Compound selector (.video-grid.video-grid--single, not just
     the modifier alone) so its specificity beats the responsive 1-column/2-column .video-grid
     overrides in css/responsive.css regardless of source order. */
  .video-grid.video-grid--single{ grid-template-columns:minmax(0,560px); justify-content:center; }




  /* video-grid--triple: a 3-column variant for whenever a .video-grid holds exactly 3 cards
     (used 2026-10-05 for the candidate-video grid's first 3 testimonials; currently unused --
     a 4th was added 2026-10-06, ALLUKNEW-6, so that grid went back to the base 4-column rule
     below, its original size). Kept rather than deleted: this count has changed twice in two
     days and will likely change again. 3 columns instead of the base grid's 4 so nothing sits
     in a half-empty row when the count genuinely is 3; same compound-selector specificity
     trick as --single, for the same reason. */
  .video-grid.video-grid--triple{ grid-template-columns:repeat(3,minmax(0,1fr)); max-width:960px; margin-inline:auto; }




  .video-card__body{ padding:1rem 1.25rem 1.25rem; }




  .video-card__body b{ display:block; font-size:.8125rem; font-weight:700; color:var(--ink); }




  .video-card__body span{ display:block; font-size:.75rem; color:var(--ink-tertiary); margin-top:.1rem; }




  /* .video-placeholder-block removed 2026-10-05 -- its only usage (the candidate Video
     sub-section's "unlock after a mutual introduction" message) was replaced with 3 real
     public testimonial videos; grep-confirmed no other reference anywhere in the repo
     before removing. */




  /* ================= CASE STUDIES (ARAUK-17): hub card grid + detail-page "related
     case studies" grid. Same visual language as .video-card (border/radius/shadow/hover/
     media aspect-ratio, same tokens) but its own correctly-named component since the
     content and purpose differ: a case-study link card (image + eyebrow + h3 + 2-line
     summary + "Read more" link), not a video testimonial. 3-column by default since every
     service shows exactly 3 cards. ================= */
  .case-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:1.1rem; }




  /* case-grid--pair: a detail page's "related case studies" shows the other 2 stories in the
     same service, never 3 (the current page is the 3rd) -- same compound-selector trick as
     .video-grid--triple so it beats the single-class responsive rules below. */
  .case-grid.case-grid--pair{ grid-template-columns:repeat(2,minmax(0,1fr)); max-width:720px; margin-inline:auto; }




  .case-card{
    background:#fff; border:1px solid var(--border); border-radius:var(--radius-lg); overflow:hidden;
    transition:box-shadow .3s var(--ease), translate .3s var(--ease);
  }




  .case-card:hover{ box-shadow:0 20px 40px rgba(58,37,156,.14); translate:0 -4px; }




  .case-card__media{ aspect-ratio:4/3; position:relative; }
  .case-card__media img{ width:100%; height:100%; object-fit:cover; display:block; }

  /* ARAUK-79 fix: the blog's own article images are the original 1600x900 (16:9)
     social-card graphics carried over from the live site, with text and the logo
     baked in close to both edges. The shared .case-card__media 4:3 box (built for
     plain photos on Case Studies) crops both edges and cuts that text off -- so
     every blog usage (the listing grid in .blog-main and the "Latest Published
     Blogs" widget in #related) gets the image's own 16:9 ratio instead, which
     object-fit:cover can then fill with zero cropping. */
  .blog-main .case-card__media,
  #related .case-card__media{ aspect-ratio:16/9; }



  .case-card__body{ padding:1.1rem 1.25rem 1.4rem; }




  .case-card__eyebrow{
    font-size:.6875rem; font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--primary);
  }




  .case-card__body h3{
    font-size:1.0625rem; font-weight:700; color:var(--ink); font-family:var(--display);
    line-height:1.35; margin-top:.5rem;
  }




  .case-card__body p{ font-size:.8125rem; color:var(--ink-secondary); line-height:1.55; margin-top:.5rem; }




  .case-card__link{
    font-weight:700; font-size:.8125rem; color:var(--primary); display:inline-flex; gap:.4rem;
    align-items:center; margin-top:1rem;
  }




  /* the compliance disclosure line (content-provenance.md / ARAUK-17 plan): small, quiet,
     never a per-card badge. */
  .case-disclosure{ font-size:.8125rem; color:var(--ink-tertiary); margin-bottom:2rem; max-width:62ch; }




  /* placeholder text for a service tab whose 3 case studies haven't shipped yet (ARAUK-17
     ships in phased batches -- see docs/plans/2026-10-26-case-studies-hub.md). */
  .case-panel__soon{ text-align:center; color:var(--ink-tertiary); padding:3rem 0; font-size:.9375rem; }




  /* generic bulleted list for a case-study detail page's Challenge/Outcome sections (ARAUK-17).
     The global reset strips default <ul> markers (list-style:none, line 11 above) and the
     existing .promo-checklist component's checkmark icon reads as "done/benefit", which fits
     an Outcome list but not a Challenge list -- so this is a neutral dot marker usable for
     both, reusing the same accent-dot motif as .emp-accent-bar rather than a new icon set. */
  .article-list{ margin-top:1.1rem; display:flex; flex-direction:column; gap:.65rem; }
  .article-list li{
    display:flex; gap:.65rem; align-items:flex-start; font-size:1.0625rem;
    color:var(--ink-secondary); line-height:1.65;
  }
  .article-list li::before{
    content:''; flex-shrink:0; width:8px; height:8px; border-radius:50%; margin-top:.55rem;
    background:linear-gradient(135deg, var(--primary), var(--secondary));
  }




  /* ═══════════════ HIRING CHALLENGES ACCORDION (ARAUK-40, Batch 1 industry pages) ═══════════════
     Reed.com's "pain points" accordion reference (chat screenshot): collapsed by default, a +
     marker that becomes − when open, rows separated by a dashed rule. Built on native
     <details>/<summary> -- zero new JS -- reusing the exact mechanic already live on this site
     for the mobile nav's "Services" accordion (.rp-mob-accordion in css/job-seekers-header.css).
     Site's own fonts throughout (no third-party font import) -- only the layout/interaction is
     borrowed from Reed. Text itself is unchanged from the already-approved Hiring Challenges copy. */
  .chq-accordion{ margin-top:1.5rem; max-width:860px; border-top:1px dashed var(--border); }
  .chq-accordion details{ border-bottom:1px dashed var(--border); }
  .chq-accordion summary{
    list-style:none; cursor:pointer; padding:1.1rem 0; display:flex; align-items:center;
    justify-content:space-between; gap:1.25rem; font-size:1.0625rem; font-weight:700;
    color:var(--ink); font-family:var(--display);
  }
  .chq-accordion summary::-webkit-details-marker{ display:none; }
  .chq-accordion summary::after{
    content:'+'; flex-shrink:0; width:28px; height:28px; border-radius:50%;
    border:1.5px solid var(--border); display:flex; align-items:center; justify-content:center;
    font-size:1.25rem; line-height:1; color:var(--primary);
  }
  .chq-accordion details[open] summary::after{ content:'\2212'; } /* en dash -> minus */
  .chq-accordion__body{ padding:0 1.75rem 1.4rem 0; color:var(--ink-secondary); font-size:.9375rem; line-height:1.65; max-width:740px; }
  .chq-accordion summary:hover{ color:var(--primary); }
  .chq-accordion summary:hover::after{ border-color:var(--primary); }




  /* ═══════════════ ROBERT HALF "HOW IT WORKS" (ARAUK-40, Batch 1 industry pages) ═══════════════
     Reference: Robert Half's numbered-steps section (chat screenshot) -- a portrait image beside
     1/2/3 steps joined by a dashed vertical connector, plus one CTA. Step copy is unchanged from
     the already-approved "Brief us / We search / You interview a shortlist / You hire" text --
     only the surrounding layout replaces the generic .why__pillars icon grid used elsewhere. */
  .steps-rh{ display:grid; grid-template-columns:minmax(260px,380px) 1fr; gap:clamp(2rem,4vw,3.5rem); align-items:stretch; }
  .steps-rh__media{ border-radius:var(--radius-lg); overflow:hidden; }
  .steps-rh__media img{ width:100%; height:100%; min-height:320px; object-fit:cover; display:block; }
  .steps-rh__list{ display:flex; flex-direction:column; justify-content:center; }
  .steps-rh__step{ position:relative; padding-left:3.5rem; padding-bottom:1.9rem; }
  .steps-rh__step:last-child{ padding-bottom:0; }
  .steps-rh__step::before{
    content:''; position:absolute; left:15px; top:34px; bottom:-2px; width:0;
    border-left:2px dashed var(--border);
  }
  .steps-rh__step:last-child::before{ display:none; }
  .steps-rh__num{
    position:absolute; left:0; top:0; width:30px; height:30px; border-radius:50%;
    background:linear-gradient(145deg, var(--primary) 0%, var(--secondary) 100%);
    color:#fff; font-weight:700; font-size:.875rem; display:flex; align-items:center; justify-content:center;
  }
  .steps-rh__step h3{ font-size:1.0625rem; font-weight:700; color:var(--ink); font-family:var(--display); line-height:1.3; margin-bottom:.35rem; }
  .steps-rh__step p{ color:var(--ink-secondary); font-size:.9375rem; line-height:1.6; }
  .steps-rh__cta{ margin-top:1.75rem; padding-left:3.5rem; }
  @media (max-width:760px){
    .steps-rh{ grid-template-columns:1fr; }
    .steps-rh__media img{ min-height:220px; }
  }




  /* ═══════════════ SECTION SPACING, Batch 1 industry pages only (ARAUK-40) ═══════════════
     Reported as "lot's of space issues" -- two back-to-back <section> elements each carry the
     sitewide section{padding-block:clamp(2.5rem,4.5vw,4rem)} (css/sections.css above), so the
     gap at every section boundary is doubled. Fixing that sitewide rule would shift every other
     live page, so this halves ONLY the top padding at a boundary, scoped to the 4 pages that
     carry the new .industry-page class on <body> -- nothing else on the site is affected. */
  body.industry-page section + section{ padding-top:clamp(1.25rem,2.5vw,2rem); }




  /* ═══════════════ BLOG ARTICLE PROSE (ARAUK-75, blog migration) ═══════════════
     Everything else a blog page uses (.emp-hero/.hero, .emp-crumb, .eyebrow, .emp-section-head,
     .case-grid/.case-card for the listing, .faq-list/.faq-item) is reused verbatim from the
     employers/case-studies pages. The one thing none of those have is plain long-form article
     body text (h2/h3/p/ul inside a prose column) -- base.css sets no heading styles at all, so
     this is the minimal addition needed, not a new design. */
  .post-meta{ display:flex; gap:.5rem; align-items:center; font-size:.9rem; color:var(--ink-secondary); margin-top:.75rem; flex-wrap:wrap; }
  .post-meta span:not(:last-child)::after{ content:"•"; margin-left:.5rem; opacity:.5; }
  .post-body{ max-width:760px; margin-inline:auto; }
  .post-body h2{ font-family:var(--display); font-size:clamp(1.3rem,2.4vw,1.6rem); font-weight:800; color:var(--ink); margin:2.5rem 0 1rem; line-height:1.3; }
  .post-body h3{ font-family:var(--display); font-size:1.15rem; font-weight:700; color:var(--ink); margin:1.75rem 0 .6rem; }
  .post-body p{ font-size:1rem; line-height:1.7; color:var(--ink); margin:0 0 1.1rem; }
  .post-body ul, .post-body ol{ margin:0 0 1.1rem 1.25rem; line-height:1.7; }
  .post-body li{ margin-bottom:.4rem; }
  .post-body a{ color:var(--link); text-decoration:underline; text-decoration-color:var(--border); }
  .post-body a:hover{ color:var(--secondary-hover); }
  .post-body strong{ color:var(--ink); }
  .post-body img{ border-radius:var(--radius-sm); margin:1rem 0; }


  /* ═══════════════ BLOG ARTICLE REDESIGN (ARAUK-79) ═══════════════
     New pieces the article template needs that nothing on the site already had: the hero-image
     block under the title-only hero, the views/date/author + share-icon meta row, the 4 AI
     "explore this post with" pills, and the native <details> table of contents. The author card
     and related-posts grid reuse .case-card/.case-grid--pair verbatim (ARAUK-17) -- no new CSS
     for those. All colours come from tokens.css; nothing here is a new hue. */
  .post-hero-media{ max-width:900px; margin:0 auto 1.5rem; }
  .post-hero-media img{ width:100%; height:auto; border-radius:var(--radius-lg); display:block; }

  .post-meta-row{ max-width:900px; margin:0 auto 1.25rem; display:flex; align-items:center; justify-content:space-between; gap:1rem; flex-wrap:wrap; padding-bottom:1rem; border-bottom:1px solid var(--border); }
  .post-meta-row__left{ display:flex; align-items:center; gap:.5rem; font-size:.9rem; color:var(--ink-secondary); flex-wrap:wrap; }
  .post-meta-row .post-views{ display:inline-flex; align-items:center; gap:.3rem; }
  .post-meta-row .post-views svg{ width:16px; height:16px; }
  .post-meta-row .post-sep{ opacity:.5; }
  .post-meta-row__share{ display:flex; align-items:center; gap:.6rem; font-size:.85rem; color:var(--ink-secondary); }
  .post-meta-row__share a{ display:inline-flex; align-items:center; justify-content:center; width:30px; height:30px; border-radius:50%; background:var(--bg-primary); color:var(--primary); }
  .post-meta-row__share a:hover{ background:var(--outline-hover); }
  .post-meta-row__share svg{ width:15px; height:15px; }
  .post-copy-link.copied::after{ content:"Copied!"; position:absolute; margin-top:-2.2rem; font-size:.75rem; background:var(--ink); color:var(--white); padding:.2rem .5rem; border-radius:var(--radius-sm); }

  .post-ai-explore{ max-width:900px; margin:0 auto 1.75rem; display:flex; align-items:center; gap:.75rem; flex-wrap:wrap; }
  .post-ai-explore__label{ font-size:.85rem; font-weight:700; color:var(--ink); }
  .post-ai-explore__pills{ display:flex; gap:.5rem; flex-wrap:wrap; }
  .ai-pill{ display:inline-flex; align-items:center; padding:.4rem 1rem; border-radius:var(--radius-pill); font-size:.85rem; font-weight:600; border:1px solid var(--border); color:var(--ink); background:var(--white); transition:all .2s var(--ease); }
  .ai-pill:hover{ translate:0 -2px; box-shadow:0 8px 18px rgba(11,6,32,.1); }
  .ai-pill--perplexity{ border-color:#C9B8F5; color:#6A3FD6; }
  .ai-pill--perplexity:hover{ background:#F4EFFD; }
  .ai-pill--chatgpt{ border-color:#A9E0CC; color:#10866B; }
  .ai-pill--chatgpt:hover{ background:#EAFBF4; }
  .ai-pill--grok{ border-color:#333; color:var(--ink); }
  .ai-pill--grok:hover{ background:var(--bg-primary); }
  .ai-pill--google{ border-color:#AECBFA; color:#1A56C4; }
  .ai-pill--google:hover{ background:#EDF3FF; }

  .post-toc{ max-width:900px; margin:0 auto 2rem; border:1px solid var(--border); border-radius:var(--radius-sm); padding:1rem 1.25rem; background:var(--bg-primary); }
  .post-toc summary{ cursor:pointer; list-style:none; display:flex; align-items:center; justify-content:space-between; font-family:var(--display); font-weight:700; color:var(--ink); }
  .post-toc summary::-webkit-details-marker{ display:none; }
  .post-toc summary svg{ width:12px; height:8px; transition:rotate .2s var(--ease); }
  .post-toc[open] summary svg{ rotate:180deg; }
  .post-toc ul{ margin:.9rem 0 0; padding-left:1.1rem; }
  .post-toc li{ margin-bottom:.45rem; line-height:1.5; }
  .post-toc a{ color:var(--link); text-decoration:none; }
  .post-toc a:hover{ text-decoration:underline; }

  .post-author-card{ max-width:760px; margin:0 auto; display:flex; gap:1.25rem; align-items:flex-start; padding:1.5rem; border:1px solid var(--border); border-radius:var(--radius-lg); background:var(--bg-primary); }
  /* ARAUK-79 fix: .post-author-card is a flex row and the photo had no flex-basis,
     so it shrank below its own 88px when the bio text ran long -- the browser then
     squeezed the square photo into a tall sliver before object-fit:cover cropped
     it, which is why the face looked sliced. Pin the column to 88px so it can
     never shrink. */
  .post-author-card__photo{ flex:0 0 88px; }
  .post-author-card__photo img{ width:88px; height:88px; border-radius:50%; object-fit:cover; display:block; }
  .post-author-card__body h3{ display:flex; align-items:center; gap:.5rem; font-family:var(--display); font-size:1.05rem; font-weight:800; color:var(--ink); margin:0 0 .5rem; }
  .post-author-card__body h3 a{ color:var(--primary); display:inline-flex; }
  .post-author-card__body h3 a svg{ width:17px; height:17px; }
  .post-author-card__body p{ font-size:.92rem; line-height:1.6; color:var(--ink-secondary); margin:0 0 .75rem; }
  .post-author-card__link{ font-size:.85rem; font-weight:700; color:var(--link); text-decoration:underline; }

  @media (max-width:640px){
    .post-meta-row{ flex-direction:column; align-items:flex-start; }
    .post-author-card{ flex-direction:column; align-items:center; text-align:center; }
  }

  /* ═══════════════ BLOG LISTING: pagination + categories sidebar (ARAUK-79) ═══════════════
     Replaces the old "all 123 on one page, grouped into an invented taxonomy" layout with a
     flat date-sorted grid (10/page) + the live site's own real categories, right-hand sidebar
     as shown on the live listing page. .case-grid/.case-card (ARAUK-17) still do the card work. */
  .blog-layout{ display:grid; grid-template-columns:1fr 300px; gap:clamp(2rem,4vw,3rem); align-items:start; margin-top:2rem; }
  .blog-main{ min-width:0; }
  .blog-sidebar{ position:sticky; top:1.5rem; background:var(--bg-primary); border:1px solid var(--border); border-radius:var(--radius-lg); padding:1.5rem; }
  .blog-sidebar h2{ font-family:var(--display); font-size:1.05rem; font-weight:800; color:var(--ink); margin:0 0 1rem; }
  .blog-sidebar ul{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:.35rem; }
  .blog-sidebar a{ display:flex; justify-content:space-between; align-items:center; gap:.5rem; padding:.55rem .65rem; border-radius:var(--radius-sm); color:var(--ink-secondary); font-size:.9rem; text-decoration:none; }
  .blog-sidebar a:hover, .blog-sidebar a.is-active{ background:var(--outline-hover); color:var(--primary); font-weight:700; }
  .blog-sidebar a span{ font-size:.78rem; color:var(--ink-tertiary); }
  .blog-sidebar a.is-active span{ color:var(--primary); }

  .blog-pagination{ display:flex; justify-content:space-between; align-items:center; gap:1rem; flex-wrap:wrap; margin-top:2.5rem; padding-top:1.5rem; border-top:1px solid var(--border); }
  .blog-pagination span.btn[aria-disabled="true"]{ opacity:.35; pointer-events:none; }
  .blog-pagination__page{ font-size:.85rem; color:var(--ink-secondary); order:1; width:100%; text-align:center; }

  @media (min-width:641px){
    .blog-pagination__page{ order:0; width:auto; }
  }
  @media (max-width:900px){
    .blog-layout{ grid-template-columns:1fr; }
    .blog-sidebar{ position:static; }
  }