/* ==========================================================================
   Interior-page components for the `.vf` design system.
   --------------------------------------------------------------------------
   Every interior template wraps its content in `<div class="vf light vf-page">`
   (a sibling of the chrome's own `.vf` wrappers). This file adds the
   page-level components the homepage doesn't have — interior hero, breadcrumb,
   article/prose body, tech-stack list, process flow, why-us rows, team grid,
   case-study metric bands, listing cards, filter bars, pagination.

   Two rules keep this safe and consistent:
     1. EVERYTHING is scoped under `.vf-page`, so it can never reach the
        header/footer chrome (those are `.vf` WITHOUT `.vf-page`).
     2. Colours come ONLY from the `.vf` theme custom properties
        (--bg/--surface/--surface2/--border/--border-soft/--text/--muted/
        --faint/--accent). So light/dark works for free — when the toggle adds
        `body.dark-theme`, `body.dark-theme .vf` re-points the variables and
        the whole page re-tones with zero extra rules here.

   The homepage's own component classes (.scard/.bcard/.ocard/.icard/.ccard,
   .eyebrow/.sect-head/.btn-accent/.pill, .ptimeline, .expander, .hform …) are
   defined in home-redesign.css under `.vf` — since `.vf-page` IS a `.vf`, those
   styles apply inside interior pages too. Templates reuse them directly; this
   file only adds what's genuinely new, using NON-colliding class names.
   ========================================================================== */

/* Legacy main_additional.css sets `svg, path { transition: .3s }` globally,
   which makes any currentColor icon "blink" its fill during the theme-switch
   View-Transition snapshot. Neutralise it inside our pages (home-redesign.css
   does the same for the hero watermark). */
.vf-page svg, .vf-page path { transition: none; }

/* ---------- dark-mode alternating bands ----------
   home-redesign.css re-tones `.tone-alt` via `.vf.dark .tone-alt`, but interior
   pages keep the wrapper as `vf light` and switch to dark through
   `body.dark-theme` instead — so that rule never fires and the alt bands would
   stay light in dark mode. Re-point the same vars under `body.dark-theme .vf`
   (higher specificity than `.vf.light .tone-alt`, so it wins in dark). Values
   copied from home-redesign.css's `.vf.dark .tone-alt`. */
body.dark-theme .vf .tone-alt {
  --bg: #1e1e1d;
  --bg2: #242423;
  --surface: #2a2a29;
  --surface2: #323130;
  --border: rgba(255, 255, 255, 0.12);
  --border-soft: rgba(255, 255, 255, 0.07);
}

/* The wrapper already inherits `.vf` (font, colour, background:var(--bg),
   overflow:clip, position:relative). Nothing else needed on the wrapper. */

/* ---------- interior page hero ---------- */
/* Smaller than the homepage hero. Big uppercase Oswald title to match the home
   display, a breadcrumb above it, and an optional lead paragraph below. */
.vf-page .page-hero { padding: 36px 0 28px; position: relative; }
.vf-page .page-hero .ph-head { max-width: 60rem; }
.vf-page .page-hero h1,
.vf-page .page-hero .ph-title {
  font-family: var(--font-head); font-weight: 700; text-transform: uppercase;
  font-size: clamp(40px, 6.2vw, 80px); line-height: 0.98; letter-spacing: 0.005em;
  margin: 14px 0 0; color: var(--text); text-wrap: balance;
}
/* article/job/legal pages use a sentence-case headline (not the big uppercase
   display) — smaller, normal weight, like the prototype's .article-title */
.vf-page .page-hero .article-title,
.vf-page h1.article-title {
  font-family: var(--font-head); text-transform: none; font-weight: 600;
  letter-spacing: -0.01em; font-size: clamp(30px, 4.4vw, 56px); line-height: 1.06;
  margin: 14px 0 0; max-width: 22ch; color: var(--text); text-wrap: balance;
}
.vf-page .page-hero .lead {
  font-size: clamp(16px, 1.4vw, 19px); color: var(--muted); line-height: 1.7;
  max-width: 56ch; margin-top: 24px; font-weight: 300;
}
.vf-page .page-hero .hero-cta { margin-top: 34px; }

/* ---------- breadcrumb (Yoast outputs <p id="breadcrumbs">) ---------- */
.vf-page .breadcrumb,
.vf-page #breadcrumbs {
  font-family: var(--font-body); font-size: 13px; color: var(--muted);
  letter-spacing: 0.01em; margin: 0;
}
.vf-page .breadcrumb a,
.vf-page #breadcrumbs a { color: var(--muted); transition: color .2s ease; }
.vf-page .breadcrumb a:hover,
.vf-page #breadcrumbs a:hover { color: var(--accent); }
.vf-page #breadcrumbs .breadcrumb_last { color: var(--accent); }

/* ---------- post meta line (category · date) ---------- */
.vf-page .post-meta {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.14em;
  font-size: 12.5px; font-weight: 500; color: var(--accent); margin: 0 0 6px;
}
.vf-page .post-meta .sep { color: var(--faint); }
.vf-page .post-meta .date, .vf-page .post-meta time { color: var(--muted); letter-spacing: 0.08em; }

/* ---------- chips / tags ---------- */
.vf-page .chips { display: flex; flex-wrap: wrap; gap: 9px; align-items: center; }
.vf-page .chip {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-body); font-size: 13px; font-weight: 400; color: var(--muted);
  background: var(--surface); border: 1px solid var(--border); border-radius: 999px;
  padding: 8px 16px; white-space: nowrap; transition: border-color .2s ease, color .2s ease;
}
.vf-page a.chip:hover { border-color: var(--accent); color: var(--text); }
.vf-page .chip.solid { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.vf-page .chip img { width: 22px; height: 22px; border-radius: 50%; object-fit: cover; }

/* ---------- article body / prose (the single most reused piece) ----------
   Long-form content from the_content() / WYSIWYG meta. Drives entirely off the
   theme vars so legal pages, blog posts, project descriptions all read clean in
   both modes. */
.vf-page .article-body, .vf-page .prose { max-width: 72ch; color: var(--text); }
.vf-page .article-body.full, .vf-page .prose.full { max-width: none; }
.vf-page .article-body > *:first-child, .vf-page .prose > *:first-child { margin-top: 0; }
.vf-page .article-body p, .vf-page .prose p {
  font-family: var(--font-body); font-size: 16.5px; line-height: 1.8;
  color: var(--muted); margin: 0 0 22px; font-weight: 300;
}
.vf-page .article-body h2, .vf-page .prose h2 {
  font-family: var(--font-head); font-weight: 600; color: var(--text);
  font-size: clamp(24px, 2.6vw, 34px); line-height: 1.15; margin: 48px 0 16px;
}
.vf-page .article-body h3, .vf-page .prose h3 {
  font-family: var(--font-head); font-weight: 600; color: var(--text);
  font-size: clamp(19px, 1.8vw, 24px); line-height: 1.2; margin: 34px 0 12px;
}
.vf-page .article-body h4, .vf-page .prose h4 {
  font-family: var(--font-head); font-weight: 600; color: var(--text);
  font-size: 19px; margin: 26px 0 10px;
}
.vf-page .article-body a, .vf-page .prose a {
  color: var(--accent); text-decoration: underline; text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
.vf-page .article-body ul, .vf-page .article-body ol,
.vf-page .prose ul, .vf-page .prose ol { margin: 0 0 22px 22px; padding: 0; }
.vf-page .article-body li, .vf-page .prose li {
  font-size: 16px; line-height: 1.75; color: var(--muted); margin-bottom: 10px; font-weight: 300;
}
.vf-page .article-body blockquote, .vf-page .prose blockquote {
  border-left: 3px solid var(--accent); padding: 4px 0 4px 24px; margin: 28px 0;
  font-size: 19px; font-style: italic; color: var(--text); font-family: var(--font-body);
}
/* The [blog_info_banner] CTA shortcode gets wrapped in (often deeply nested)
   quote blocks in the editor. Each wrapper adds a green left border + 24px left
   indent, so the card rendered narrower than the body copy and shoved to the
   right — with stray green bars beside it. When a quote block contains the CTA
   card, strip the quote styling so the card spans the full article width and
   lines up with the surrounding text. */
.vf-page .article-body blockquote:has(.blog-info),
.vf-page .prose blockquote:has(.blog-info) {
  border: 0; margin: 0; padding: 0; font-style: normal;
}
/* Empty quote blocks left over in post content (an editor artifact — a quote
   block whose only content is an empty paragraph) otherwise render as orphan
   green bars. Hide any quote block whose sole content is an empty paragraph;
   real quotes contain text or a heading, so they're unaffected. */
.vf-page .article-body blockquote:has(p:only-child:empty),
.vf-page .prose blockquote:has(p:only-child:empty) {
  display: none;
}
.vf-page .article-body img, .vf-page .prose img { border-radius: var(--radius); margin: 28px 0; }
.vf-page .article-body table, .vf-page .prose table {
  width: 100%; border-collapse: collapse; margin: 28px 0; font-size: 15px;
}
.vf-page .article-body th, .vf-page .article-body td,
.vf-page .prose th, .vf-page .prose td {
  border: 1px solid var(--border); padding: 12px 14px; text-align: left; color: var(--muted);
}
.vf-page .article-body th, .vf-page .prose th {
  font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.04em;
  font-size: 13px; background: var(--surface2); color: var(--text);
}
.vf-page .article-body hr, .vf-page .prose hr { border: none; border-top: 1px solid var(--border); margin: 40px 0; }

/* two-column article layout: body + sticky aside */
.vf-page .post-layout { display: grid; grid-template-columns: minmax(0,1fr) 320px; gap: 56px; align-items: start; }
.vf-page .post-aside { position: sticky; top: 96px; display: flex; flex-direction: column; gap: 26px; }
.vf-page .post-aside .aside-title { font-family: var(--font-head); font-size: 18px; font-weight: 600; color: var(--text); }
/* "Have a question?" CTA: its arrow svg uses stroke="currentColor". In dark mode
   the legacy global `*{ color: var(--whiteColor) }` rule paints the <path> white,
   so the arrow turned white on the green button. Pin the stroke to the accent ink
   so the arrow stays dark (matching the button label) in light and dark modes. */
.vf-page .post-aside .btn-accent svg path { stroke: var(--accent-ink); }
.vf-page .post-aside ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.vf-page .post-aside li a {
  /* line-height added so TOC titles that wrap onto two lines aren't cramped */
  display: block; padding: 9px 0; font-size: 14px; line-height: 1.5; color: var(--muted);
  border-bottom: 1px solid var(--border-soft); transition: color .2s ease;
}
.vf-page .post-aside li a:hover { color: var(--accent); }
.vf-page .post-aside li.is-current a { color: var(--accent); font-weight: 500; }
.vf-page .post-aside .share-icons { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; font-size: 13px; color: var(--muted); }
.vf-page .post-aside .share-icons a {
  width: 38px; height: 38px; border: 1px solid var(--border); border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center; color: var(--muted);
  transition: border-color .2s ease, color .2s ease, transform .2s ease;
}
.vf-page .post-aside .share-icons a:hover { border-color: var(--accent); color: var(--accent); transform: translateY(-2px); }
.vf-page .post-aside .share-icons svg { width: 17px; height: 17px; fill: currentColor; }

/* ---------- single-post hero meta line (author · date · categories) ----------
   Title sits on top; the meta line (author chip · date · categories) drops BELOW
   it. The chip keeps its own (non-uppercase) styling while date/categories stay
   uppercase. */
.vf-page .page-hero .article-title { margin-top: 16px; }
.vf-page .page-hero .post-meta { margin: 22px 0 0; row-gap: 8px; }
.vf-page .post-meta .post-author { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 9px; }
.vf-page .post-meta .chip { text-transform: none; letter-spacing: 0; }
/* The TOC aside is lifted to the top-right (see the margin-top:-1000px trick below),
   so the hero meta line must stop before that column or it slides under the TOC.
   Reserve the aside's footprint: 320px column + 56px grid gap = 376px. Reset on
   mobile (<=1000px) where the TOC stacks above the article instead. */
.vf-page .page-hero .post-meta { max-width: calc(100% - 376px); }

/* ---------- gap between the title block (hero) and the article body ----------
   `.vf section` defaults to 104px vertical padding; the post body sits right
   under the hero, so trim its top padding to tighten that seam (request #1). */
.vf-page .post-body { padding-top: 36px; }

/* ---------- desktop: lift the Table of contents to the very top ----------
   The aside lives in `.post-body` (so its `position:sticky` can track the long
   article), but visually we want it pinned near the top beside the hero. Rather
   than a fragile fixed pull (whose landing point depends on the hero's height and
   font rendering), we give it a deliberately huge negative margin: position:sticky
   then CLAMPS it to exactly its `top` (96px). So the TOC always sits 96px from the
   top — at first paint and while scrolling — regardless of content height. Reset on
   mobile below. */
.vf-page .post-aside { margin-top: -1000px; }
/* Logged-in admins: the fixed nav sits 32px lower (below the admin bar), so the TOC
   sticks 32px lower too (96 + 32) to keep the same clearance below the nav. */
body.admin-bar .vf-page .post-aside { top: 128px; }

/* ---------- Table of contents wrapper / collapsible dropdown ----------
   Desktop: the list is always open and the chevron is hidden, so `.toc` reads as
   a plain heading + list. Mobile rules (in the responsive block) turn it into a
   closed-by-default dropdown and move it above the article. */
.vf-page .toc { display: flex; flex-direction: column; gap: 14px; }
.vf-page .toc-toggle {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin: 0; cursor: default;
}
.vf-page .toc-chevron { display: none; flex-shrink: 0; transition: transform .25s ease; }

/* ---------- in-content CTA + author-bio cards (legacy .blog-info / .blog-bio) ----------
   These blocks come from the_content() as raw markup from the old theme, hard-coded
   to a dark card with a washed-out sage button. Re-skin them onto the vf token
   system so they tone correctly in light/dark and match the article's type scale
   (requests #6 and #7). */
.vf-page .blog-info,
.vf-page .blog-bio {
  display: grid; align-items: stretch; gap: 0; margin: 44px 0;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); overflow: hidden;
}
/* contact CTA: a clean single-column card. Its legacy image is a wide banner
   that already bakes in the same heading, so it crops badly in a column — drop it. */
.vf-page .blog-info { grid-template-columns: 1fr; }
.vf-page .blog-info__img-wrapper { display: none; }
.vf-page .blog-info__text-content { max-width: 62ch; }
/* author bio: a smaller, rounded portrait on the left; bio text on the right.
   The card itself is padded so the photo sits inset (not edge-to-edge). */
.vf-page .blog-bio {
  grid-template-columns: 230px 1fr;
  gap: clamp(24px, 3vw, 40px);
  padding: clamp(24px, 3vw, 40px);
}

/* text columns: drop the legacy aspect-ratio / space-evenly, use calm padding */
.vf-page .blog-info__text-content,
.vf-page .blog-bio__content {
  width: auto; aspect-ratio: auto;
  padding: clamp(28px, 3vw, 46px);
  display: flex; flex-direction: column; justify-content: center; gap: 16px;
}
.vf-page .bio-content__header { display: flex; align-items: center; gap: 12px; margin: 0; }
.vf-page .bio-content__header-text { font-family: var(--font-body); font-size: 14px; color: var(--muted); margin: 0; }
.vf-page .bio-content__link { width: 34px; height: 34px; flex-shrink: 0; }
.vf-page .bio-content__link svg { width: 100%; height: 100%; fill: var(--text); }
/* bio footer: the "Check all articles" button and the LinkedIn icon share one
   row at the bottom of the card (the icon was moved here from the top). */
.vf-page .bio-content__footer { display: flex; align-items: center; gap: 18px; margin-top: 4px; }

/* `#blog_page` prefix needed to beat the legacy id rules (`#blog_page h2` forces
   Yanone 62px; `.vf-page .article-body a` paints the button text green-on-green). */
.vf-page #blog_page .blog-info__title {
  font-family: var(--font-head); font-weight: 600; color: var(--text);
  font-size: clamp(24px, 2.5vw, 32px); line-height: 1.12; letter-spacing: -0.01em;
  text-transform: none; margin: 0;
}
.vf-page .blog-info__text {
  font-family: var(--font-body); font-size: 16px; line-height: 1.7;
  color: var(--muted); font-weight: 300; margin: 0;
}
/* contact CTA: extra breathing room between the title and the description
   (#blog_page needed to beat the shared title rule's `margin:0`) */
.vf-page #blog_page .blog-info .blog-info__title { margin-bottom: 16px; }

/* button → the vf accent button (was a min-width:240px washed sage block) */
.vf-page #blog_page .blog-info__button {
  align-self: flex-start; width: auto; min-width: 0; max-width: none;
  background: var(--accent); color: var(--accent-ink);
  border: 1px solid var(--accent); border-radius: 10px;
  padding: 14px 28px; margin-top: 6px;
  font-family: var(--font-body); font-weight: 500; font-size: 15px;
  text-decoration: none; text-align: center;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22), 0 1px 2px rgba(0, 0, 0, .10);
  transition: background-color .22s ease, transform .22s ease, box-shadow .22s ease;
}
.vf-page #blog_page .blog-info__button:hover {
  background: color-mix(in oklab, var(--accent) 80%, white);
  color: var(--accent-ink) !important; /* beats legacy `color:#fff!important` on hover */
  transform: translateY(-1px);
}

/* images fill their column edge-to-edge (override the .article-body img margin/radius) */
.vf-page .blog-info__img-wrapper,
.vf-page .blog-bio__img-wrapper { width: auto; }
.vf-page .blog-info__img-wrapper img,
.vf-page .blog-bio__img-wrapper img {
  width: 100%; height: 100%; max-height: none;
  object-fit: cover; display: block; border-radius: 0; margin: 0;
}

/* ---------- author bio: spacing + element tweaks (request: image #9) ----------
   The card is padded, so the content column drops its own padding and stacks from
   the top with the button pushed to the very bottom (aligned with the photo). */
.vf-page .blog-bio__content { padding: 0; justify-content: flex-start; gap: 12px; }
/* drop the "Author's Bio" label; keep just the LinkedIn icon, sized down and
   sitting right above (near) the title */
.vf-page .blog-bio .bio-content__header { margin-bottom: 2px; }
.vf-page .blog-bio .bio-content__header-text { display: none; }
.vf-page .blog-bio .bio-content__link { width: 28px; height: 28px; }
/* rounded, inset portrait that stretches to align its bottom with the button */
.vf-page .blog-bio__img-wrapper img { border-radius: 14px; }
/* push the button to the very bottom of the column for coherence with the photo
   (#blog_page beats the shared button rule's `margin-top:6px`) */
.vf-page #blog_page .blog-bio .blog-info__button { margin-top: auto; align-self: flex-start; }

/* ---------- in-content CTA separator band (legacy .cta_separator) ----------
   A centred mid-article call-to-action. The legacy markup is a `<section>` (so it
   picks up `.vf section`'s 104px padding) on a hard-coded dark-green block with a
   washed sage button. Re-skin it as a soft accent-tinted panel that tones with the
   theme, and turn its button into the vf accent button. */
.vf-page .cta_separator {
  background: color-mix(in oklab, var(--accent) 10%, var(--surface));
  border: 1px solid color-mix(in oklab, var(--accent) 24%, var(--border));
  border-radius: var(--radius); margin: 44px 0;
  padding: clamp(40px, 5vw, 72px) clamp(24px, 4vw, 56px);
}
.vf-page .cta_separator .cta_wrapper {
  max-width: 640px; margin: 0 auto; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 16px;
}
.vf-page #blog_page .cta_separator .services__title {
  font-family: var(--font-head); font-weight: 600; color: var(--text);
  font-size: clamp(26px, 3vw, 40px); line-height: 1.1; letter-spacing: -0.01em;
  text-transform: none; margin: 0;
}
.vf-page .cta_separator .description,
.vf-page .cta_separator .description p {
  font-family: var(--font-body); font-size: 16.5px; line-height: 1.7;
  /* The legacy compiled CSS still forces the inner <p> to a light #D9D9D9
     !important (it was made for the old solid dark-green CTA). On the new
     light panel that washes the text out, so override it here. Use a
     theme-token mix (dark in light theme, light in dark theme) and bump the
     weight to 400 so the subtitle stays readable but subordinate to the head.
     !important is required to beat the legacy rule's !important. */
  color: color-mix(in oklab, var(--text) 78%, var(--muted)) !important;
  font-weight: 400; margin: 0; max-width: 52ch;
}
.vf-page #blog_page .cta_separator .simple_button {
  margin-top: 8px; align-self: center;
  width: auto; min-width: 0; max-width: none;
  background: var(--accent); color: var(--accent-ink) !important;
  border: 1px solid var(--accent); border-radius: 10px;
  padding: 15px 32px; font-family: var(--font-body); font-weight: 500; font-size: 15px;
  text-decoration: none; text-align: center;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22), 0 1px 2px rgba(0, 0, 0, .10);
  transition: background-color .22s ease, transform .22s ease, box-shadow .22s ease;
}
.vf-page #blog_page .cta_separator .simple_button:hover {
  background: color-mix(in oklab, var(--accent) 80%, white);
  color: var(--accent-ink) !important; transform: translateY(-1px);
}

/* ---------- stats strip (big number + label) ---------- */
.vf-page .stats { display: flex; flex-wrap: wrap; gap: clamp(24px, 5vw, 64px); align-items: flex-start; }
.vf-page .stat .num, .vf-page .stat .counter {
  font-family: var(--font-head); font-weight: 700; line-height: 1;
  font-size: clamp(30px, 4vw, 46px); color: var(--text); display: block;
}
.vf-page .stat .lbl { font-size: 13.5px; color: var(--muted); margin-top: 8px; max-width: 18ch; }

/* ---------- generic card grid (.cards/.card) — listings & misc ---------- */
.vf-page .cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); gap: 18px; }
.vf-page .cards.cols-3 { grid-template-columns: repeat(3, 1fr); }
.vf-page .cards.cols-2 { grid-template-columns: repeat(2, 1fr); }
.vf-page .card {
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  padding: clamp(24px, 2.6vw, 34px); display: flex; flex-direction: column; gap: 12px;
  will-change: transform;
  transition: border-color .2s ease, transform .35s cubic-bezier(.2,.7,.3,1), box-shadow .3s ease;
}
.vf-page .card:hover { border-color: var(--accent); box-shadow: 0 18px 44px rgba(0,0,0,0.16); }
.vf-page .card .idx { font-family: var(--font-head); font-size: 26px; font-weight: 700; color: var(--accent); }
.vf-page .card h3 { font-family: var(--font-head); font-size: 21px; line-height: 1.2; color: var(--text); }
.vf-page .card p { font-size: 14.5px; color: var(--muted); line-height: 1.7; }
.vf-page .card ul { list-style: none; margin: 0; padding: 0; }
.vf-page .card ul li { font-size: 13.5px; color: var(--muted); padding: 5px 0 5px 18px; position: relative; }
.vf-page .card ul li::before { content: "›"; position: absolute; left: 0; color: var(--accent); font-weight: 700; }
.vf-page .card .card-cta { margin-top: auto; padding-top: 18px; }

/* ---------- article/resource listing cards (.articles/.article) ----------
   Mirrors the homepage .bcard look so blog/insights/resources match home. */
.vf-page .articles { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 18px; }
.vf-page .article {
  display: flex; flex-direction: column; gap: 14px; background: var(--surface);
  border: 1px solid var(--border); border-radius: 14px; overflow: hidden;
  color: inherit; will-change: transform;
  transition: border-color .2s ease, transform .35s cubic-bezier(.2,.7,.3,1), box-shadow .3s ease;
}
.vf-page .article:hover { border-color: var(--accent); box-shadow: 0 18px 44px rgba(0,0,0,0.16); }
.vf-page .article .thumb { aspect-ratio: 16/10; background: var(--surface2); background-size: cover; background-position: center; }
.vf-page .article .a-body { display: flex; flex-direction: column; gap: 12px; padding: 24px 26px 28px; flex: 1; }
.vf-page .article .a-meta { display: flex; align-items: center; gap: 10px; font-size: 12.5px; color: var(--faint); }
.vf-page .article .a-meta .cat { color: var(--accent); letter-spacing: 0.1em; text-transform: uppercase; }
.vf-page .article h3 { font-family: var(--font-head); font-size: 20px; line-height: 1.3; color: var(--text); flex: 1; }
.vf-page .article .a-read { display: inline-flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--muted); transition: color .2s ease; }
.vf-page .article .a-read svg { transition: transform .25s ease; }
.vf-page .article:hover .a-read { color: var(--accent); }
.vf-page .article:hover .a-read svg { transform: translateX(4px); }

/* ---------- service cards with 2-column feature lists (.svc-grid) ----------
   Reuses the homepage .scard look (defined in home-redesign.css); this only
   adds the bottom feature list. */
/* equal-height cards (default grid stretch): the copy stays at the top and the
   feature list is pinned to the bottom (margin-top:auto), so the lists
   bottom-align across every card in a row. */
.vf-page .svc-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
/* one service per row (single column) so each point sits on its own line
   instead of wrapping across two narrow columns; margin-top:auto pins to bottom */
.vf-page .svc-grid .scard ul {
  list-style: none; margin: auto 0 0; padding: 18px 0 0; border-top: 1px solid var(--border);
  display: grid; grid-template-columns: 1fr; gap: 8px;
}
.vf-page .svc-grid .scard ul li { list-style: none; font-size: 12.5px; line-height: 1.5; color: var(--muted); padding: 0 0 0 13px; position: relative; }
.vf-page .svc-grid .scard ul li::before { content: "›"; position: absolute; left: 0; color: var(--accent); font-weight: 700; }

/* ---------- tech-stack list (.stack-list/.stack-row) ---------- */
.vf-page .stack-list { border: 1px solid var(--border); border-radius: 14px; overflow: hidden; background: var(--surface); }
.vf-page .stack-row {
  display: grid; grid-template-columns: 200px 1fr; gap: 24px; align-items: center;
  padding: 18px clamp(20px, 2.4vw, 30px); border-bottom: 1px solid var(--border);
}
.vf-page .stack-row:last-child { border-bottom: none; }
.vf-page .stack-row .stack-label {
  font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.06em;
  font-size: 14px; font-weight: 600; color: var(--text);
}
.vf-page .stack-row .chips .chip { font-size: 12px; padding: 6px 14px; background: var(--surface2); }

/* ---------- connected process flow (.proc / .proc-step / .proc-node) ----------
   New names (NOT .pstep) so the homepage's .ptimeline .pstep rules don't bleed in. */
.vf-page .proc { display: grid; grid-template-columns: repeat(4, 1fr); gap: 28px; }
.vf-page .proc-step { position: relative; }
.vf-page .proc-node {
  width: 52px; height: 52px; border-radius: 50%; border: 2px solid var(--accent);
  color: var(--accent); background: var(--surface);
  font-family: var(--font-head); font-weight: 700; font-size: 21px;
  display: flex; align-items: center; justify-content: center; margin-bottom: 22px;
  position: relative; z-index: 1;
}
.vf-page .proc-step:not(:last-child)::before {
  content: ""; position: absolute; top: 26px; left: 52px; right: -28px; height: 2px;
  background: linear-gradient(90deg, var(--accent) 0%, var(--border) 100%); z-index: 0;
}
.vf-page .proc-step h3 { font-family: var(--font-head); font-size: 20px; color: var(--text); margin-bottom: 10px; }
.vf-page .proc-step p { font-size: 14px; color: var(--muted); line-height: 1.7; }
.vf-page .proc-step .pmeta {
  display: inline-block; margin-top: 14px; font-family: var(--font-head);
  text-transform: uppercase; letter-spacing: 0.08em; font-size: 12px; color: var(--accent);
}
/* breathing room between the "Our Process" heading and the timeline row */
.vf-page .services-process__flow { margin-top: 48px; }

/* ---------- why-us cards (.why-list/.why-row) ----------
   Compact 2-up card grid (was full-width rows with a big number gutter and a
   lot of wasted horizontal space). Number sits on top, then title + copy. */
/* feedback (Services): the "Why Work with Hygge Software?" heading sat too close
   to the cards — give the section heading the same breathing room the other
   service sections use before their grids. */
.vf-page .services-advantages .sect-head { margin-bottom: 48px; }
.vf-page .why-list { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; }
.vf-page .why-row {
  display: block;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  padding: 30px 32px; transition: box-shadow .25s ease, border-color .2s ease;
}
.vf-page .why-row:hover { box-shadow: 0 18px 44px rgba(0,0,0,0.10); border-color: var(--accent); }
.vf-page .why-row .why-num { display: block; font-family: var(--font-head); font-weight: 700; font-size: 30px; color: var(--accent); line-height: 1; margin-bottom: 16px; }
.vf-page .why-row h3 { font-family: var(--font-head); font-size: 20px; color: var(--text); margin-bottom: 14px; }
.vf-page .why-row p { font-size: 14.5px; color: var(--muted); line-height: 1.7; }

/* ---------- vertical timeline (.timeline) ---------- */
.vf-page .timeline { border-left: 2px solid var(--border); padding-left: 34px; display: flex; flex-direction: column; gap: 38px; }
.vf-page .timeline .t-item { position: relative; }
.vf-page .timeline .t-item::before {
  content: ""; position: absolute; left: -41px; top: 6px; width: 14px; height: 14px;
  background: var(--accent); border-radius: 50%; box-shadow: 0 0 0 5px var(--bg);
}
.vf-page .timeline .t-item .t-when { font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.1em; font-size: 13px; color: var(--accent); }
.vf-page .timeline .t-item h3 { font-family: var(--font-head); font-size: 22px; color: var(--text); margin: 6px 0 10px; }
.vf-page .timeline .t-item p { font-size: 15px; color: var(--muted); line-height: 1.75; }

/* ---------- team photo grid (.team-grid/.team-card) ---------- */
.vf-page .team-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 20px; }
.vf-page .team-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px; overflow: hidden;
  transition: border-color .2s ease, box-shadow .3s ease, transform .35s cubic-bezier(.2,.7,.3,1);
}
.vf-page .team-card:hover { border-color: var(--accent); box-shadow: 0 18px 44px rgba(0,0,0,0.16); }
.vf-page .team-card .photo { width: 100%; aspect-ratio: 4/5; background-size: cover; background-position: center top; background-color: var(--surface2); }
.vf-page .team-card .photo img { width: 100%; height: 100%; object-fit: cover; object-position: center top; }
.vf-page .team-card .t-body { padding: 18px 20px 22px; }
.vf-page .team-card h3 { font-family: var(--font-head); font-size: 18px; color: var(--text); margin-bottom: 4px; }
.vf-page .team-card .role { font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.08em; font-size: 12px; color: var(--accent); }

/* ---------- case-study metric band (.cs-band) ---------- */
.vf-page .cs-band {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 24px;
  border: 1px solid var(--border); border-radius: 16px; padding: clamp(26px, 3vw, 40px); background: var(--surface);
}
.vf-page .cs-band .m .v, .vf-page .cs-band .m .counter {
  display: block; font-family: var(--font-head); font-weight: 700; line-height: 1.05;
  /* font dialled down from 40px max: a long single-word value (e.g. "Headquarters")
     has to fit one column without breaking mid-word — this size keeps it whole at
     every breakpoint while staying bold. */
  font-size: clamp(22px, 2.4vw, 34px); color: var(--accent); margin-bottom: 8px;
}
.vf-page .cs-band .m .k { font-size: 13px; color: var(--muted); }
/* feedback (Projects): the metric value lives in `.v` with the animated number in
   a child `.counter` and the "+"/"%" suffix as a sibling text node. The global
   `.counter{display:block}` pushed that suffix onto a second line (e.g. "200" then
   "+"), mis-sizing the block. Making the counter inline keeps each number + suffix
   on one line (there's no break opportunity inside e.g. "200+"). Mirrors the
   about-numbers band fix above. */
.vf-page .cs-band .m .counter { display: inline; }
/* values can be long free text too (e.g. "Three iterations", "$50K–$100K"), so the
   value must be allowed to WRAP at spaces — `white-space:nowrap` here forced those
   onto one line and overflowed into the next column. min-width:0 lets the grid
   column shrink (grid items default to min-width:auto). We deliberately do NOT use
   overflow-wrap:break-word: that split single words mid-character ("Headquarter|s").
   Words stay whole (the reduced font above keeps even long ones fitting a column). */
.vf-page .cs-band .m { min-width: 0; }
.vf-page .cs-band .m .v { overflow-wrap: normal; word-break: normal; hyphens: none; }

/* ---------- raw form controls inside .hform (non-CF7 custom forms) ----------
   home-redesign.css styles `.vf .hform .wpcf7 input` (needs a .wpcf7 ancestor)
   and the `.form-container__*` chrome; these rules cover the plain controls of
   custom forms like the resource report-download form so they match too. */
.vf-page .hform .form-container__input,
.vf-page .hform input[type="text"],
.vf-page .hform input[type="email"],
.vf-page .hform input[type="tel"],
.vf-page .hform select,
.vf-page .hform textarea {
  font-family: var(--font-body); font-size: 14.5px; color: var(--text);
  background: var(--surface2); border: 1px solid var(--border); border-radius: 10px;
  padding: 14px 16px; width: 100%; outline: none; transition: border-color .15s ease; resize: vertical;
}
.vf-page .hform input::placeholder, .vf-page .hform textarea::placeholder { color: var(--faint); }
.vf-page .hform input:focus, .vf-page .hform textarea:focus { border-color: var(--accent); }
.vf-page .hform .form-container__button,
.vf-page .hform input[type="submit"]:not(.wpcf7-form-control),
.vf-page .hform button[type="submit"]:not(.wpcf7-form-control) {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  align-self: flex-start; width: auto; cursor: pointer;
  font-family: var(--font-body); font-size: 15px; font-weight: 500;
  padding: 15px 30px; border-radius: 10px; border: 1px solid transparent;
  background: var(--accent); color: var(--accent-ink);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.22), 0 1px 2px rgba(0,0,0,.10);
  transition: transform .22s cubic-bezier(.3,.7,.3,1), background-color .22s ease, box-shadow .22s ease;
}
.vf-page .hform .form-container__button:hover,
.vf-page .hform input[type="submit"]:not(.wpcf7-form-control):hover {
  background: color-mix(in oklab, var(--accent) 80%, white); transform: translateY(-1px);
}
.vf-page .hform .single_input_holder { display: flex; flex-direction: column; gap: 14px; }
.vf-page .hform fieldset { border: none; margin: 0; padding: 0; min-width: 0; }

/* ---------- resource report-download form polish ----------
   All rules here are scoped to `#report_form` (unique to single-resources.php),
   NOT `.hform` — the About referral form and Vacancy application form are also
   `.vf-page .hform` CF7 forms, and a wider scope would strip their legacy
   checkbox box / red invalid-state cue too. */
/* title: the legacy `#report_page h3` (main_additional.css: Yanone, 36px) beats
   the redesign head-font rule by ID; win it back to the page's Oswald heading.
   Scoped to the form, so the success-message <h3> (outside #report_form) keeps
   its own styling. font-family/line-height are re-declared on purpose — they are
   needed to outrank `#report_page h3`, not just to repeat the shared rule. */
.vf-page #report_form .form-container__title {
  font-family: var(--font-head); font-size: 22px; font-weight: 600;
  line-height: 1.2; text-align: left; color: var(--text); margin: 0 0 18px;
}
/* fields: the legacy `.form-container__input { margin-bottom: 20px }` doubles up
   with the holder's 14px flex gap, making the spacing too loose — drop it so
   only the gap controls the rhythm */
.vf-page #report_form .form-container__input { margin-bottom: 0; }
/* checkbox: home-redesign.css styles the real <input> as a custom box, but the
   legacy system hides it (`.wpcf7-acceptance input { display:none }`) and draws
   its own box via `label::before` plus a checkmark via `label::after` (the latter
   shown once JS adds `.label-selected`). Reveal the styled input and drop BOTH
   legacy pseudo-elements — otherwise the legacy checkmark stacks on top of the
   input's own, giving a doubled tick. */
.vf-page #report_form .wpcf7-acceptance input[type="checkbox"] { display: inline-block; }
.vf-page #report_form .wpcf7-acceptance label::before,
.vf-page #report_form .wpcf7-acceptance label::after { content: none; }
/* report-download form success message: hidden until send-report.js adds
   `.send_report` to the wrapper (matches the legacy toggle, kept theme-aware) */
.vf-page .send_message { display: none; }
.vf-page .send_report .send_message { display: block; }
.vf-page .send_report #report_form { display: none; }

/* ---------- contact panel (reuse home .hform via .contact-grid) ---------- */
.vf-page .contact-grid {
  display: grid; grid-template-columns: 1fr 1.1fr; gap: clamp(32px, 5vw, 64px);
  border: 1px solid var(--border); border-radius: 20px; background: var(--surface); padding: clamp(32px, 4vw, 56px);
}
.vf-page .contact-grid .cg-side { display: flex; flex-direction: column; gap: 18px; }
.vf-page .contact-grid h2 { font-size: clamp(30px, 3.6vw, 46px); }

/* ---------- two-column bordered grid (.grid-2) ---------- */
.vf-page .grid-2 {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
  background: var(--border); border: 1px solid var(--border); border-radius: 16px; overflow: hidden;
}
.vf-page .grid-2 .cell { background: var(--surface); padding: clamp(28px, 3.2vw, 44px); }
.vf-page .grid-2 .cell h3 { font-family: var(--font-head); font-size: 24px; color: var(--text); margin-bottom: 14px; }
.vf-page .grid-2 .cell p { font-size: 15px; color: var(--muted); line-height: 1.75; }

/* The global `.vf section { padding: 104px 0 }` rule pushes the filter bar far
   below the hero title. Trim the listing's top padding so the pills sit closer
   to the title/subtitle (the hero still supplies its own 28px bottom padding).
   `.projects-listing` is the projects page's own section — give it the same
   tight top padding so its filter pills hug the title too (request #1). */
.vf-page .posts-listing,
.vf-page .projects-listing { padding-top: 24px; }

/* ---------- filter bar (listing pages) ---------- */
/* desktop: keep chips + search on ONE row. nowrap stops the search box from
   dropping below the pills; the chips block (.f-chips) still wraps internally.
   margin-bottom adds breathing room between the bar/search and the grid below. */
.vf-page .filter-bar { display: flex; flex-wrap: nowrap; align-items: center; gap: 12px; margin-bottom: 32px; }
/* flex:1 lets the chips block take the free space and shrink (min-width:0) so the
   search box fits beside it instead of pushing itself onto a new line */
.vf-page .filter-bar .f-chips { display: flex; flex-wrap: wrap; gap: 9px; flex: 1 1 auto; min-width: 0; }
/* The projects page has NO search box: its filter element is BOTH `filter-bar`
   and `f-chips` on the same node (not a nested chips block). So `.filter-bar`'s
   `nowrap` applied to it directly and the pills overflowed off the row instead
   of wrapping. When both classes sit on one element, switch back to wrap so the
   pills flow onto the next line when they run out of horizontal space (#3). */
.vf-page .filter-bar.f-chips { flex-wrap: wrap; }
.vf-page .filter-bar .f-chip,
.vf-page .filter-bar .projects-filter__button {
  font-family: var(--font-body); font-size: 13.5px; color: var(--muted); cursor: pointer;
  background: var(--surface); border: 1px solid var(--border); border-radius: 999px;
  padding: 9px 18px; transition: all .2s ease; white-space: nowrap;
}
.vf-page .filter-bar .f-chip:hover,
.vf-page .filter-bar .projects-filter__button:hover { border-color: var(--accent); color: var(--text); }
.vf-page .filter-bar .f-chip.is-active,
.vf-page .filter-bar .projects-filter__button--active {
  /* Keep the SAME weight as the inactive pill: bolding the active pill made its
     text wider, which shifted every other pill on selection. The accent
     background already marks the selection clearly. `font-weight:400` is set
     explicitly (not just inherited) so no legacy `--active` rule can re-bold it
     and bring the layout shift back (request #2). */
  font-weight: 400;
  background: var(--accent); border-color: var(--accent); color: var(--accent-ink);
}
.vf-page .filter-bar .f-search {
  /* align-self:flex-start keeps the search at the TOP, level with the first row
     of pills, instead of being vertically centred against the taller chips block */
  margin-left: auto; flex: 0 0 auto; align-self: flex-start; display: flex; align-items: center; gap: 8px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 999px; padding: 0 16px;
}
.vf-page .filter-bar .f-search input {
  border: none; background: none; outline: none; color: var(--text);
  font-family: var(--font-body); font-size: 14px; padding: 11px 0; min-width: 180px;
}
.vf-page .filter-bar .f-search input::placeholder { color: var(--faint); }

/* ---------- pagination ---------- */
.vf-page .pagination, .vf-page #pagination-wrapper { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: center; margin-top: 48px; }
.vf-page .pagination a, .vf-page .pagination span,
.vf-page #pagination-wrapper a, .vf-page #pagination-wrapper span {
  min-width: 42px; height: 42px; display: inline-flex; align-items: center; justify-content: center;
  padding: 0 12px; border: 1px solid var(--border); border-radius: 10px;
  font-family: var(--font-head); font-size: 15px; color: var(--muted);
  transition: border-color .2s ease, color .2s ease, background .2s ease;
}
.vf-page .pagination a:hover, .vf-page #pagination-wrapper a:hover { border-color: var(--accent); color: var(--accent); }
.vf-page .pagination .current, .vf-page .pagination [aria-current],
.vf-page #pagination-wrapper .current { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

/* ---------- vacancy rows (careers listing) ---------- */
/* The careers listing sits in a `.vf section` (default 104px top padding), which
   left a large empty gap under the hero copy. Tighten just this section's top so
   the filter chips sit closer to the description. */
.vf-page .vacancies-listing { padding-top: 28px; }
.vf-page .vacancies-card__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.vf-page .vacancy-row {
  display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  padding: 24px clamp(22px, 2.6vw, 32px); transition: border-color .2s ease, box-shadow .3s ease;
}
.vf-page .vacancy-row:hover { border-color: var(--accent); box-shadow: 0 14px 34px rgba(0,0,0,0.08); }
.vf-page .vacancy-row .vr-main { display: flex; flex-direction: column; gap: 12px; }
.vf-page .vacancy-row__title { font-family: var(--font-head); font-size: clamp(20px, 2vw, 26px); color: var(--text); transition: color .2s ease; }
.vf-page .vacancy-row:hover .vacancy-row__title { color: var(--accent); }
.vf-page .vacancy-row .vr-actions { display: flex; align-items: center; gap: 12px; }
.vf-page .vacancy-row .vacancies-card__share-btn {
  width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--border); background: transparent;
  color: var(--muted); cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
  transition: border-color .2s ease, color .2s ease;
}
.vf-page .vacancy-row .vacancies-card__share-btn:hover { border-color: var(--accent); color: var(--accent); }

/* vacancy perks/info cards */
.vf-page .vacancies__info-list { list-style: none; }
/* The job list loads via AJAX, so until it populates the perks block would
   render high up (in view), get its scroll-reveal "used up" there, then jump
   down when the jobs arrive — a visible flash. Hide it (no layout space) while
   loading; projects-filter.js removes `vf-pending` once the jobs are injected,
   so the perks enter cleanly in their final position. Gated on `vf-js` so it
   stays visible when JS is unavailable. */
html.vf-js .vf-page .vacancies__info-list.vf-pending { display: none; }
.vf-page .vacancies__info-item { align-items: flex-start; }
.vf-page .vacancies__info-img { width: 48px; height: 48px; object-fit: contain; margin-bottom: 6px; }
.vf-page .vacancies__info-text { font-size: 15px; color: var(--muted); line-height: 1.7; }

/* ---------- centered pages (404, thank-you) ---------- */
.vf-page .center-page { padding: clamp(60px, 12vw, 140px) 0; }
.vf-page .center-page .wrap { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 6px; }
.vf-page .center-page .eyebrow { justify-content: center; }
.vf-page .center-page .lead { margin: 16px auto 0; }
.vf-page .center-page .hero-cta { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; margin-top: 30px; }
.vf-page .center-page .breadcrumb { margin-bottom: 18px; }

/* ---------- 404 page: text on the left, animated logo on the right ---------- */
.vf-page .not-found-page { padding: clamp(60px, 12vw, 140px) 0; }
.vf-page .not-found-page__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: clamp(32px, 6vw, 96px);
}
.vf-page .not-found-page__content { flex: 1 1 auto; min-width: 0; }
.vf-page .not-found-page .hero-cta { display: flex; gap: 14px; flex-wrap: wrap; }

.vf-page .not-found-page__logo { flex: 0 0 auto; line-height: 0; }
.vf-page .not-found-page__logo svg {
  width: clamp(150px, 24vw, 320px); height: auto; display: block; overflow: visible;
  transform-origin: center;
}
/* the inner arrow keeps nudging left, trying to slot into the rest of the
   mark — but it's too big to fit, so it bumps and springs back each time */
.vf-page .not-found-page__logo .nf-mark__inner {
  transform-box: fill-box; transform-origin: center;
  animation: nf-try-fit 3s cubic-bezier(.36, 0, .2, 1.2) infinite;
}
/* the accent chevron gives a tiny shove back on each bump, selling the "won't fit" */
.vf-page .not-found-page__logo .nf-mark__outer {
  transform-box: fill-box; transform-origin: center;
  animation: nf-resist 3s ease-out infinite;
}
@keyframes nf-try-fit {
  0%   { transform: translateX(0); }
  12%  { transform: translateX(-5px); }   /* presses in toward the logo */
  24%  { transform: translateX(0); }      /* bumped back out — doesn't fit */
  36%  { transform: translateX(-3px); }   /* tries again, a little softer */
  48%  { transform: translateX(0); }
  100% { transform: translateX(0); }      /* rests, then repeats */
}
@keyframes nf-resist {
  0%, 8% { transform: translateX(0); }
  14%    { transform: translateX(-1.5px); } /* small give when the arrow hits it */
  22%    { transform: translateX(0); }
  34%    { transform: translateX(-1px); }
  46%    { transform: translateX(0); }
  100%   { transform: translateX(0); }
}
/* stack on narrow screens: logo above the text, slightly smaller */
@media (max-width: 860px) {
  .vf-page .not-found-page__inner { flex-direction: column-reverse; align-items: flex-start; }
  .vf-page .not-found-page__logo svg { width: clamp(120px, 34vw, 200px); }
}
/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
  .vf-page .not-found-page__logo svg,
  .vf-page .not-found-page__logo .nf-mark__inner,
  .vf-page .not-found-page__logo .nf-mark__outer { animation: none; }
}

/* ---------- single vacancy (job detail) ----------
   The body lives in a <section>, which inherits the homepage's `padding:104px 0`.
   That left a big empty band under the hero, so tighten the top here — the hero
   already supplies its own bottom padding. */
.vf-page .vacancy-body { padding-top: 20px; }

/* Pull the title up to the header. The legacy container adds a big top padding
   (style.min.css clamp ≈ 53px) and the hero adds its own — but the breadcrumb is
   empty on vacancies, so all that space sat blank above the title. */
.vf-page .vacancy_page__container { padding-top: 0; }
.vf-page #vacancy_page .page-hero { padding-top: 24px; }

.vf-page .vacancy_page__wrapper { display: grid; grid-template-columns: minmax(0,1fr) 380px; gap: 56px; align-items: start; margin-top: 8px; }
/* Block (not the legacy flex+gap:30px) so spacing under the tabs is controlled
   solely by the tab bar's own margin below. */
.vf-page .vacancy_tabs__wrapper { display: block; min-width: 0; }

/* Tabs as an underline tab bar — clearly NOT the rounded hero tags. The buttons
   carry `chip`-free markup, so only these rules style them. */
.vf-page .vacancy-tabs {
  display: flex; flex-wrap: wrap; gap: 0 26px;
  border-bottom: 1px solid var(--border); margin-bottom: 18px;
}
.vf-page .vacancy-tabs .projects-filter__button {
  font-family: var(--font-head); font-weight: 500; font-size: 16px; letter-spacing: .01em;
  color: var(--muted); background: none; border: 0; border-radius: 0;
  padding: 0 2px 16px; margin-bottom: -1px; cursor: pointer;
  border-bottom: 2px solid transparent;
  transition: color .2s ease, border-color .2s ease;
}
.vf-page .vacancy-tabs .projects-filter__button:hover { color: var(--text); }
.vf-page .vacancy-tabs .projects-filter__button--active { color: var(--text); border-bottom-color: var(--accent); }

/* Show the full job text — the legacy 11-line clamp / 400px cap (style.min.css)
   went with the now-removed "Show more" button. */
.vf-page .vacancy-body .tab-content { max-height: none; overflow: visible; font-size: inherit; }
.vf-page .vacancy-body .tab-content__content { display: block; overflow: visible; -webkit-line-clamp: unset; color: var(--text); }

/* Editors set inline `color:#0d0d0d` on paragraphs/headings in the WYSIWYG, which
   is invisible on the dark background. Inline styles can only be beaten with
   !important — so in dark mode only, re-tone the job text to the theme colours
   (links stay accent). Light mode keeps the editor's near-black, which reads fine. */
body.dark-theme .vf-page #vacancy_page .tab-content__content :is(p, ul, ol, li, span, em) { color: var(--muted) !important; }
body.dark-theme .vf-page #vacancy_page .tab-content__content :is(h1, h2, h3, h4, h5, h6, strong, b) { color: var(--text) !important; }
body.dark-theme .vf-page #vacancy_page .tab-content__content a { color: var(--accent) !important; }

/* Apply form — ONE card. The aside is the card; the legacy CF7 `.form-container`
   brings its own background+shadow (style.min.css), which created the nested
   "two wrappers" look — flatten it and drop its duplicate "Apply Now" title so
   the outer <h2> "Apply for this role" is the single heading. */
.vf-page .vacancy-apply { position: sticky; top: 96px; border: 1px solid var(--border); border-radius: 18px; background: var(--surface); padding: clamp(26px,3vw,36px); }
.vf-page .vacancy-apply h2 { font-family: var(--font-head); font-weight: 600; font-size: 24px; line-height: 1.15; margin: 0 0 20px; }
.vf-page .vacancy-apply .form-container {
  background: none; box-shadow: none; border-radius: 0;
  max-width: none; width: 100%; padding: 0; text-align: left;
}
.vf-page .vacancy-apply .form-container__wrapper { display: block; justify-content: flex-start; }
.vf-page .vacancy-apply .form-container__title { display: none; }

/* Upload CV — full-width dashed dropzone with an upload icon (legacy was a
   narrow 200px inline pill). Icon is drawn from currentColor so it tracks the
   label colour on hover. */
.vf-page #vacancy_page .form-container__file-upload { width: 100%; }
.vf-page #vacancy_page .form-container__file-label {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; max-width: none; box-sizing: border-box;
  padding: 16px 18px; border: 1px dashed var(--border); border-radius: 12px;
  background: var(--surface2); color: var(--muted);
  font-family: var(--font-body); font-size: 14px; font-weight: 500; cursor: pointer;
  transition: border-color .2s ease, color .2s ease, background-color .2s ease;
}
.vf-page #vacancy_page .form-container__file-label:hover { border-color: var(--accent); color: var(--text); background: var(--surface); }
.vf-page #vacancy_page .form-container__file-label::before {
  content: ""; width: 18px; height: 18px; flex-shrink: 0; background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'/%3E%3Cpolyline points='17 8 12 3 7 8'/%3E%3Cline x1='12' y1='3' x2='12' y2='15'/%3E%3C/svg%3E") center/contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'/%3E%3Cpolyline points='17 8 12 3 7 8'/%3E%3Cline x1='12' y1='3' x2='12' y2='15'/%3E%3C/svg%3E") center/contain no-repeat;
}

/* Consent checkbox — modernise to the site-wide input-drawn control (accent
   fill + checkmark), matching other forms. The vacancy form ships a LEGACY
   custom box (style.min.css hides the real input and draws `label::before` /
   `.label-selected::after`); neutralise that and re-show the real input. */
.vf-page #vacancy_page .wpcf7-acceptance label::before,
.vf-page #vacancy_page .wpcf7-acceptance label.label-selected::after { content: none; display: none; }
.vf-page #vacancy_page .wpcf7-acceptance label { gap: 10px; align-items: flex-start; margin: 0; }
.vf-page #vacancy_page .wpcf7-acceptance .wpcf7-list-item-label { transform: none; color: var(--muted); }
.vf-page #vacancy_page .wpcf7-acceptance input[type="checkbox"] {
  appearance: none; -webkit-appearance: none; display: inline-block;
  width: 20px; height: 20px; margin: 1px 0 0; flex-shrink: 0;
  border: 1px solid var(--border); border-radius: 6px; background: var(--surface2);
  cursor: pointer; transition: background-color .15s ease, border-color .15s ease;
}
.vf-page #vacancy_page .wpcf7-acceptance input[type="checkbox"]:hover { border-color: var(--accent); }
.vf-page #vacancy_page .wpcf7-acceptance input[type="checkbox"]:checked {
  background-color: var(--accent); border-color: var(--accent);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2310231c' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5l3 3 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: center; background-size: 13px;
}

/* Apply (submit) — full width to match the inputs and the Upload CV button.
   Legacy style.min.css caps it at max-width:240px, so clear that too. */
.vf-page #vacancy_page .wpcf7 input[type="submit"] { width: 100%; max-width: none; }
@media (max-width: 1000px) {
  .vf-page .vacancy_page__wrapper { grid-template-columns: 1fr; gap: 36px; }
  .vf-page .vacancy-apply { position: static; }
}

/* ---------- author page ---------- */
.vf-page .author__title-wrapper { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.vf-page .author__title-wrapper .article-title { margin: 0; }
.vf-page .bio-content__link { color: var(--accent); display: inline-flex; transition: transform .2s ease; }
.vf-page .bio-content__link:hover { transform: translateY(-2px); }

/* ---------- empty state ---------- */
.vf-page .empty-list { text-align: center; padding: 60px 0; color: var(--muted); font-size: 16px; }

/* ---------- page show-more expander (distinct from chrome [data-expander]) ----------
   Uses [data-pexpander] + #target so it is wired ONLY by redesign-pages.js and
   never double-bound by the chrome's [data-expander] handler. Reuses the same
   grid-rows height animation as the homepage .expander. */
.vf-page .pexpander { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .6s cubic-bezier(.22,1,.36,1); }
.vf-page .pexpander.on { grid-template-rows: 1fr; }
.vf-page .pexpander > .pexp-inner { min-height: 0; overflow: hidden; }
.vf-page [data-pexpander] .pexp-more { display: inline; }
.vf-page [data-pexpander] .pexp-less { display: none; }
.vf-page [data-pexpander][aria-expanded="true"] .pexp-more { display: none; }
.vf-page [data-pexpander][aria-expanded="true"] .pexp-less { display: inline; }
.vf-page [data-pexpander] .exp-arrow { transition: transform .3s ease; }
.vf-page [data-pexpander][aria-expanded="true"] .exp-arrow { transform: rotate(180deg); }

/* ---------- simple accordion (services dev-areas / tech stacks) ---------- */
.vf-page .acc { border: 1px solid var(--border); border-radius: 14px; overflow: hidden; background: var(--surface); }
.vf-page .acc-item { border-bottom: 1px solid var(--border); }
.vf-page .acc-item:last-child { border-bottom: none; }
.vf-page .acc-head {
  width: 100%; text-align: left; background: none; border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
  padding: 20px clamp(20px, 2.4vw, 28px); font-family: var(--font-head); font-size: 18px; color: var(--text);
}
.vf-page .acc-head .acc-ic { color: var(--accent); transition: transform .3s ease; flex-shrink: 0; }
.vf-page .acc-item.on .acc-head .acc-ic { transform: rotate(45deg); }
.vf-page .acc-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .45s cubic-bezier(.22,1,.36,1); }
.vf-page .acc-item.on .acc-body { grid-template-rows: 1fr; }
.vf-page .acc-body > .acc-inner { min-height: 0; overflow: hidden; }
.vf-page .acc-body .acc-inner-pad { padding: 0 clamp(20px, 2.4vw, 28px) 24px; color: var(--muted); font-size: 15px; line-height: 1.75; }

/* ==========================================================================
   About page — restyle legacy sections/sliders to the .vf system.
   Swiper markup (classes + structure) is kept intact so the existing JS still
   drives the testimonials/history carousels; we only restyle appearance.
   Higher specificity (.vf-page .about-*) wins over the legacy main_additional.
   ========================================================================== */
/* hero image below the title */
.vf-page .about-hero-img { padding-top: 8px; }
/* legacy style.min.css hides `.about__img` at desktop (display:none) — force it visible here */
.vf-page .about-hero-img .about__img { display: block; width: 100%; border-radius: 18px; max-height: 520px; object-fit: cover; }

/* ===== intro tabs: vertical word-list + quote panel (matches live reference) ===== */
.vf-page .about-tabs { padding-top: 96px; padding-bottom: 72px; }
/* lay the tab list and the quote side by side */
.vf-page .about-tabs .wrap { display: flex; gap: clamp(32px, 8vw, 140px); align-items: center; flex-wrap: wrap; }
/* stack the tab words in a column (overrides the legacy centred-column + chip-row) */
/* overflow:visible kills the legacy mobile rule (.tabs gets overflow-x:scroll
   under 768px, which on this vertical layout shows a stray scrollbar) */
.vf-page .about-tabs .tabs { flex-direction: column; align-items: flex-start; justify-content: flex-start; gap: clamp(14px, 1.6vw, 26px); margin-bottom: 0; height: auto; overflow: visible; flex: 0 0 auto; }
/* each tab is a big condensed word, faint until it is the active one */
.vf-page .about-tabs .tabs__button {
  font-family: var(--font-head); font-weight: 700; font-size: clamp(26px, 2.6vw, 40px); line-height: 1.05;
  color: var(--faint); background: transparent; border: 0; border-radius: 0; padding: 0; cursor: pointer;
  text-align: left; transition: color .25s ease;
}
.vf-page .about-tabs .tabs__button:hover { color: var(--muted); }
.vf-page .about-tabs .tabs__button.active,
.vf-page .about-tabs .tabs__button[aria-selected="true"] { background: transparent; border: 0; color: var(--text); }
/* quote column. panels are display-toggled (the tab JS just swaps .active) */
/* height:auto !important overrides the inline height the legacy tab JS sets on
   mobile (it assumed absolutely-positioned panels); our panels are in flow */
.vf-page .about-tabs .tabs__content { flex: 1 1 480px; max-width: 760px; height: auto !important; overflow: visible; display: block; }
.vf-page .about-tabs .tabs__panel { position: static; display: none; }
/* fade + slide the quote in each time the tab JS swaps the .active class */
.vf-page .about-tabs .tabs__panel.active { display: block; animation: aboutTabFade .45s cubic-bezier(.2,.7,.3,1) both; }
@keyframes aboutTabFade { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
.vf-page .about-tabs .tabs__panel-text {
  position: relative; padding: 30px 0; font-size: clamp(17px, 1.5vw, 21px); line-height: 1.75;
  color: var(--muted); font-weight: 300;
}
/* decorative opening/closing quotation marks, restored from the reference design */
.vf-page .about-tabs .tabs__panel-text::before,
.vf-page .about-tabs .tabs__panel-text::after {
  content: ''; position: absolute; width: 32px; height: 24px; background-size: cover;
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="32" height="24" viewBox="0 0 32 24" fill="none"><path d="M7.6074 23.268C5.5434 23.268 3.88073 22.5513 2.6194 21.118C1.35807 19.6273 0.727399 17.6493 0.727399 15.184C0.727399 12.0307 1.64473 9.078 3.4794 6.326C5.31407 3.574 7.57873 1.53867 10.2734 0.219998L11.1334 1.68199C9.98673 2.59933 8.95473 3.71733 8.0374 5.036C7.1774 6.35466 6.4894 7.96 5.9734 9.852L7.7794 10.368C9.61407 10.9413 11.0474 11.8013 12.0794 12.948C13.1687 14.0947 13.7134 15.4993 13.7134 17.162C13.7134 18.9967 13.1114 20.4873 11.9074 21.634C10.7034 22.7233 9.27007 23.268 7.6074 23.268ZM25.6674 23.268C23.6034 23.268 21.9407 22.5513 20.6794 21.118C19.4181 19.6273 18.7874 17.6493 18.7874 15.184C18.7874 12.0307 19.7047 9.078 21.5394 6.326C23.3741 3.574 25.6387 1.53867 28.3334 0.219998L29.1934 1.68199C28.0467 2.59933 27.0147 3.71733 26.0974 5.036C25.2374 6.35466 24.5494 7.96 24.0334 9.852L25.8394 10.368C27.6741 10.9413 29.1074 11.8013 30.1394 12.948C31.2287 14.0947 31.7734 15.4993 31.7734 17.162C31.7734 18.9967 31.1714 20.4873 29.9674 21.634C28.7634 22.7233 27.3301 23.268 25.6674 23.268Z" fill="%23779c99"/></svg>');
}
.vf-page .about-tabs .tabs__panel-text::before { top: 0; left: 0; }
.vf-page .about-tabs .tabs__panel-text::after { bottom: 0; right: 0; }

/* ===== vision / mission: open two columns + button (matches live reference) ===== */
.vf-page .about-info .wrap { display: flex; align-items: center; justify-content: space-between; gap: clamp(32px, 5vw, 80px); flex-wrap: wrap; }
.vf-page .about-info__list { display: flex; gap: clamp(32px, 5vw, 80px); max-width: 820px; list-style: none; margin: 0; padding: 0; }
.vf-page .about-info__item { flex: 1 1 0; min-width: 240px; }
.vf-page .about-info__title { display: flex; align-items: center; gap: 16px; margin-bottom: 18px; font-family: var(--font-head); font-weight: 700; font-size: clamp(24px, 2.2vw, 34px); line-height: 1.1; color: var(--text); }
.vf-page .about-info__title img { width: clamp(44px, 3.4vw, 60px); height: clamp(44px, 3.4vw, 60px); object-fit: contain; flex-shrink: 0; }
.vf-page .about-info__text { font-size: 15px; line-height: 1.75; color: var(--muted); }
.vf-page .about-info .sect-actions { margin: 0; flex: 0 0 auto; }

/* numbers section: even row of stats, each number + suffix and each label on ONE line */
.vf-page .about-numbers .stats { margin-top: 48px; justify-content: space-between; gap: 32px 40px; }
.vf-page .about-numbers .stat { flex: 0 0 auto; }
/* feedback (About): the figures (incl. the text "UA" stat) read too small — bump
   the number size up a step so each stat number has more presence. text-transform
   uppercases the "ua" text stat so it reads "UA" as intended (digits unaffected). */
.vf-page .about-numbers .stat .num { font-size: clamp(48px, 5.5vw, 76px); white-space: nowrap; text-transform: uppercase; }
/* the animated counter is display:block globally — make it inline so the "+"/"%"
   suffix stays on the same line as the number instead of dropping below it */
.vf-page .about-numbers .stat .counter { display: inline; }
/* the "+"/"%" suffix glyphs (esp. % in Oswald) render oversized — drop them to a
   smaller superscript-style size so they read as a unit with the number */
.vf-page .about-numbers .stat .num-suffix { font-size: 0.6em; vertical-align: baseline; }
/* feedback (About): add more padding between the stat number and its label */
.vf-page .about-numbers .stat .lbl { max-width: none; white-space: nowrap; margin-top: 18px; }

/* testimonials slider */
.vf-page .about-reviewes__header { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; flex-wrap: wrap; margin-bottom: 40px; }
.vf-page .about-reviewes__header .sect-head { margin-bottom: 0; }
.vf-page .reviewes-slider { overflow: hidden; }
.vf-page .reviewes-slider .swiper-slide {
  height: auto; background: var(--surface); border: 1px solid var(--border); border-radius: 16px;
  padding: 32px; display: flex; flex-direction: column; gap: 18px;
}
.vf-page .reviewes-slider__stars { display: flex; gap: 5px; list-style: none; margin: 0; padding: 0; }
.vf-page .reviewes-slider__star { width: 16px; height: 16px; }
.vf-page .reviewes-slider__star::before { content: '★'; color: var(--accent); font-size: 16px; line-height: 1; }
.vf-page .reviewes-slider .testimonial__text { font-size: 16px; line-height: 1.7; color: var(--text); flex: 1; }
.vf-page .reviewes-slider .testimonial__name { font-family: var(--font-head); font-size: 16px; color: var(--text); }
.vf-page .reviewes-slider .testimonial__position { font-size: 13px; color: var(--muted); }
.vf-page .reviewes-slider__user-info { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.vf-page .reviewes-slider__verefied { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--accent); }
.vf-page .reviewes-slider__verefied svg { color: var(--accent); }
.vf-page .about-reviewes__pagination { display: flex; justify-content: center; gap: 8px; margin-top: 26px; }
.vf-page .swiper-pagination-bullet { background: var(--faint); opacity: 1; }
.vf-page .swiper-pagination-bullet-active { background: var(--accent); }

/* company history slider */
.vf-page .about-history__header { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; flex-wrap: wrap; margin-bottom: 40px; }
.vf-page .about-history__header .sect-head { margin-bottom: 0; }
.vf-page .about-history__buttons { display: flex; gap: 10px; }
/* Swiper's stylesheet positions .swiper-button-prev/next absolutely over the
   slider and adds a glyph via ::after — that's the broken overlapping arrow.
   Pin them back into the header flow and drop the default glyph so our circular
   buttons with inline SVGs render correctly. */
.vf-page .about-history__buttons > div,
.vf-page .about-history__buttons .swiper-button-prev,
.vf-page .about-history__buttons .swiper-button-next {
  position: static; margin: 0; top: auto; left: auto; right: auto;
  /* !important + flex-basis beat Swiper's width:calc(...) (~32px) so the buttons
     stay perfect circles instead of squished ovals */
  width: 46px !important; height: 46px !important; flex: 0 0 46px; border-radius: 50%;
  border: 1px solid var(--border); color: var(--text);
  display: flex; align-items: center; justify-content: center; cursor: pointer; transition: border-color .2s ease, color .2s ease, opacity .2s ease;
}
.vf-page .about-history__buttons .swiper-button-prev::after,
.vf-page .about-history__buttons .swiper-button-next::after { content: none; }
.vf-page .about-history__buttons > div:hover { border-color: var(--accent); color: var(--accent); }
.vf-page .about-history__buttons .swiper-button-disabled { opacity: .35; cursor: default; }
.vf-page .about-history__buttons svg { width: 18px; height: auto; }
.vf-page .history-list { overflow: hidden; }
/* timeline cards: leave headroom at the top for the connecting line + node */
/* display:flex !important overrides legacy `.history-list__item{display:grid!important}`
   which placed the copy in a centered 1fr row — that made each title start at a
   different height. Flow layout + top alignment makes every title start level. */
.vf-page .history-list .swiper-slide.history-list__item {
  height: auto; background: var(--surface); border: 1px solid var(--border); border-radius: 16px; padding: 56px 30px 30px;
  display: flex !important; flex-direction: column; align-items: flex-start; justify-content: flex-start;
  gap: 14px; position: relative; overflow: visible;
}
/* the node dot sits on the timeline, with a soft pulsing ring */
.vf-page .history-list .process-list__circle {
  position: absolute; top: 22px; left: 30px; width: 18px; height: 18px; border-radius: 50%;
  background: var(--accent); border: 3px solid var(--surface); box-shadow: 0 0 0 2px var(--accent); z-index: 2;
  animation: histDotPulse 2.4s ease-in-out infinite;
}
@keyframes histDotPulse {
  0%, 100% { box-shadow: 0 0 0 2px var(--accent); }
  50% { box-shadow: 0 0 0 7px color-mix(in oklab, var(--accent) 28%, transparent); }
}
/* the connecting line runs from each node across the card and the gap to the
   next node; it animates in (scaleX) once the slider scrolls into view */
.vf-page .history-list .history-list__line {
  display: block; position: absolute; top: 30px; left: 0; right: -30px; height: 2px; z-index: 1;
  background: color-mix(in oklab, var(--accent) 50%, transparent);
  transform: scaleX(0); transform-origin: left center; transition: transform .8s ease;
}
.vf-page .history-list .history-list__line.in-view { transform: scaleX(1); }
.vf-page .history-list .swiper-slide:last-child .history-list__line { display: none; }
.vf-page .history-list .process-list__title { font-family: var(--font-head); font-size: 20px; color: var(--text); }
.vf-page .history-list .process-list__text { font-size: 14.5px; line-height: 1.7; color: var(--muted); }

/* team grid (redesign-global converts the slider to a grid; restyle the cards) */
/* all members in a single row on desktop */
.vf-page .about-teams__slider .swiper-wrapper { grid-template-columns: repeat(5, 1fr); gap: 18px; }
.vf-page .about-teams__slider .swiper-slide { grid-column: auto; }
/* breathing room between the section heading and the cards */
.vf-page .about-teams .sect-head { margin-bottom: 44px; }
.vf-page .about-teams__slider .swiper-slide {
  border-radius: 16px; overflow: hidden; position: relative; display: flex; align-items: flex-end;
  background-size: cover; background-position: center top; min-height: 340px; border: 0;
}
.vf-page .about-teams__slide-content {
  width: 100%; padding: 22px 20px 18px; display: flex; flex-direction: column; gap: 4px;
  background: linear-gradient(to top, rgba(10,10,9,0.82) 0%, rgba(10,10,9,0.35) 55%, transparent 100%); color: #fff;
}
.vf-page .about-teams__name { font-family: var(--font-head); font-size: 18px; color: #fff; }
.vf-page .about-teams__position { font-size: 13px; color: rgba(255,255,255,0.78); }
.vf-page .about-teams__slide-content .social-icons { list-style: none; margin: 10px 0 0; padding: 0; display: flex; gap: 8px; }
/* solid white chip + dark glyph reads clearly on the dark portrait gradient
   (a translucent circle with a white glyph was too low-contrast) */
.vf-page .about-teams__slide-content .social-icons__link { width: 36px; height: 36px; background: #fff; border: 1px solid #fff; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; color: #1b1b19; transition: background .2s ease, border-color .2s ease, color .2s ease; }
.vf-page .about-teams__slide-content .social-icons__link:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
/* literal dark fill (not currentColor) — the legacy `*{color:var(--whiteColor)}`
   forces the path's color to white in dark mode, which made the glyph vanish on
   the white chip. A fixed dark fill keeps it legible in both themes. */
.vf-page .about-teams__slide-content .social-icons__link svg { width: 18px; height: 18px; fill: #1b1b19; }
.vf-page .about-teams__slide-content .social-icons__link svg path { fill: #1b1b19; }
.vf-page .about-teams__slide-content .social-icons__link:hover svg,
.vf-page .about-teams__slide-content .social-icons__link:hover svg path { fill: #fff; }

/* certificates logo grid */
.vf-page .about-certificates__list {
  list-style: none; margin: 56px 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 18px;
}
.vf-page .about-certificates__item {
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  display: flex; align-items: center; justify-content: center; padding: 24px; min-height: 140px;
}
.vf-page .about-certificates__item img { max-height: 120px; width: auto; object-fit: contain; }

/* referral program: legacy section is a fixed-height green flex band with white
   text — reset it to a normal section so our contact panel lays out cleanly */
.vf-page .about-refers { background: transparent; display: block; height: auto; align-items: normal; }
.vf-page .contact-grid { align-items: start; max-height: none; overflow: visible; }
/* vertically centre the email field/button against the copy on the left */
.vf-page .about-refers .contact-grid { align-items: center; }
/* legacy joins the input+submit into one pill (overflow:hidden, no gap) — open
   it up so there's clear spacing between the field and the Send button */
.vf-page .about-refers__form { overflow: visible; align-items: center; gap: 16px; }
.vf-page .about-refers__form .wpcf7-form-control-wrap { flex: 1 1 240px; }
.vf-page .about-refers__form input[type="submit"] { height: auto; align-self: stretch; }
.vf-page .about-refers .cg-side { text-align: left; }
.vf-page .about-refers__title { color: var(--text); text-align: left; }
.vf-page .about-refers__text { color: var(--muted); text-align: left; }
/* referral copy-link */
.vf-page .about-refers__copy-link { display: inline-flex; align-items: center; gap: 10px; margin-top: 8px; color: var(--text); cursor: pointer; }
.vf-page .about-refers__copy-link a { color: inherit; }
.vf-page .about-refers__copy-link svg { color: var(--accent); cursor: pointer; }

/* ==========================================================================
   Services page — restyle legacy sections to the .vf system.
   Keeps legacy hooks the JS needs: #services_show + [data-visible]/.hide,
   .accordion/.panel (max-height toggled by app.min.js), .process-list.
   ========================================================================== */
/* frameworks intro: two columns (copy + logo strip) */
/* single-column header (the framework-logo strip was removed) */
.vf-page .services-direction__header { margin-bottom: 56px; }
.vf-page .services-direction__header .sect-head { margin-bottom: 0; }
.vf-page .direction-icons__list { display: flex; flex-wrap: wrap; gap: 12px; list-style: none; margin: 0 0 16px; padding: 0; }
.vf-page .direction-icons__item {
  width: 56px; height: 56px; background: var(--surface); border: 1px solid var(--border);
  border-radius: 12px; display: flex; align-items: center; justify-content: center; padding: 11px;
}
.vf-page .direction-icons__item img { max-width: 100%; max-height: 100%; object-fit: contain; }
.vf-page .services-direction__text { font-size: 14px; color: var(--muted); }

/* direction services use .svc-grid + .scard; legacy .hide removes overflow items
   until #services_show reveals them. scard h3/p come from home-redesign.css. */
.vf-page .services-direction__list.svc-grid { margin-top: 0; list-style: none; padding: 0; }
.vf-page .direction-list__item.hide { display: none; }
.vf-page .direction-list__title { font-size: 21px; line-height: 1.2; color: var(--text); }
/* feedback (Services): tighten + unify the line spacing inside the "What We Do"
   cards. The description used line-height 1.7 while the feature list below used
   1.5 — match the paragraph to 1.5 so the whole card copy reads as one tight,
   consistent block. (The selectors out-rank `.vf .scard p {line-height:1.7}`.) */
.vf-page .services-direction__list .scard p,
.vf-page .direction-list__text { font-size: 14px; color: var(--muted); line-height: 1.5; }

/* feedback (Services): collapsible card grids — show only the first 3 cards by
   default and reveal the rest with a "Show more" button. The button uses the
   shared [data-pexpander] hook (redesign-pages.js), which toggles `.on` on the
   grid; without `.on` we hide every card from the 4th onward. */
.vf-page .svc-grid.is-collapsible:not(.on) > li:nth-child(n+4),
.vf-page .ind-grid.is-collapsible:not(.on) > li:nth-child(n+4) { display: none; }
.vf-page .svc-more { display: flex; justify-content: center; margin-top: 28px; }
.vf-page .svc-more__btn { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }
.vf-page .svc-more__chev { transition: transform .25s ease; }
/* flip the chevron when the grid is expanded (button aria-expanded toggled by JS) */
.vf-page .svc-more__btn[aria-expanded="true"] .svc-more__chev { transform: rotate(180deg); }

/* accordion (legacy <button class="accordion"> with inner .panel toggled by JS) */
.vf-page .services-acc { display: flex; flex-direction: column; gap: 12px; }
.vf-page .services-acc .accordion {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px;
  width: 100%; text-align: left; cursor: pointer; background: var(--surface);
  border: 1px solid var(--border); border-radius: 14px; padding: 20px clamp(20px, 2.4vw, 28px);
  font-family: var(--font-head); font-size: 19px; color: var(--text); transition: border-color .2s ease;
}
.vf-page .services-acc .accordion:hover,
.vf-page .services-acc .accordion.active { border-color: var(--accent); }
/* hide the legacy accordion's own +/− pseudo indicator (we render .accordion__ic) */
.vf-page .services-acc .accordion::before, .vf-page .services-acc .accordion::after { content: none; }
.vf-page .services-acc .accordion__label { flex: 1; }
.vf-page .services-acc .accordion__ic { font-family: var(--font-head); font-size: 26px; line-height: 1; color: var(--accent); transition: transform .3s ease; }
.vf-page .services-acc .accordion.active .accordion__ic { transform: rotate(45deg); }
/* .panel max-height is animated by app.min.js — keep its transition, theme the body */
.vf-page .services-acc .accordion .panel {
  flex-basis: 100%; width: 100%; overflow: hidden;
  color: var(--muted); font-size: 15px; line-height: 1.75;
}
.vf-page .services-acc .accordion .panel ul { margin: 16px 0 8px 20px; }
.vf-page .services-acc .accordion .panel li { margin-bottom: 8px; }
/* tech-stack icon lists inside panels */
.vf-page .services__items-list { list-style: none; margin: 16px 0 8px; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 18px; }
.vf-page .services__items-list li { display: flex; flex-direction: column; align-items: center; gap: 8px; text-align: center; }
.vf-page .panel__item-img { width: 42px; height: 42px; object-fit: contain; }
.vf-page .panel__item-text { font-size: 13px; color: var(--muted); }

/* process — clean two-column step grid with accent dots */
.vf-page .services-process__list.process-list {
  list-style: none; margin: 56px 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 44px 56px;
}
.vf-page .process-list__item { position: relative; padding-left: 44px; padding-bottom: 0; }
.vf-page .process-list__circle { position: absolute; left: 0; top: 4px; width: 16px; height: 16px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 5px var(--bg); z-index: 1; }
.vf-page .process-list__line { display: none; }
.vf-page .process-list__title { font-family: var(--font-head); font-size: 22px; color: var(--text); margin-bottom: 8px; }
.vf-page .process-list__text { font-size: 15px; color: var(--muted); line-height: 1.75; }

/* services .scard number badge sits above the title (legacy markup has no .num
   wrapper of its own, so give it the homepage rhythm) */
.vf-page .direction-list__item.scard .num { margin-bottom: -4px; }

/* --------------------------------------------------------------------------
   Industries — static card grid (replaces the legacy accordion).
   The legacy theme set `.services-experience { display:flex }`, which collapsed
   the .wrap to a narrow centred column. Force normal block flow so the grid
   spans the full content width like every other section.
   -------------------------------------------------------------------------- */
.vf-page .services-experience { display: block; }
.vf-page .services-experience .sect-head { margin-bottom: 48px; }
.vf-page .ind-grid {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px;
}
.vf-page .ind-card {
  border: 1px solid var(--border); border-radius: 14px; background: var(--surface);
  padding: 26px 26px 24px; display: flex; flex-direction: column; gap: 16px;
  will-change: transform;
  transition: border-color .2s ease, transform .35s cubic-bezier(.2, .7, .3, 1), box-shadow .3s ease;
}
.vf-page .ind-card:hover { border-color: var(--accent); box-shadow: 0 18px 44px rgba(0, 0, 0, 0.10); }
.vf-page .ind-card__head { display: flex; align-items: baseline; gap: 12px; }
.vf-page .ind-card__num { font-family: var(--font-head); font-size: 13px; letter-spacing: 0.1em; color: var(--faint); transition: color .35s ease; }
.vf-page .ind-card:hover .ind-card__num { color: var(--accent); }
.vf-page .ind-card h3 { font-family: var(--font-head); font-size: 20px; line-height: 1.15; color: var(--text); }
/* the WYSIWYG <ul> of solutions, themed with accent markers */
.vf-page .ind-card ul {
  list-style: none; margin: auto 0 0; padding-top: 16px; border-top: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 9px;
}
.vf-page .ind-card li { position: relative; padding-left: 18px; font-size: 13.5px; color: var(--muted); line-height: 1.5; }
.vf-page .ind-card li::before { content: "›"; position: absolute; left: 0; color: var(--accent); font-weight: 700; }

/* --------------------------------------------------------------------------
   Technologies — labelled chip rows (replaces the legacy accordion).
   Uses the shared .stack-list/.stack-row/.chip components; this only tunes the
   tech-logo image inside each chip (logos need contain, not a circular crop).
   -------------------------------------------------------------------------- */
.vf-page .services-stacks__list { margin-top: 48px; }
.vf-page .stack-row .chip { padding: 8px 14px; }
.vf-page .stack-row .chip img { width: 20px; height: 20px; border-radius: 4px; object-fit: contain; }

/* ==========================================================================
   Single project (case study) detail
   ========================================================================== */
/* tighten the gap from the site header to the title: `.vf section` adds 104px
   of top padding by default which, stacked on the hero's own top padding, left
   a huge void above the title (request: image #17). Trim the section's top
   padding here and shrink the hero's so the title sits close to the header. */
.vf-page .project_page__container { padding-top: 40px; }
.vf-page .project-hero { padding: 12px 0 8px; }
.vf-page .project_page__container > .wrap > * + * { margin-top: 56px; }

/* ---------- project facts: modern borderless info columns ----------
   Was four bordered/hover cards (felt heavy and dated — request: image #18).
   Drop the card chrome and present each fact as a clean column under a thin
   accent-tinted divider, so the row reads as a light, modern fact strip.
   auto-fit keeps them on one line on wide screens and reflows on narrow ones
   with no extra media queries. */
.vf-page .project-facts.cards { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 4px clamp(28px, 4vw, 56px); }
.vf-page .project-facts .card {
  background: none; border: 0; border-top: 1px solid var(--border); border-radius: 0;
  padding: 20px 0 6px; gap: 8px; box-shadow: none; will-change: auto;
}
/* neutralise the shared `.card:hover` lift/border/shadow — these are flat now */
.vf-page .project-facts .card:hover { border-color: var(--border); box-shadow: none; transform: none; }
.vf-page .project-facts .page-aside__title { font-family: var(--font-head); font-size: 13px; color: var(--accent); margin-bottom: 4px; text-transform: uppercase; letter-spacing: 0.08em; }
.vf-page .project-facts .card p, .vf-page .project-facts .card li { font-size: 14.5px; color: var(--muted); line-height: 1.75; }
.vf-page .project-facts .card ul { list-style: none; padding: 0; }
.vf-page .project-section-title, .vf-page .project-page__about h2 { font-family: var(--font-head); font-size: clamp(26px, 3vw, 38px); color: var(--text); margin-bottom: 16px; }
.vf-page .project-page__banners .cell h3 { color: var(--accent); }

/* ---------- stats band: dark-mode fix + modern divided row ----------
   The band carries both `cs-band` and the legacy `project-page__stats`. In dark
   mode the legacy `body.dark-theme .project-page__stats { background:#fff }`
   (specificity 0,2,1) beat the redesign `.vf-page .cs-band` (0,2,0), so the band
   stayed bright white on the dark page (request: image #19). These selectors are
   0,3,0 — they out-rank the legacy rule in BOTH modes, so the band tones from the
   theme surface and reads correctly in light and dark. We also split the metrics
   with thin column dividers (instead of one heavy card) for a cleaner, modern
   look that matches the borderless facts above. */
.vf-page .cs-band.project-page__stats { background: var(--surface); }
.vf-page .cs-band.project-page__stats .m { padding-left: clamp(18px, 2.4vw, 32px); border-left: 1px solid var(--border); }
.vf-page .cs-band.project-page__stats .m:first-child { padding-left: 0; border-left: 0; }
/* key features image + text */
.vf-page .project-feature__grid { display: grid; grid-template-columns: 1.2fr 1fr; gap: 40px; align-items: center; }
.vf-page .project-feature__img { width: 100%; border-radius: var(--radius); border: 1px solid var(--border); }
/* tech stack icon grid */
.vf-page .project-page__icons { list-style: none; margin: 24px 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 18px; }
.vf-page .project-page__icons li { display: flex; flex-direction: column; align-items: center; gap: 10px; text-align: center; background: var(--surface); border: 1px solid var(--border); border-radius: 14px; padding: 22px 16px; }
.vf-page .project-page__icons img { width: 44px; height: 44px; object-fit: contain; }
.vf-page .project-page__icons p { font-size: 13px; color: var(--muted); }
/* results gallery swiper */
.vf-page .project-page__wrapper-slider { margin-top: 32px; position: relative; }
.vf-page .project-page__slider { border-radius: var(--radius); overflow: hidden; }
.vf-page .project-page__slider .swiper-slide img { width: 100%; border-radius: var(--radius); }
/* smaller, lighter arrow buttons — the 46px circles read too heavy
   (request: image #23). 38px discs with a soft shadow and a scaled-down arrow
   feel more modern and less bulky over the slide. margin-top keeps them centred
   after the size change (Swiper offsets prev/next by -22px for the old height). */
.vf-page .project-page__slider .swiper-button-next, .vf-page .project-page__slider .swiper-button-prev {
  width: 38px; height: 38px; margin-top: -19px; border-radius: 50%; background: var(--surface); border: 1px solid var(--border);
  color: var(--text); display: flex; align-items: center; justify-content: center; cursor: pointer;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.10); transition: border-color .2s ease, color .2s ease, box-shadow .2s ease;
}
.vf-page .project-page__slider .swiper-button-next svg, .vf-page .project-page__slider .swiper-button-prev svg { width: 15px; height: auto; }
/* inset the arrows a little from the slide edges (Swiper pins them at 10px;
   request: image #24) so they don't hug the corners */
.vf-page .project-page__slider .swiper-button-prev { left: 18px; }
.vf-page .project-page__slider .swiper-button-next { right: 18px; }
.vf-page .project-page__slider .swiper-button-next:hover, .vf-page .project-page__slider .swiper-button-prev:hover { border-color: var(--accent); color: var(--accent); box-shadow: 0 6px 18px rgba(0, 0, 0, 0.14); }
/* Swiper ships its own arrow glyph via `::after` (a chevron from its icon font).
   It rendered ON TOP of our custom SVG arrows, so the two buttons showed
   mismatched icons (request: image #20). Kill the default glyph — same fix the
   about-history slider uses — leaving only our clean, symmetric SVG arrows. */
.vf-page .project-page__slider .swiper-button-next::after,
.vf-page .project-page__slider .swiper-button-prev::after { content: none; }
/* the gallery's swiper pagination shares the .pagination class with listing
   pagination — override the box style back to small round dots */
.vf-page .project-page__slider .pagination { display: flex; gap: 8px; justify-content: center; margin-top: 18px; }
.vf-page .project-page__slider .pagination .swiper-pagination-bullet {
  min-width: 0; width: 10px; height: 10px; padding: 0; border: none; border-radius: 50%;
  background: var(--faint); opacity: 1;
}
.vf-page .project-page__slider .pagination .swiper-pagination-bullet-active { background: var(--accent); }
/* client testimonial card */
.vf-page .page-response { display: flex; flex-direction: column; gap: 18px; margin-top: 22px; }
.vf-page .page-response__header { display: flex; align-items: center; justify-content: space-between; gap: 18px; flex-wrap: wrap; }
.vf-page .page-response__user-info { display: flex; align-items: center; gap: 14px; }
.vf-page .page-response__avatar { width: 54px; height: 54px; border-radius: 50%; object-fit: cover; }
.vf-page .page-response__info-wrapper .nm { font-family: var(--font-head); font-size: 16px; color: var(--text); display: block; }
.vf-page .page-response__info-wrapper .rl { font-size: 13px; color: var(--muted); }
.vf-page .page-response__logo { max-height: 34px; width: auto; }
.vf-page .page-response .q { font-size: 17px; line-height: 1.7; color: var(--text); font-weight: 300; margin: 0; }

/* ---------- "Other cases" grid ----------
   The list carries both `projects__list` (legacy) and `articles` (redesign). The
   legacy `.project-page__other-case .projects__list` rule (specificity 0,2,0)
   ties our `.vf-page .articles` and, loading later, won — collapsing the cards to
   one column (request: image #21). This 0,3,0 selector out-ranks it and restores
   a real 3-up grid that reflows to 2-up / 1-up on smaller screens. */
/* margin-top adds breathing room between the "Other cases" heading and the cards
   (request: image #22) */
.vf-page .project-page__other-case .articles { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; margin-top: 36px; }
@media (max-width: 1000px) {
  .vf-page .project-page__other-case .articles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 680px) {
  .vf-page .project-page__other-case .articles { grid-template-columns: 1fr; }
}

@media (max-width: 760px) {
  .vf-page .project-feature__grid { grid-template-columns: 1fr; gap: 24px; }
  /* stack the stat metrics: drop the column dividers so they don't sit awkwardly
     above each stacked block */
  .vf-page .cs-band.project-page__stats .m { padding-left: 0; border-left: 0; }
}

/* ==========================================================================
   Gutenberg / ACF block pages (Builder wrapper) — light-touch alignment.
   The blocks keep their legacy markup; we only nudge the most visible details
   into the .vf system (heading font, accent buttons, theme-aware text) so
   block-built pages (contact, service landings) read as part of the redesign.
   ========================================================================== */
/* block pages (and the thank-you template) redefine --accent to the palette's
   dark teal (#183633) deep in the legacy markup; re-assert the real brand accent
   on the wrapper so our overrides below — and the redesigned .btn-accent — resolve
   correctly. (The thank-you page shares the same #183633 leak via main_additional's
   `.thank_you_page { --accent:#183633 }`, which turned its primary CTA dark.) */
.vf-page.builder-wrap, .vf-page .builder_page, .vf-page .thank_you_page { --accent: #21CE99; }
.vf-page .builder_page h1, .vf-page .builder_page h2,
.vf-page .builder_page h3, .vf-page .builder_page h4 { font-family: var(--font-head); color: var(--text); }
/* hide the legacy decorative animated-text SVG letters behind headings */
.vf-page .builder_page .animated-text, .vf-page .builder_page .section-header__letter svg,
.vf-page .builder_page .project-page__svg { display: none; }
/* solid buttons → accent */
.vf-page .builder_page .simple_button,
.vf-page .builder_page .button:not(.projects-filter__button),
.vf-page .builder_page .form-container__button,
.vf-page .builder_page .wpcf7-submit,
.vf-page .builder_page input[type="submit"],
.vf-page .builder_page .navigate-link {
  /* literal accent (not var) — block pages reset --accent locally to the dark
     palette teal; !important beats the Gutenberg has-*-background-color class */
  background: #21CE99 !important; color: #10231c !important; border: 1px solid #21CE99;
  border-radius: 10px; transition: filter .2s ease, transform .2s ease;
}
.vf-page .builder_page .simple_button:hover,
.vf-page .builder_page .form-container__button:hover,
.vf-page .builder_page .wpcf7-submit:hover,
.vf-page .builder_page input[type="submit"]:hover { filter: brightness(1.06); transform: translateY(-1px); }
/* button with reverse/outline style stays outline */
.vf-page .builder_page .button_reverse_style { background: transparent; color: var(--text); border: 1px solid var(--border); }
.vf-page .builder_page .button_reverse_style:hover { border-color: var(--accent); color: var(--accent); }
/* accent links + form focus */
.vf-page .builder_page a.link, .vf-page .builder_page .form-container__link { color: var(--accent); }
.vf-page .builder_page input:focus, .vf-page .builder_page textarea:focus, .vf-page .builder_page select:focus { border-color: var(--accent); outline: none; }

/* ---------- block-specific contrast / brand fixes ----------
   The CTA treatment higher up in this file is scoped to `#blog_page`, an id that
   only the blog/post templates emit. The SAME legacy block classes are reused by
   the ACF blocks on Builder-wrapper pages, where that id is absent — so a handful
   of hard-coded legacy colours leak through and read wrong on the light page.
   Re-assert them here, scoped to `.builder_page`, using the theme tokens so the
   light AND dark themes both stay readable. */

/* cta_separator block: the legacy title is pure white (it used to sit on a solid
   dark-green band). On the redesigned pale band that white title is invisible —
   use the theme text colour so it reads in both light and dark. */
.vf-page .builder_page .cta_separator .cta_wrapper .services__title { color: var(--text); }

/* vertical_tabs_content: the inactive nav words use the legacy #d9d9d9, which is
   almost invisible on the light page. Use the muted tone, and accent the
   active/hover word so the current tab is obvious. (!important beats the legacy
   `.single_nav { color: var(--vertical_tab) }` rule.) */
.vf-page .builder_page .vertical_tabs_content .controls_section .single_nav { color: var(--muted) !important; }
.vf-page .builder_page .vertical_tabs_content .controls_section .single_nav.active,
.vf-page .builder_page .vertical_tabs_content .controls_section .single_nav:hover { color: var(--accent) !important; }

/* universal_blocks_content number badge: white digits on the accent green are too
   low-contrast — use the dark accent ink (matches the accent buttons/badges). */
.vf-page .builder_page .universal_blocks_content .number { color: #10231c !important; }

/* horizontal_tabs_content: the selected tab was a legacy dark pill. Make it the
   brand accent (with dark ink) so the tab bar matches the rest of the redesign. */
.vf-page .builder_page .horizontal_tabs_content .controls .single_control.active,
.vf-page .builder_page .horizontal_tabs_content .controls .single_control:hover {
  background: #21CE99 !important; color: #10231c !important; border-color: #21CE99 !important;
}

/* ---------- block container width ----------
   The legacy blocks size their inner container with `[class*="__container"]`,
   which is 1580px wide with huge responsive side padding. That makes block
   content wider than — and ~60px left of — the rest of the redesigned site,
   which aligns to `.vf .wrap` (1240px / 56px gutters; the header/footer and all
   interior pages use it). Re-constrain every block container to match so block
   content lines up with the header brand/menu and the footer. */
.vf-page .builder_page .page__container,
.vf-page .builder_page .services-experience__container,
.vf-page .builder_page .about__container {
  max-width: 1240px; padding-left: 56px; padding-right: 56px;
}
/* full-width band blocks (CTA / report separator) have no inner container — cap
   the band itself to the same width so it aligns with the other blocks. */
.vf-page .builder_page .cta_separator { max-width: 1240px; margin-left: auto; margin-right: auto; }

/* ---------- legacy display fonts ----------
   Several block titles/labels still use the old display fonts (Yanone Kaffeesatz
   / Montserrat). The site's heading font is Oswald (`--font-head`); the heading
   nudge only covers h1–h4, so these div/span title elements slip through. Map
   them all to the design heading font. (!important beats the deep legacy
   per-block selectors.) */
.vf-page .builder_page .title,
.vf-page .builder_page .title_point,
.vf-page .builder_page .point_title,
.vf-page .builder_page .slider_title,
.vf-page .builder_page .single_nav,
.vf-page .builder_page .accordion_title,
.vf-page .builder_page .loc_title,
.vf-page .builder_page .author .name { font-family: var(--font-head) !important; }

/* ---------- block spacing & layout polish ----------
   Fixes from design review. */

/* Hero gap: the `.builder_page` wrapper is itself a <section>, so it picks up
   `.vf section`'s 104px vertical padding — and the first block (the hero, also a
   <section>) adds ANOTHER 104px, doubling the space below the header. Drop the
   wrapper's own vertical padding (the blocks already pad themselves) and tighten
   the hero's top so the title sits a comfortable distance under the header. */
/* +50px of breathing room at the very top of the page (between the header and
   the first block), requested for the gutenberg/builder template. Applied on
   the wrapper so it holds regardless of which block renders first. */
.vf-page .builder_page { padding-top: 50px; padding-bottom: 0; }
.vf-page .builder_page .hero_simple { padding-top: 28px; }

/* Block header: more breathing room between the section title and its
   description (the legacy 20px reads cramped under the large Oswald titles). */
.vf-page .builder_page .main_section_description { margin-top: 24px; }

/* collapse_content (accordion / FAQ): (1) space the heading off the accordion
   list — the legacy title has no bottom margin so it touches the first row;
   (2) give each accordion a surface that actually reads on the light theme. The
   legacy fill is `--projects-bg` (#f4f4f4), nearly identical to the page
   background in light; switch to the standard card surface + border so it reads
   as a card in both themes. */
.vf-page .builder_page .collapse_content .services__title { margin-bottom: 28px; }
.vf-page .builder_page .collapse_content .accordion {
  background: var(--surface); border: 1px solid var(--border);
}
/* the expanded answer panel sits inside the (now carded) accordion — drop its
   own legacy grey fill so the content reads flat on the card, not a box-in-box. */
.vf-page .builder_page .collapse_content .panel { background: transparent; }

/* simple_quote: the portrait should fill the full height of the quote panel.
   Let the image column stretch to the (taller) text column via the flex row,
   then absolutely fill it with the image so it always spans the full height
   (object-fit: cover keeps it undistorted; legacy used a fixed height + fill). */
.vf-page .builder_page .simple_quote .quote_row { align-items: stretch; }
.vf-page .builder_page .simple_quote .image { position: relative; overflow: hidden; }
.vf-page .builder_page .simple_quote .image img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
}

/* ---------- responsive ---------- */
@media (max-width: 768px) {
  /* universal_blocks: on mobile the title was pinned to a narrow ~150px column
     (legacy two-column title|description row), so big titles wrapped one word
     per line. Stack the title above the description and let it use full width. */
  .vf-page .builder_page .universal_blocks_content .point_content { flex-direction: column; }
  .vf-page .builder_page .universal_blocks_content .point_content .title {
    flex: 1 1 auto; width: 100%; max-width: none;
  }
}

/* ---------- responsive ---------- */
@media (max-width: 1000px) {
  .vf-page .svc-grid { grid-template-columns: repeat(2, 1fr); }
  .vf-page .ind-grid { grid-template-columns: repeat(2, 1fr); }
  .vf-page .cards.cols-3 { grid-template-columns: repeat(2, 1fr); }
  .vf-page .proc { grid-template-columns: repeat(2, 1fr); }
  .vf-page .proc-step:not(:last-child)::before { display: none; }
  .vf-page .post-layout { grid-template-columns: 1fr; gap: 32px; }
  /* TOC no longer sits beside the hero, so the meta line can use the full width. */
  .vf-page .page-hero .post-meta { max-width: none; }
  /* `display:contents` dissolves the aside box so its children become rows of the
     single-column post-layout. The TOC then orders above the article, while
     share-icons fall naturally below it. */
  .vf-page .post-aside { position: static; margin-top: 0; display: contents; }
  .vf-page .post-aside .toc { order: -1; }
  .vf-page .post-aside .share-icons { margin-top: 8px; }

  /* TOC becomes a closed-by-default dropdown: collapse the list, show + rotate
     the chevron, make the heading tappable. JS toggles `.toc.open`. */
  .vf-page .toc {
    border: 1px solid var(--border); border-radius: 12px;
    padding: 4px 16px; gap: 0; background: var(--surface);
  }
  .vf-page .toc-toggle { cursor: pointer; padding: 14px 0; font-size: 20px; }
  .vf-page .toc-chevron { display: inline-block; }
  .vf-page .toc.open .toc-chevron { transform: rotate(180deg); }
  .vf-page .toc ul { display: none; padding-bottom: 8px; }
  .vf-page .toc.open ul { display: flex; }

  .vf-page .contact-grid { grid-template-columns: 1fr; }

  /* team grid: drop the 2/3 span layout to an even 2-up on tablet */
  .vf-page .about-teams__slider .swiper-wrapper { grid-template-columns: repeat(2, 1fr); }
  .vf-page .about-teams__slider .swiper-slide:nth-child(-n+2),
  .vf-page .about-teams__slider .swiper-slide:nth-child(n+3) { grid-column: span 1; }
}
@media (max-width: 720px) {
  /* universal_blocks heading sits too close to the 71px sticky header on phones
     (`.vf section` drops to 64px top padding here), so the title reads as jammed
     under / cut off by the header bar. Add ~70px of breathing room above it. */
  .vf-page .builder_page .universal_blocks_content { padding-top: 134px; }

  /* tabs: ensure the quote sits below the word list with breathing room */
  .vf-page .about-tabs .wrap { gap: 28px; }
  .vf-page .about-tabs .tabs__content { flex-basis: 100%; }
  /* team grid: single column on phones */
  .vf-page .about-teams__slider .swiper-wrapper { grid-template-columns: 1fr; }

  /* numbers: one stat per row (space-between left "100+" and "2019" sharing a row) */
  .vf-page .about-numbers .stats { flex-direction: column; gap: 28px; }

  /* testimonials: left-align the heading + button (were pushed right on mobile) */
  .vf-page .about-reviewes__header { flex-direction: column; align-items: flex-start; gap: 16px; }
  .vf-page .about-reviewes__header .sect-head { text-align: left; }

  /* referral: stack the email field above a full-width Send button with a small
     gap (the wrapped flex row left a large gap between them) */
  .vf-page .about-refers .contact-grid { align-items: start; }
  .vf-page .about-refers__form { flex-direction: column; align-items: stretch; gap: 14px; }
  .vf-page .about-refers__form .wpcf7-form-control-wrap { flex: 1 1 auto; width: 100%; }
  .vf-page .about-refers__form input[type="submit"] { width: 100%; align-self: stretch; }

  .vf-page .page-hero { padding: 26px 0 18px; }
  .vf-page .svc-grid, .vf-page .ind-grid, .vf-page .cards, .vf-page .cards.cols-3, .vf-page .cards.cols-2,
  .vf-page .articles, .vf-page .proc, .vf-page .grid-2 { grid-template-columns: 1fr; }
  .vf-page .stack-row { grid-template-columns: 1fr; gap: 12px; }
  .vf-page .why-list { grid-template-columns: 1fr; }
  /* re-enable wrapping on mobile so the full-width search drops below the pills */
  .vf-page .filter-bar { flex-wrap: wrap; }
  .vf-page .filter-bar .f-search { margin-left: 0; width: 100%; }

  /* stack the in-content cards; the CTA image is decorative so hide it, keep the
     author portrait (capped height) above the bio text */
  .vf-page .blog-info, .vf-page .blog-bio { grid-template-columns: 1fr; }
  .vf-page .blog-info__img-wrapper { display: none; }
  .vf-page .blog-bio__img-wrapper img { max-height: 320px; }
}

/* ==========================================================================
   Thank-you template (template-thank-you.php) — redesign alignment.
   ========================================================================== */
/* (--accent for this page is re-asserted with the builder pages above.)
   Vertically center the message, nudged a touch above the optical centre.
   min-height fills the space below the 71px sticky nav (the same nav height the
   admin-bar offset uses in home-redesign.css); padding-top:0 overrides the
   .center-page clamp padding so the grid controls vertical position, and the
   bottom padding lifts the centred block slightly above centre. The bottom value
   is clamped so it never over-lifts on tall monitors nor crowds short viewports. */
.vf-page .thank_you_page {
  display: grid;
  place-items: center;
  min-height: calc(100vh - 71px);
  padding-top: 0;
  padding-bottom: clamp(96px, 17vh, 168px);
}
/* Drop the legacy 120px content_block padding so the grid centring is clean. */
.vf-page .thank_you_page .content_block { padding-top: 0; padding-bottom: 0; }


/* =====================================================================
   CONTACT PAGE  (gutenberg "Builder wrapper" → .vf-page .builder_page)
   /contact-us/ renders three legacy ACF blocks inside the redesign chrome:
   hero-form, locations (map) and a team grid. These blocks predate the
   redesign, so we modernise them here. Everything is scoped to the block
   classes so it only touches these blocks — and works in any environment
   (no page-id dependency).
   ===================================================================== */

/* ---- 1. Form: text fields should show a text caret, not a pointer ----
   Legacy `.form-container__input,.form-container__textarea{cursor:pointer}`
   makes the fields feel like buttons. Restore the normal text caret. */
.vf-page .form_holder .form-container__input,
.vf-page .form_holder .form-container__textarea { cursor: text; }

/* ---- 2. Form: recolour the old sage-green (#779C99) accents to the
   site's current primary (the bright accent green used by the Send button
   and logo). ---- */
/* the big stat numbers (150+, 95%…) read their colour from this var, which
   is defined on `.builder_page`; redefine it closer to the numbers so it
   wins without fighting the original 6-class selector. */
.vf-page .form_holder .points_row { --points_secondary_color: var(--accent); }
/* the "Attach File" upload label */
.vf-page .form_holder .form-container__file-label { color: var(--accent); }

/* ---- 3. Form: consent checkbox → the site-wide custom control (an
   accent-filled box with a checkmark), replacing the legacy box that was
   drawn with `label::before/::after` over a hidden <input>. Mirrors the
   homepage `.vf .hform .wpcf7-acceptance` styling. ---- */
/* remove the legacy drawn box + checkmark pseudo-elements */
.vf-page .form_holder .wpcf7-acceptance label::before,
.vf-page .form_holder .wpcf7-acceptance label::after { content: none; }
/* top-align the box with the first line of the (multi-line) consent text */
.vf-page .form_holder .wpcf7-acceptance label { align-items: flex-start; }
/* reveal the real <input> (legacy hid it) and draw it as our own box */
.vf-page .form_holder .wpcf7-acceptance input[type="checkbox"] {
  display: inline-block; appearance: none; -webkit-appearance: none;
  width: 20px; height: 20px; margin: 2px 0 0; flex-shrink: 0;
  border: 1px solid var(--border); border-radius: 6px; background: var(--surface);
  cursor: pointer; transition: background-color .15s ease, border-color .15s ease;
}
.vf-page .form_holder .wpcf7-acceptance input[type="checkbox"]:hover { border-color: var(--accent); }
.vf-page .form_holder .wpcf7-acceptance input[type="checkbox"]:checked {
  background-color: var(--accent); border-color: var(--accent);
  /* dark checkmark (accent-ink) drawn as a background SVG — reliable everywhere */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2310231c' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5l3 3 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: center; background-size: 13px;
}

/* ---- 4. Team: a real CSS grid (the block now outputs plain grid markup
   instead of Swiper — app.min.js auto-inits Swiper on `.swiper-container`,
   so the old markup was a live carousel masked by CSS). The card INNER
   styling (gradient, name, position, social chips) is shared with the
   about page via the `.about-teams__*` rules earlier in this file, so we
   only need the grid + card-box layout here. ---- */
.vf-page .about-teams.image_slider .about-teams__grid {
  display: grid; grid-template-columns: repeat(5, 1fr); gap: 18px;
}
.vf-page .about-teams.image_slider .about-teams__item {
  position: relative; display: flex; align-items: flex-end;
  min-height: 340px; border-radius: 16px; overflow: hidden;
  background-size: cover; background-position: center top;
}
/* names render dark & unreadable otherwise: they are <h3>s, so the generic
   `.vf-page .builder_page h3{color:var(--text)}` rule out-specifies
   `.about-teams__name{color:#fff}`. They sit on a dark photo gradient. */
.vf-page .builder_page .about-teams__name { color: #fff; }
@media (max-width: 1000px) {
  .vf-page .about-teams.image_slider .about-teams__grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 720px) {
  .vf-page .about-teams.image_slider .about-teams__grid { grid-template-columns: 1fr; }
}

/* ---- 5. Locations map ----
   Two problems with the legacy map:
   (a) it sat in a white/dark panel that didn't match the page background;
   (b) the theme toggle swapped a 2.77MB Earth.svg for a 1.7MB dark SVG, and
       decoding that multi-megabyte SVG mid-View-Transition stalled the main
       thread (~190ms) → the hard lag when switching theme over the map.
   Fix: use ONE lightweight map layer for both themes (nothing downloads,
   decodes or repaints on toggle), drawn on a dedicated ::after layer so we
   can tint it for dark mode without touching the pins/cards, and fade it
   from the page background so there is no visible panel. */
/* drop the heavy direct background + the per-theme swap on .map_col */
.vf-page .locations_block .map_col { background-image: none; }
/* the map itself: a single SVG layer that blends into the page */
.vf-page .locations_block .map_col::after {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: url("../../template-parts/blocks/locations/Earth.svg") center / cover no-repeat;
}
/* the left-side fade now uses the PAGE background (var(--bg)) instead of a
   hardcoded white / #1E1E22, so the map melts into the page with no panel.
   It sits above the map layer so it still fades the map under the heading. */
.vf-page .locations_block .map_col::before {
  z-index: 1;
  background: linear-gradient(90deg, var(--bg) 0%, var(--bg) 42%, transparent 78%) !important;
}
/* keep the pins and the location cards above both map layers */
.vf-page .locations_block .map_holder,
.vf-page .locations_block .locations_holder { z-index: 2; }
/* dark mode: invert the light-grey continents to a dark grey that reads on
   the dark page — no second SVG download/decode needed */
body.dark-theme .vf-page .locations_block .map_col::after { filter: invert(1); }
