/**
 * Practice-area pages.
 *
 * Every value here is read out of the Figma file (UB7FmaXxJY1PnhVnhHqlEJ,
 * page "Fieldlink Practice area", frame 483:3 — FieldLink's own artboard, not
 * the sibling project this was first built against) rather than eyeballed:
 * auto-layout became flex, itemSpacing became gap, the frame paddings became
 * the container widths, and the corner radii are the literal
 * rectangleCornerRadii. The design is drawn at 1920.
 *
 * This pass (2026-09) replaces the tokens and the hero only. Everything below
 * the hero still points at the OLD sibling-project tokens removed here, so it
 * will render broken — unstyled colour, no max-width — until each section is
 * rebuilt against 483:3 in a later pass. That is expected, not a bug to chase.
 *
 * Mobile-first: base rules are the phone layout, every media query is
 * min-width and adds complexity going up, matching the theme's own 768/1280
 * breakpoints. The desktop numbers land at 1280.
 */

:root {
  /* Palette, by frequency in the node tree. */
  --pa-navy: #00003d;    /* fill_224895b8 — dominant fill: headings, body copy, panels */
  --pa-white: #ffffff;   /* fill_658ab2fa — page background, pill/heading text on navy or red */
  --pa-red: #ff363b;     /* fill_40839e0c — H1 pills, primary accents */
  --pa-lime: #d9ff1a;    /* fill_5b6cba63 — Staffing/Recruiting cards, "Hire talent" pill */
  --pa-pale-blue: #d1f2ff; /* fill_836f5461 — "Partner with Fieldlink" band background */
  --pa-green: #638573;   /* fill_65a0c07c — "Completed Searches" panel */
  --pa-ink: #041131;     /* node #483:5 — a visually-hidden accessibility-utility string near the
                             top of the page, NOT any section's own body copy. cold-assessment,
                             2026-09: this had been reused for the intro/services/compliance
                             (the .pa-credential__label card, not .pa-compliance__text, which is
                             white-on-navy and was already right)/about paragraph text, which each
                             measure #00003d (--pa-navy) on their own node — three points of blue
                             apart, invisible on screen but real and traceable, so all four rules
                             now read --pa-navy directly. Nothing in this stylesheet reads this
                             token any more; left defined rather than deleted in case a future
                             section genuinely wants the old node's own colour again. */

  /* --pa-blue was this palette's dominant-navy token before the 2026-09
     rename to --pa-navy above. A run of rules added since (the shared
     focus-visible outline, several buttons, the testimonials/tiles work
     below) were written against the old name and, without this alias,
     silently do nothing — var() failing at compute time invalidates the
     whole declaration, so e.g. every :focus-visible outline listed near
     line 240 currently renders no outline at all. Aliased rather than
     mass-renamed so this stays a one-line fix instead of touching rules
     across sections this pass does not otherwise own. */
  --pa-blue: var(--pa-navy);

  /* --pa-orange was the sibling project's link/button accent (#ffab00). The
     2026-09 rename above never gave FieldLink's own palette an equivalent, so
     every rule still written against --pa-orange (the orange button variant,
     the body-copy/jobs/show-more hover states below) silently did nothing —
     var() failing at compute time drops the whole declaration, so those
     hovers rendered with no colour change at all. FieldLink's own accent for
     exactly this role is --pa-red (fill_40839e0c, "primary accents" above),
     already used at rest by .pa-btn--red, so this aliases to it rather than
     re-introducing a colour the FieldLink design never specifies. */
  --pa-orange: var(--pa-red);

  /* Type ramp. Sizes are literal Figma px; families are already loaded by the
     theme (June Expt on headings/UI, DM Sans on body) so these tokens carry
     size only. */
  --pa-font-display: 58px;     /* style_40636f12 — H1 pill text */
  --pa-line-display: 75.4px;   /* style_40636f12 */
  --pa-font-heading: 26px;     /* style_2a8ad2ae / style_2555774f — section + card headings */
  /* Re-checked 2026-09 (rebuild-11): --pa-font-body's own 16px is only ever
     right for the ONE body-copy block that is actually 16px in the node tree
     — #495:1316/#495:1336, the service cards (fs16.0/lh20.83). Every other
     "DM Sans paragraph copy" block on the page reads smaller: #516:42/#516:43
     (intro) fs13.3/lh17.92 — identical to --pa-font-small, not its own size
     — and #493:985 (compliance) / #495:1289 (about) both fs14.0/lh17.92,
     a third size this pass had been folding into the 16px token along with
     everything else. Split into the two real sizes below rather than one
     token doing three jobs. */
  --pa-font-body: 16px;        /* style_480f6106 — #495:1316/1336, the service cards only */
  --pa-font-body-sm: 14px;     /* #493:985 / #495:1289 — compliance + about body copy */
  --pa-font-small: 13.3px;     /* style_22a442e1 / style_48619f6b — CTA links, card body copy, and #516:42/43's intro paragraphs */
  --pa-font-eyebrow: 12px;     /* style_ab9dcf43 / style_c093ef48 — nav links, eyebrow labels */

  /* Container widths, both measured against the 1920 frame. */
  --pa-wide: 1400px;  /* header logo x=260, nav right edge 1920-260=1660: symmetric 260px margins.
                          Kept ONLY for the hero (matching the header/nav it sits directly under)
                          and for the .pa-about bleed calc below, which both cite it explicitly —
                          every other section's own content sits at --pa-panel, not this. */
  --pa-panel: 1380px; /* #493:989, #495:1524, #495:1209 (the colour panels) AND, per the node
                          data, the real margin every OTHER section's plain content also sits at
                          — .pa-intro__columns x=273, .pa-tile x=271, .pa-testimonial__quote
                          x=270, .pa-tiles-section's own comment below ("4 across at the design's
                          own 1380px container width") all agree on ~270-273, not --pa-wide's 260.
                          Confirmed 2026-09 (cold-assessment fix pass): .pa-page-w itself now caps
                          at this value, not --pa-wide, so every section built directly against
                          .pa-page-w inherits the correct inset for free instead of the six-plus
                          separate 10-13px misses a per-element nudge would have left behind. */
  /* --pa-narrow backs .pa-page-n, which only extra.php uses — a standalone
     prose block ported unchanged from the sibling project for a different
     client's page (see extra.php's own docblock) and not called anywhere in
     single-practice-area.php today, so this width renders nothing on any of
     FieldLink's five pages. 483:3 has no artboard for it to measure against.
     Carried forward at the sibling project's own value rather than invented
     against a comp that does not exist, so the layout is correct on the day
     a page wires extra.php back in. */
  --pa-narrow: 958px;

  /* Vertical rhythm: #524:393 and #516:26 both pad "80px 0" around their
     section content, replacing the old design's flat 100px. */
  --pa-rhythm: 80px;

  /* Corner radii. */
  --pa-radius: 30px;      /* EL-27d294a8/-bbd8d9d3/-46ab3c08/-40ff93fa and every panel/tile rect */
  --pa-radius-pill: 50px; /* #490:664 etc. — bigger than half the pill's own height, so it renders
                              as a full stadium rather than a merely-rounded rectangle */
}

/* --------------------------------------------------------------- layout - */

.pa-page-w,
.pa-page-n {
  width: 100%;
  margin: 0 auto;
  padding: 0 20px;
  box-sizing: border-box;
}

@media (min-width: 768px) {
  .pa-page-w, .pa-page-n { padding: 0 40px; }
}

@media (min-width: 1280px) {
  /* --pa-panel, not --pa-wide — see that token's own comment. The hero is
     the one section that genuinely wants the wider 1400px/260px margin (it
     sits directly under the site header/nav, which use that margin too), so
     it gets its own override right below rather than everything else
     inheriting its width by sharing this class.

     2026-09 (client-reported: container flush against both viewport edges
     below 1380px): this used to be `max-width: var(--pa-panel); padding: 0`
     — exactly the container bug verifying.md's own worked example is about.
     `max-width` with no padding measures a gutter that is purely an accident
     of how far 1380 is from the current viewport: 270px at 1920 (271px per
     the node itself, 1px of rounding against --pa-panel), 30px at 1440, and
     that accident reaches zero right at 1380 and STAYS zero for every
     narrower width, because once the viewport no longer exceeds the cap
     there is nothing left to produce a gutter at all.

     Fixed the same way .pa-split__inner's own bleed padding above already
     does it for the About section's photo: padding computed from the
     viewport, floored at the tablet tier's own 40px rather than a max-width
     doing the capping. The design's inset (calc((100vw - panel) / 2)) grows
     unbounded above the design width and shrinks below it exactly as far as
     the 40px floor, never past it, so the gutter is derived, not a round
     number restated as a literal. `max-width` is dropped entirely — the
     padding formula already caps content at --pa-panel on its own (at 2400:
     padding grows to (2400-1380)/2=510, content=1380px); keeping max-width
     alongside would cap the box AND keep growing the padding against
     100vw, crushing the content edge to 360px instead of holding 1380. */
  .pa-page-w { padding: 0 max(40px, calc((100vw - var(--pa-panel)) / 2)); }
  .pa-page-n { padding: 0 max(40px, calc((100vw - var(--pa-narrow)) / 2)); }

  .pa-hero__inner { padding: 0 max(40px, calc((100vw - var(--pa-wide)) / 2)); }
}

/* Section rhythm. Figma has a flat 100px gap between every section; that is
   too much air on a phone, so it scales rather than being reproduced.

   These are per-side paddings and two of them meet between any two sections,
   so the gap is double the value here. That is what made tablet the loosest
   breakpoint on the page: 70px a side is a 140px gap, against 100px at 1280
   and 96px on a phone. There is no tablet override now — the phone's 48px
   carries up to 1280, where half the rhythm gives the design's 100px. */

/* #483:252 (header) ends 85.8px into the 1920 frame; the H1 pill group
   (#494:1093) starts at 161.38 — a 75.58px gap the hero owns as its own top
   padding, rounded to 76. No bottom padding of its own: whatever follows the
   pills carries its own top spacing instead.

   2026-09: that 76px (32px below 1280) was the gap from the *design's*
   header-bottom to the pill group — it assumed something in the real flow
   already pushed .pa-hero down to start where the header ends. Until now
   that something was breadcrumb.php: not visible (painted underneath the
   theme's fixed, 92px-tall header — see single-practice-area.php's own
   comment), but very much occupying flow space, 71.6px of it, which is what
   actually cleared the header. Once the breadcrumb stopped rendering,
   .pa-hero became the page's first flow element with nothing above it, so
   its old padding-top put the H1 pills' top ~16px *under* the fixed header
   — confirmed by sampling rendered pixels through that band: solid white
   from the header's own opaque background, not a pill, until the header's
   bottom edge.

   Fixed by folding the header's real height into this padding, so it does
   both jobs the breadcrumb used to split between two elements: clear the
   header, then leave the same original gap. Real header height measured
   (Playwright, getBoundingClientRect): 92px at >=1280px, 90-94px below it
   (ignoring a 2px-wide transitional glitch exactly at the 768px breakpoint
   where the header's own nav briefly reflows — pre-existing, not a
   practice-area concern) — 94px covers the whole sub-1280 range with room
   to spare. 92 + 76 = 168; 94 + 32 = 126. */
.pa-hero { padding: 126px 0 0; }

@media (min-width: 1280px) {
  .pa-hero { padding: 168px 0 0; }
}

.pa-intro,
.pa-services,
.pa-split,
.pa-compliance,
.pa-testimonials,
.pa-tiles-section,
.pa-roles-section,
.pa-searches-section,
.pa-team-section,
.pa-faq-section,
.pa-jobs,
.pa-partner,
.pa-extra,
.pa-cta {
  padding: 48px 0;
}

@media (min-width: 1280px) {
  .pa-intro, .pa-services, .pa-split, .pa-compliance, .pa-testimonials, .pa-tiles-section,
  .pa-roles-section, .pa-searches-section, .pa-team-section, .pa-faq-section,
  .pa-jobs, .pa-partner, .pa-extra, .pa-cta {
    padding: calc(var(--pa-rhythm) / 2) 0;
  }

  /* The hero is the one section with no bottom padding of its own, so the
     section after it has to carry the whole 100px rather than half. */
  .pa-hero + * { padding-top: var(--pa-rhythm); }

  /* Two adjacent-section pairs where both sides carrying the shared default
     above (verifying.md's own recurring shape) lands on the wrong gap —
     cold-assessment, 2026-09, measured directly off #524:393/#516:26's real
     y-values, not the flat rhythm token.
     Completed Searches -> the mid-page CTA band wants 50px, tighter than
     the 80 two defaults give: give way on the CTA's own side (its other,
     bottom-of-page instance keeps the ordinary 40/40 split, which already
     measures correctly against tile-row -> bottom-CTA). `.pa-team-section`
     is included too though team.php renders nothing on any page today
     (see its own docblock) — if a page ever populates it, it sits between
     Searches and the CTA and this selector should still find the CTA. */
  .pa-searches-section + .pa-cta,
  .pa-team-section + .pa-cta {
    padding-top: 10px; /* 40 (Searches' own bottom, unchanged) + 10 = 50 */
  }

  /* FAQ -> the Explore-tiles/Typical-Roles band wants 93px, looser than 80 —
     give way on the following section's own top, the same way the hero's
     own rule above does. `.pa-roles-section` shares the fix since 483:3
     draws no Typical-Roles frame to measure separately (single-practice-
     area.php's own docblock) and the category pages put it in the same slot
     the hub puts the tile grid. */
  .pa-tiles-section,
  .pa-roles-section {
    padding-top: 53px; /* 40 (FAQ's own bottom, unchanged) + 53 = 93 */
  }
}

/* fill_658ab2fa on the root frame: the new design's page background is white,
   not the sibling project's beige. */
body.single-practice-area { background: var(--pa-white); }

/* ----------------------------------------------------------- breadcrumb - */

/* Not in the Figma comp — added because the structured data was describing a
   trail the page never showed, and because a category page had no link back up
   to its own industry. Deliberately quiet: it sits in the gap between the
   header and the hero photo and should not compete with the H1.

   The hero has no top padding of its own, so the spacing below lives here. */
/* The top padding is doing more work than it looks like. The header sits over
   the top of the page rather than pushing it down, so the first 16px of this is
   spent clearing it — measured, the rule below the menu was landing 1px above
   the breadcrumb text on a phone and 4px on desktop. These numbers are set so
   the visible gap between that rule and the text is 16px and 24px. */
.pa-crumbs {
  padding: 32px 0 4px;
  font-size: 14px;
  line-height: 1.4;
}

@media (min-width: 1280px) {
  .pa-crumbs { padding: 44px 0 8px; }
}

.pa-crumbs__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.pa-crumbs__item {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* A CSS separator rather than a character in the markup, so it is not read out
   as "greater than" between every entry. */
.pa-crumbs__item + .pa-crumbs__item::before {
  content: "";
  width: 5px;
  height: 5px;
  border-top: 1.5px solid currentColor;
  border-right: 1.5px solid currentColor;
  transform: rotate(45deg);
  opacity: .5;
  flex: none;
}

.pa-crumbs__item { color: var(--pa-blue); }

/* Not in the Figma at all (see this template's own docblock) — .pa-crumbs
   sets its own deliberately-chosen 14px, not a value read off a node. It
   still falls to the same class of bug, one level worse than elsewhere in
   this sweep: .pa-crumbs__link/.pa-crumbs__current sit three elements below
   .pa-crumbs itself (.pa-page-w > .pa-crumbs__list > .pa-crumbs__item), and
   styles.css's global `body, * { font-size: 16px }` matches every one of
   those intervening elements directly too — so `font-size: inherit` here
   would only inherit the .pa-crumbs__item li's own already-reset 16px, not
   the nav's 14px. Restating the literal value is correct here (unlike this
   sweep's other fixes, which use `inherit`) because 14px is this component's
   own fixed choice, not a token that varies by breakpoint. The <a>'s own
   `color: inherit` already beats the reset for colour (a class selector
   outranks the universal one, and .pa-crumbs__item's color sits just one
   level up); font-size never had the equivalent restatement. */
.pa-crumbs__link {
  color: inherit;
  text-decoration: none;
  opacity: .7;
  font-size: 14px;
  font-weight: inherit;
  font-family: inherit;
}

.pa-crumbs__link:hover,
.pa-crumbs__link:focus-visible {
  opacity: 1;
  text-decoration: underline;
}

/* Same font-size bug as .pa-crumbs__link above (literal 14px for the same
   reason — inherit would only reach .pa-crumbs__item's own already-reset
   16px, three elements short of .pa-crumbs itself), plus colour: th-job-
   board's own `input, p, span { color: #1f3d47 }` matches this SPAN directly
   (more specific than styles.css's universal reset, less specific than a
   class — see .pa-faq__question's own note further down for the identical
   mechanism), so this rendered #1f3d47 instead of .pa-crumbs__item's navy.
   Colour only needs `inherit` — .pa-crumbs__item, one level up, carries its
   own explicit color rule rather than falling to any reset. */
.pa-crumbs__current {
  font-weight: 500;
  opacity: 1;
  font-size: 14px;
  font-family: inherit;
  color: inherit;
}

.pa-hero img, .pa-split img, .pa-tile img, .pa-cta img {
  max-width: 100%;
  height: auto;
  display: block;
}

/* Section title: Figma 50px / 500 / lh 55, centred. */
.pa-section__title {
  font-size: clamp(1.75rem, 1.05rem + 2.9vw, 3.125rem);
  font-weight: 500;
  line-height: 1.1;
  color: var(--pa-blue);
  text-align: center;
  /* Figma sizes each heading's text box rather than the container, and that
     box width is what makes a heading wrap to two lines instead of running
     the full 1170. The 2026-08-12 pass widened every one of them — the
     services heading went 717 -> 965, testimonials 770 -> 939 — so the cap is
     now set per section below, and this is only the fallback. */
  max-width: 965px;
  margin: 0 auto 32px;
}

@media (min-width: 1280px) {
  /* Frame 65/45/28: heading sits 50px above its content. */
  .pa-section__title { margin-bottom: 50px; }

  /* One cap per section, each the width of that heading's text box in the
     design. They only differ by tens of pixels, but that is exactly the range
     that decides where a 50px heading breaks. */
  .pa-services .pa-section__title      { max-width: 965px; }
  /* .pa-testimonials has no visible heading at all (see that section's own
     comment), and .pa-tiles-section and .pa-roles-section each have their
     own complete, left-aligned override further down — none of the three
     belongs in this centred-heading table. */
  /* .pa-searches-section has its own complete override, further down the
     file, the same way .pa-compliance does — not listed here. */
  .pa-team-section .pa-section__title { max-width: 940px; }
  .pa-faq-section .pa-section__title   { max-width: 867px; }
}

.pa-section__title--left { text-align: left; max-width: none; margin-left: 0; }

/* The theme sets no global focus style. */
.pa-btn:focus-visible, .pa-tile:focus-visible, .pa-faq__toggle:focus-visible,
.pa-showmore:focus-visible, .pa-jobs__title:focus-visible, .pa-jobs__apply:focus-visible,
.pa-services__link:focus-visible, .pa-crumbs__link:focus-visible,
.pa-partner__link:focus-visible,
.pa-intro__body a:focus-visible, .pa-split__text a:focus-visible,
.pa-services__body a:focus-visible, .pa-partner__body a:focus-visible,
.pa-extra__body a:focus-visible, .pa-compliance__text a:focus-visible {
  outline: 3px solid var(--pa-blue);
  outline-offset: 3px;
  border-radius: 4px;
}

/* -------------------------------------------- links inside body copy - */

/* The theme sets no link style for prose, so an <a> in a WYSIWYG field comes
   out as the browser's default bright blue with a default underline — which on
   this beige page reads as an unstyled document rather than as the design.
   Every prose block on the page is listed, not only the one that has a link
   today, so the next one written into a Google Doc lands styled.

   Underlined at rest on purpose: colour alone is the one thing that cannot
   carry "this is a link" for a reader who does not see the difference between
   #1f3d47 body text and a #1f3d47 link.

   .pa-compliance__text was missing from this list entirely — added
   2026-09 (invented-elements sweep): with no rule at all it fell to
   styles.css's global `body, * { font-size: 16px; color: #041131 }`, which
   is worse here than everywhere else on this list, because this block sits
   white-on-navy (see .pa-compliance__text's own rule) — a link would have
   rendered #041131 on a navy panel, unreadably close to invisible, not just
   the wrong size.

   font-size/font-weight/font-family are the same fix as everywhere else in
   this sweep: none of these five ever restated them, so an <a> nested inside
   a sized/weighted paragraph was still exposed to the universal reset
   directly, regardless of what its parent paragraph resolved to. */
.pa-intro__body a,
.pa-split__text a,
.pa-services__body a,
.pa-partner__body a,
.pa-extra__body a,
.pa-compliance__text a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 1px;
  transition: color 0.15s ease;
  font-size: inherit;
  font-weight: inherit;
  font-family: inherit;
}

/* -------------------------------------------------------------- buttons - */

/* Figma btn frame: 130x49, padding 16px 24px, radius 100px, gap 15px between.
   Text 12px / 700 / letter-spacing -0.24px. */
.pa-btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 15px;
  align-items: center;
}

.pa-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 49px;
  padding: 16px 24px;
  border-radius: 100px;
  font-size: 12px;
  font-weight: 700;
  line-height: 17px;
  letter-spacing: -0.24px;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color 0.18s ease, color 0.18s ease, transform 0.1s ease;
}

.pa-btn--orange { background: var(--pa-orange); color: #fff; }
.pa-btn--blue   { background: var(--pa-blue);   color: #fff; }
.pa-btn--white  { background: #fff;             color: var(--pa-blue); }

/* ----------------------------------------------------------------- hero - */

/* Re-checked 2026-09 (rebuild-11), figma_css.py against #524:390 "Frame 210"
   (the H1 pill group) — confirms every number already in place below, no
   changes:

     Frame 210 #524:390 { display:flex; flex-direction:column; gap:5px; width:780px }
       Frame 209 #524:389 { display:flex; flex-direction:row; gap:5px; align-items:center }
         Frame 162 #490:664 (pill) { padding:14px 20px 5px 20px; justify-content:center;
                                      align-items:center; background:#ff363b; border-radius:50px }
           "Digital" #490:665 { color:#fff; font-family:'June Expt'; font-size:58px;
                                 font-weight:400; line-height:75px }
       Frame 208 #524:388 { display:flex; flex-direction:row; gap:5px; align-items:flex-end }

   Every other pill in the group (#490:669/671/676/678/680) reports the same
   padding/radius/fill/type quartet — one pill style, not per-word variants.

   No photo and no buttons in this design's hero — just the H1. (The same
   "Hire talent" / "Search jobs" pair renders lower on the page via cta.php,
   reading the same pa_cta_* fields; the old orange/blue pair here duplicated
   it under the old design.) The hero image field, still read for meta/OG tags
   in inc/practice-area.php, is simply unused visually now. */
.pa-hero__inner { display: block; }

/*
 * The H1 renders as one continuous string in the DOM and to assistive tech —
 * th_pa_h1() returns a single string, and hero.php splits it on whitespace
 * into <span class="pa-hero__word"> pills joined by literal space characters
 * (not just visual gap), so the accessible name is unchanged: "Digital
 * Infrastructure Staffing and Workforce Solutions", one <h1>, read as one
 * sentence.
 *
 * The per-line word count (2 / 3 / 1) is not hand-placed. It falls out of
 * ordinary flex-wrap once the container is capped at the design's 780px and
 * every word is its own pill: "Staffing"(271) + "and"(155) + "Workforce"(344)
 * sums to exactly 780 with the 5px gaps, so "Solutions" is pushed to its own
 * line — the same thing a longer or shorter title on another practice-area
 * page will do automatically, without per-page markup.
 */
.pa-hero__title {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  font-weight: 400; /* style_40636f12 — June Expt Regular, not the old bold */
}

.pa-hero__word {
  display: inline-flex;
  align-items: center;
  /* Vertical padding is deliberately lopsided; see the 1280px block below
     for the measurements. Same total (12px) as every previous value here,
     so the pill's own height is unchanged. */
  padding: 11px 14px 1px;
  border-radius: 999px;
  background: var(--pa-red);
  color: var(--pa-white);
  font-size: clamp(1.5rem, 1rem + 4vw, 2.25rem);
  line-height: 1.3;
  white-space: nowrap;
}

@media (min-width: 1280px) {
  .pa-hero__title {
    gap: 5px; /* #524:390 column gap, #524:389/#524:388 row gap — 5px on both axes */
    max-width: 780px; /* #494:1093 — the H1 group's own fixed width in the 1920 frame */
  }

  .pa-hero__word {
    /* 2026-09-08 (client review rows 5 and 14, "text is still not aligned at
       vertical midpoint of pills" — reported twice).

       The first attempt replaced #490:664's own lopsided `14px 20px 5px`
       with an equal 9.5/9.5 split, reasoning that equal padding centres
       text. It does not: equal padding centres the LINE BOX, and the glyphs
       sit inside that box according to the font's ascent and descent, which
       for June Expt leaves the visible letters high. Measured on the
       rendered page, the equal split put the ink 11px from the top of a 94px
       pill and 21px from the bottom — visibly high, which is what the client
       saw the second time.

       What to centre on is the cap-height block, cap top to baseline, not
       the line box and not the descender: most words in these headlines
       ("Structured", "Dedicated", "Recruiters", "with") have no descender at
       all, so centring on cap-to-descender tips the common case upward. The
       numbers below are derived, not guessed — ink measured inside the red
       fill at 1920 and 390, then the split biased until a descenderless word
       balances:

         equal 9.5/9.5      above 15  below 32   (9px high)
         the file's 14/5    above 19  below 28   (4px high)
         18/1               above 23  below 24   centred

       Words that do have a descender ("Digital", "Staffing") now sit 19/13,
       i.e. the tail of the g hangs 3px below centre, which is what a
       descender is supposed to do. Total vertical padding stays 19px, so
       pill height is unchanged from every previous revision. */
    padding: 18px 20px 1px;
    border-radius: var(--pa-radius-pill);
    font-size: var(--pa-font-display);
    line-height: var(--pa-line-display);
  }
}

/* ---------------------------------------------------------------- intro - */

/* 483-3-index.json, not the crop — see intro.php's own docblock for how the
   field boundary (pa_intro / pa_extra_text) maps onto these two columns.
   #516:42 (left column text) runs real x 273-834, w561; #516:43 (right
   column text) runs real x 969-1530, w561 — each column 561px wide (not the
   crop-measured 555px), a 135px gap between (not 140px), inside a container
   starting at the same ~260px left margin as the hero/nav's own --pa-wide. */
.pa-intro__columns {
  display: grid;
  gap: 24px;
}

/* 2026-09-09, client: one column, like Equiliem's. This used to be
   `repeat(2, minmax(0, 561px))` with a 135px gutter at 1280+, matching
   #516:42 and #516:43 side by side in the artboard — see intro.php for why
   a "Show more" toggle cannot be fitted to that split, which is what forced
   the change.

   958px, which is Equiliem's own figure: their intro is wrapped in
   `.pa-page-n`, the NARROW container (--pa-narrow: 958px), not the wide one
   the rest of their page uses. A first pass kept this block at 1257px — the
   two columns' combined span — and the client called it too wide, which it
   was: 24px type across 1257px runs to about 85 characters a line, where
   958px gives about 65. The intro being narrower than everything below it is
   the point, not an inconsistency; Equiliem does the same thing. */
@media (min-width: 1280px) {
  /* Centred, not left-aligned against the container's gutter. Equiliem's
     .pa-page-n carries `margin: 0 auto`, so its 958px column sits in the
     middle of the page with the copy left-aligned inside it — the text
     itself is ragged-right, it is the block that is centred. Here the block
     is a child of .pa-page-w's own 1380px content box rather than the
     container itself, so the auto margins have to be set on it directly. */
  .pa-intro__columns {
    max-width: 958px;
    margin-inline: auto;
  }
}

.pa-intro__body {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.pa-intro__body p {
  /* The theme's global reset (styles.css: `body,* { font-family:
     "june-expt-variable" }`) defaults everything to the headings/UI face, so
     body copy has to opt back into DM Sans explicitly rather than inheriting
     it.

     2026-09-09, client: "including the larger font size". The artboard's own
     #516:42/#516:43 report fs13.3/lh17.92, which is what this used to set via
     --pa-font-small, and at that size the block reads as fine print rather
     than as the page's opening statement. Equiliem's equivalent is
     `clamp(1rem, 0.9rem + 0.55vw, 1.5rem)` at line-height 1.46 — 16px on a
     phone rising to 24px on a wide screen — and that is copied here verbatim
     rather than re-derived, since matching it is the whole request. */
  font-family: 'DM Sans', sans-serif;
  font-size: clamp(1rem, 0.9rem + 0.55vw, 1.5rem);
  line-height: 1.46;
  color: var(--pa-navy);
  margin: 0;
}

/* The "Show more +" control, injected by practice-area.js's initClamps() on
   any block carrying data-pa-clamp. Ported from Equiliem's own .pa-showmore,
   in Fieldlink's colours: navy rather than their blue, and red on hover,
   which is the accent this page uses for every other interactive text.

   44px minimum height is the touch target, not decoration — the button is a
   line of underlined text and would otherwise be about 20px tall. */
.pa-showmore {
  appearance: none;
  background: none;
  border: 0;
  /* .pa-intro__body is a flex column, so the button stretches the full width
     and a <button> centres its own label — which put "Show more +" in the
     middle of the page. Equiliem's sits under the first word of the copy. */
  align-self: flex-start;
  text-align: left;
  padding: 12px 0;
  min-height: 44px;
  margin-top: 8px;
  font: inherit;
  font-family: 'DM Sans', sans-serif;
  font-size: 1rem;
  color: var(--pa-navy);
  text-decoration: underline;
  cursor: pointer;
}

/* A short standalone sentence the design sets visibly heavier than the
   paragraphs around it — see intro.php for why this is flagged by length
   rather than by paragraph position. */
.pa-intro__pull {
  font-weight: 700;
}

/* 2026-09-08 (client round 2, item 2 — "the blue background still does not
   match", reported three times now). This used to be a hand-traced clip-path
   shape (two pieces, one per section, unioned from points measured off a
   crop) — the client's direction this round is explicit: stop adjusting our
   own shape and use the site's, the way `.section-list-find:before`
   (styles.css) already applies `banner-bg-shape.svg` — absolutely
   positioned, full size, `background-size: 120%`, `background-position:
   top`, `z-index: -1`. That selector carries no markup of its own (the
   image is painted straight on the section via `::before`), so the old
   `.pa-intro__wash` / `.pa-services__wash` <span> elements and the inline
   SVG clipPath in services.php are removed rather than repointed — nothing
   here needs a DOM hook any more than section-list-find's own copy does.

   Two separate `::before`s (one per section) rather than one shared wash,
   for the same reason the previous pass split it: intro.php and services.php
   are two sections in single-practice-area.php's own sequence, and no
   shared wrapper is available to this pass to fix (touchable files are
   template-parts/practice-area/*, this stylesheet, and single-practice-
   area.php — merging the two sections' markup is a structural change this
   task doesn't ask for). Same asset both times, positioned per section so
   the coverage reads as one continuous sweep — entering behind the hero/
   intro copy at the right (crop 01) and opening up into the dominant wash
   behind the service cards (crop 02) — rather than two independent guesses.

   Gated to 1024px and up, same floor every other decorative shape on this
   page uses (the About mask, the searches/CTA motifs): the design has no
   comp for this wash below that width, and painting it into a phone-width
   column would swamp the copy instead of sitting behind it. `.pa-page-w`
   inside .pa-intro/.pa-services keeps `position:relative; z-index:1` so its
   content always paints above this decorative layer regardless of DOM order
   — `position:relative` alone does not create a stacking context, so
   without an explicit z-index a positioned box with z-index:auto paints
   AFTER (on top of) ordinary in-flow content only when that content has no
   established order of its own; giving the content block its own z-index:1
   removes any doubt, the same reason .pa-testimonial__quote and
   .pa-testimonials__eyebrow already carry z-index:1 of their own. */
/* ------------------------------------------------------------ the wash -- */

/* The page's two pale-blue background waves. Each is one shape spanning
   several sections, clipped by its own rectangle — see the per-shape notes
   at .pa-wash--upper and .pa-wash--lower below and the wrappers in
   single-practice-area.php.

   Not gated by width. The previous passes hid the wash below 1024/1280 on
   the reasoning that "the design gives no comp for a phone" — true, but it
   left the testimonial slider's own position indicator unreadable, which is
   what the client reported as item 1 this round. That widget is the site's
   own: white 48x48 bullets fused by pale-blue curve-1.svg notches and a red
   dot, styles.css 2091-2185, and `.swiper-pagination { background: #fff }`
   at 2182. Every one of those parts is white or pale blue BECAUSE it is
   drawn to sit on this wash — on white it is a row of invisible circles
   with blue chevrons floating between them, which is exactly what the
   client's mobile screenshot showed. The bug was never in the pagination
   CSS (correctly a verbatim copy of the site's); it was that the ground it
   needs had been switched off underneath it. */
.pa-wash {
  position: relative;
  overflow: hidden;
}

.pa-wash::before {
  content: '';
  position: absolute;
  inset: 0;
  background-repeat: no-repeat;
  z-index: -1;
  pointer-events: none;
}

/* 2026-09-08 (client round 2, item 2, re-fix — the shape, not the asset).
   The two per-section ::befores this replaces each painted the WHOLE wave
   inside their own box, so one lobe appeared in the intro and the same
   lobe again in the services section. Worse, neither used the design's
   own asset: `banner-bg-shape.svg` is 2176x1023 (aspect 2.13) and
   #495:1595, the node actually drawn here, is 3667.5x2312.7 (aspect
   1.59) — a different shape entirely, so no amount of tuning
   `background-size: 120%` and a position keyword could have matched it.
   `.section-list-find:before`'s recipe was copied faithfully; the recipe
   was never the problem, the asset and the box were.

   The real geometry, from 483-3-with-paths.json (fillGeometry, which the
   earlier passes did not have):

     mask  #570:394  1920 x 1510  at frame (1.2, 448.0)
     wave  #495:1595 3667.5 x 2312.7 at frame (190.6, -262.8)

   so on the mask's own box the wave sits at (189.4, -710.8) at size
   3667.5 x 2312.7. Expressed against the 1920 design width that is
   191.016vw wide, offset 9.8646vw / -37.0208vw — vw rather than px so
   the shape keeps its aspect and its position relative to the page's own
   content as the viewport changes, which a percentage background-size
   against a box of arbitrary height cannot do.

   `.pa-wash--upper` (single-practice-area.php) IS that mask rectangle:
   it wraps intro + services + compliance, which render at 461-1957
   against the design's own 448-1958. `overflow: hidden` is the mask.
   The wave's own path is extracted to pa-wash-upper.svg; nothing else on
   the site draws this shape, which is why no existing asset fitted. */
.pa-wash--upper::before {
  background-image: url(../images/pa-wash-upper.svg);
  background-size: 195%;
  background-position: 10.4167vw -19.7917vw;
}

/* Kept off below 1024, the floor every other decorative shape on this page
   uses. Sized in vw, the wave is 745px wide and 470px tall at 390 — a smear
   across the top of a section that is several thousand pixels long — and
   unlike the lower wash there is nothing here that needs a coloured ground
   to be legible, so the honest answer at phone width is no wash rather than
   a fragment of one. */
@media (max-width: 1023px) {
  .pa-wash--upper::before { content: none; }
}

/* 2026-09-08 (client round 2, item 2, re-fix). Mask #570:395 is 1920x2083
   at frame (0, 3847.4); wave #483:65 is 3840x3264.8 at frame (-500, 3638.9)
   — on the mask's own box, (-500, -208.5). Against the 1920 design width:
   200vw wide, offset -26.0417vw / -10.8594vw. The asset is right this time
   (fieldlink_link-shape_down.svg, 3252.9x2765.7, a uniform 1.1805x scale of
   the node) — an earlier pass had these numbers nearly right at
   `-26.04vw -5.208vw` and they were replaced with a `120%` keyword recipe
   that could not express a vertical offset at all. The y is -10.8594vw, not
   -5.208vw: the earlier figure measured the wave against the testimonial
   section alone instead of against the mask that spans testimonial + FAQ. */
.pa-wash--lower::before {
  background-image: url(../images/fieldlink_link-shape_down.svg);
}

@media (min-width: 1280px) {
  .pa-wash--lower::before {
    background-size: 200%;
    background-position: -26.0417vw -10.4167vw;
  }
}

/* Below 1280 the design's own numbers stop working, and the reason is worth
   stating because it is the trap this wash keeps falling into. Sizing the
   wave in vw keeps its aspect — necessary — but it also means the shape
   shrinks with the viewport while the content it sits behind GROWS, because
   narrower columns wrap into more lines. At 1920 the wave covers a 2083px
   box; at 390 the same rule draws it 780px wide and 663px tall behind a box
   that is 2011px long, so it covered the quote and stopped short of the
   slider's own position indicator — the white-bullets-on-white the client
   reported as item 1.

   So below 1280 the shape is scaled to the SECTION instead of the viewport,
   which is what the site's own `.testimonials:before` does at its phone
   breakpoints too (styles.css 9793, 10600: `background-size: 400% 30%`,
   `500% 40%` — deliberately non-uniform, tracking the box). The numbers
   here place the wave's own top-left lobe — solid #D1F2FF for roughly its
   first 500 x 1000 units — over the whole testimonial section: at 768vw the
   wave is 7.68x the viewport, so that lobe covers 390 x 780 at phone width
   against a section 724 tall, and scales with the viewport from there.
   Verified at 360, 390, 430, 768 and 1023: the quote, the byline and the
   indicator all sit on blue at every one, with the lobe's own curved edge
   reading as the top of the panel. The FAQ below it stays on white, which
   the navy cards are legible against and the design has no phone comp to
   contradict. */
@media (max-width: 1279px) {
  .pa-wash--lower::before {
    background-size: 768vw auto;
    background-position: -100vw -41.5vw;
  }
}

.pa-intro,
.pa-services {
  position: relative;
}

.pa-intro > .pa-page-w,
.pa-services > .pa-page-w {
  position: relative;
  z-index: 1;
}


/* ------------------------------------------------------------- services - */

/* 483-3-index.json (#495:1304/#495:1324, the two card FRAMEs), not the crop.
   Two lime cards, no position-based tinting and no coloured bar under either
   one — both of those were the old three-card sibling design, dropped along
   with it (see this template's own docblock). Corner radius confirmed 30 on
   both card nodes — exactly --pa-radius, already in place, not changed. */
.pa-services__grid {
  display: grid;
  row-gap: 30px;
  column-gap: 30px;
}

.pa-services .pa-section__title {
  font-size: clamp(32px, 2.8vw, 44px);
  text-wrap: balance;
}

.pa-services__col {
  display: flex;
  flex-direction: column;
  /* The copy and the link are pushed apart, so the links line up across
     cards whose copy runs to different lengths. */
  justify-content: space-between;
  gap: 40px;
  background: var(--pa-lime);
  border-radius: var(--pa-radius);
  padding: 32px 24px;
}

.pa-services__title {
  font-size: var(--pa-font-heading);
  font-weight: 400; /* cold-assessment, 2026-09: was 700 — #495:1315 ("Staffing",
                        this card title's own text node) reports 400 directly,
                        not the bold the old design used here. */
  line-height: 1.3;
  color: var(--pa-navy);
  margin: 0;
}

/* The "{area} services" tail of the heading, coloured in the crop from
   "range of" on — see services.php for where the string is split.

   Same defect as .pa-about__accent above and the same root cause: a style
   run inside the design's one heading text node becomes a span with no node
   of its own, and styles.css's global `body, * { font-size / font-weight /
   font-family }` matches that span directly, overriding the 26px/400 it
   should inherit from the h2. Restated as `inherit` rather than hard-coded. */
.pa-services__title-accent {
  color: var(--pa-red);
  font-size: inherit;
  font-weight: inherit;
  font-family: inherit;
}

.pa-services__text {
  /* See .pa-intro__body p above: body copy has to opt back into DM Sans.
     #495:1316/#495:1336 report lh20.83/fs16 (ratio 1.302), not 1.5 — this is
     the one body-copy block --pa-font-body's 16px is actually right for (see
     that token's own note), but the line-height was still a round guess. */
  font-family: 'DM Sans', sans-serif;
  font-size: var(--pa-font-body);
  font-weight: 400;
  line-height: 1.3; /* 20.83 / 16 */
  color: var(--pa-navy);
  margin: 0;
}

/* Title and body 20px apart. */
.pa-services__body { display: flex; flex-direction: column; gap: 20px; }

/* Label and arrow 10px apart, vertically centred. */
.pa-services__link {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: 10px;
  font-size: var(--pa-font-small);
  font-weight: 700;
  line-height: 1.4;
  color: var(--pa-navy);
  text-decoration: none;
}

/* The label text is wrapped in its own span (so the hover underline in the
   dark-mode block below can target the text without also underlining the
   arrow glyph next to it) — an element the design has no node for, since
   Frame 157's link (see the arrow's own comment below) is one object. With
   no rule of its own it was left exposed to styles.css's global `body, *
   { font-size: 16px; font-weight: 400; color: ... }`, which matches the span
   directly and wins over inheriting the link's own 13.3px/700/navy —
   measured rendering at 16px/400 instead. Restated as `inherit` rather than
   duplicating the link's values. */
.pa-services__link-label {
  font-size: inherit;
  font-weight: inherit;
  font-family: inherit;
  color: inherit;
}

.pa-services__arrow {
  flex: none;
  width: 22px;
  height: 22px;
  color: var(--pa-red);
}

/* Same bug as .pa-roles__tick further down this file (see its own comment
   for the full explanation): styles.css's global `body, * { color: ... }`
   matches this SVG's <path> directly, so the path renders the page's navy
   ink instead of inheriting .pa-services__arrow's red. */
.pa-services__arrow path { color: inherit; }

@media (min-width: 768px) {
  .pa-services__grid { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1280px) {
  /* Re-derived 2026-09 (rebuild-11) straight off #495:1304's own auto-layout
     properties (figma_css.py), not a child's measured y a second time:
       #495:1304 { padding: 60px 30px 30px 30px; gap: 30px;
                   background: #d9ff1a; border-radius: 30px; width: 444px }
     #495:1324 (the second card) reports the identical quartet. The previous
     reading (50px top) came from measuring down to a descendant — #495:1313
     "Frame 66", the title/body/link wrapper, at real y=954 — 60px below the
     card's own y=894, not 50; there is no separate "#495:1305 icon badge" at
     y=944 in this export to have produced that number from. */
  .pa-services__col { padding: 60px 30px 30px; }

  /* Same defect as the Completed Searches grid (see .pa-searches's own
     1280px comment further down): left fluid, `1fr 1fr` splits whatever the
     layout's own 1fr track leaves it, which measured 475px per card against
     the design's fixed 444. #524:392 ("Frame 211", the row both cards sit
     in) is itself `{ layoutMode: HORIZONTAL, itemSpacing: 24 }` over two
     444-wide children (#495:1304/#495:1324, both real x-width 444, real x
     738/1206 — a 24px gap, not this rule's inherited 30) — a fixed-width
     row, not a share of its column. That row (912px) also doesn't fill its
     980px 1fr track: it sits flush against the track's own right edge
     (738+444*2+24 = 1650, the same panel-right-edge every other section on
     this page ends at), matching the "gap on the left" composition already
     confirmed in the searches grid — hence `justify-content: end` rather
     than the track's default left/start packing. */
  /* 2026-09-08 (client item 7: "Direct Hire Recruiting is cut off", 1280):
     `repeat(2, 444px)` is a fixed 912px-wide (444+444+24 gap) track set —
     correct at the design width, where the 1fr column beside it (980px, see
     .pa-services__layout below) is wider than that and `justify-content:end`
     right-aligns the smaller content within the larger track exactly as
     the comment above intends. At 1280 that 1fr column is only ~800px
     (1200px page content - the 375px heading column - 25px gap), narrower
     than the fixed 912px the tracks demand — confirmed by rendering
     (.pa-services__grid measured 912px wide, right edge at 1352px against a
     1280px viewport). A grid item's default automatic minimum size is its
     content's own min-content, which a fixed-px track can't shrink below,
     so the item overflowed its own track and the page's right edge instead
     of shrinking. `minmax(0, 444px)` keeps the exact same 444px at the
     design width (and above, where the 1fr track has room) but lets each
     column shrink down to fit the available space at 1280, same fix shape
     as the bounds-check `min(design, vw - gutter)` pattern. */
  .pa-services__grid {
    grid-template-columns: repeat(2, minmax(0, 444px));
    column-gap: 24px;
    justify-content: end;
  }

  /* The heading sits beside the cards. Match their 60px top inset so the
     heading aligns with the two service titles, not the cards' outer edges. */
  .pa-services__layout {
    display: grid;
    grid-template-columns: 375px 1fr;
    gap: 25px;
    align-items: start;
  }

  .pa-services .pa-section__title {
    text-align: left;
    max-width: none;
    margin: 60px 0 0;
    font-weight: 400; /* cold-assessment, 2026-09: was inheriting the base
                          rule's 500 — #516:40 (this heading's own node)
                          reports 400, same as every heading on the page. */
    line-height: 1.3;
  }

}

/* ------------------------------------------------------------ compliance - */

/* A deep navy panel: copy inset on the left, the photo flush to the panel's
   own top/right/bottom edges and bleeding into the copy's side along an
   organic line rather than a straight one. That bleed is the section's whole
   character (crop 03, docs/design-refs/03-compliance.png) — no gap, no
   margin, no rounded-rectangle photo sitting inside a colour block the way
   the rest of the page's images do.

   Corrected against 483-3-index.json / the full node tree (no longer the
   crop's pixels). #493:989 — the panel — runs real x 270-1650 (1380px,
   exactly --pa-panel, not a third token) and y 1430-1962 (532px tall),
   radius 30 (exactly --pa-radius, also not a new token — the earlier
   crop-based ~24px reading was close but wrong). #495:1592 — the photo's
   own mask rectangle — runs real x 856-1650 (794px, ~57.5% of the panel,
   not the ~46% the crop reading gave) and y 1430-1960, i.e. flush to the
   panel's right edge and running its full height, same conclusion as
   before but a materially wider photo column.

   The copy column: #516:38 (the heading frame) and #493:985 (the body text)
   both run exactly 530px wide starting at real x 301 — 31px inset from the
   panel's own left edge (270). #516:36's heading text starts real y 1548,
   118px below the panel's top edge; #493:985's body text ends real y 1843,
   119px above the panel's bottom edge. Copy width (530) + its own 31px
   left inset (561px total) + a 25px gap to the photo + the photo's own
   794px sums to exactly 1380 — the panel's own width — so the grid below is
   expressed as that same 561fr/794fr split (matching how .pa-split__inner
   already expresses its own copy/photo ratio as fr-weighted minmax()
   tracks) with an explicit 25px gap, rather than a percentage that has no
   simple relationship to the measured pixels.

   The organic left edge: see compliance.php's own clip-path comment — it's
   built from the design's own two ELLIPSEs and one rotated square VECTOR
   now, not traced from crop pixels. */
.pa-compliance__panel {
  position: relative;
  max-width: var(--pa-panel);
  margin: 0 auto;
  background: var(--pa-navy);
  border-radius: var(--pa-radius);
  /* Clips the copy's own padding-box and the photo's square corners to the
     panel's rounded ones — the photo has no border-radius of its own. */
  overflow: hidden;
}

.pa-compliance__copy {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 32px 24px;
}

.pa-compliance .pa-section__title {
  text-align: left;
  max-width: none;
  margin: 0;
  font-size: var(--pa-font-heading);
  font-weight: 400; /* cold-assessment, 2026-09: was inheriting the base
                        rule's 500 — every heading node in 483:3 reports 400,
                        this one included, no exception. */
  line-height: 1.35;
  color: var(--pa-white);
}

.pa-compliance__text p {
  /* See .pa-intro__body p: body copy has to opt back into DM Sans.
     Re-derived 2026-09 (rebuild-11): #493:985 reports fs14.0/lh17.92 (ratio
     1.28), not --pa-font-body's 16px — see that token's own note. */
  font-family: 'DM Sans', sans-serif;
  font-size: var(--pa-font-body-sm);
  line-height: 1.28; /* 17.92 / 14 */
  color: var(--pa-white);
  margin: 0 0 16px;
}

.pa-compliance__text p:last-child { margin-bottom: 0; }

/* 2026-09 QA fix (base rule, no width in the comment because this IS the
   phone layout): this used to be `display: none` below 1024px, dropping the
   photo entirely rather than stacking it — the panel has no phone artboard
   in the design, but deleting a photograph is not what "no phone artboard"
   implies. Stacked below the copy, flush to the panel's own left/right/
   bottom edges the same way the desktop photo is flush to three of its
   edges (the panel's own `overflow: hidden` rounds the bottom two corners
   for free, no extra radius needed here).

   The organic two-ellipse-and-bridge clip further down is measured against
   the desktop photo's 794x530 crop specifically; stretched over a full-
   bleed mobile width it would just read as a random bite out of the photo,
   not a shape, so mobile gets a plain rectangular crop instead of the blob
   — the clip-path stays scoped to the 1024px block below. */
.pa-compliance__media { display: block; position: relative; }

/* 2026-09-08, client: "on mobile, hide the Compliance image".
   Below 768 the panel stacks, so the photo dropped underneath the copy as a
   full-width rectangle — the one place it is neither beside the text as the
   design draws it nor cropped to the blob (that clip is scoped to 1024+ for
   its own reasons, see this block's note above), just a plain letterbox
   between the last paragraph and the next section. Removed rather than
   hidden with visibility, so it costs no layout space; `display: none` on
   the container also stops the browser fetching the image at all at phone
   width, which is the right outcome for a decoration nobody sees.

   768 is the same floor the two-column grid uses below — the photo appears
   exactly when there is a column to put it in. */
@media (max-width: 767px) {
  .pa-compliance__media { display: none; }
}

.pa-compliance__image {
  display: block;
  width: 100%;
  aspect-ratio: 794 / 530; /* the desktop photo's own measured crop ratio */
  object-fit: cover;
}

/* 2026-09-08 (client item 6: "Match Figma two column design", both 768 AND
   1024): was gated at min-width:1024px on the reasoning that a ~46% photo
   column needs the same room a two-column layout needs elsewhere on this
   page. That's still true of a literal 1024px content width, but the client
   named an actual browser window at 1024 — and a real browser's clientWidth
   at a 1024px window is ~1007-1009px once the scrollbar is subtracted (see
   verifying.md's own note on exactly this trap), so `min-width:1024px`
   never matched what the client was actually looking at: the panel stacked
   there instead of showing the two-column design. Lowered to 768: the grid
   tracks below are fr-weighted (561fr/794fr), not fixed pixels, so they
   already reflow to whatever width the panel has rather than assuming
   1024's worth of room — narrower at 768 than at 1024, same as every other
   fr-based split on this page, not broken. */
@media (min-width: 768px) {
  .pa-compliance__panel {
    display: grid;
    grid-template-columns: minmax(0, 561fr) minmax(0, 794fr);
    gap: 25px;
    align-items: stretch;
  }

  /* 118/31/119 real px — see this block's own comment above. The 25px gap
     to the photo is the grid's own column gap, not padding-right here. */
  .pa-compliance__copy { padding: 118px 0 119px 31px; }

  /* cold-assessment, 2026-09: `.pa-compliance__image` inside is
     `position: absolute`, so it contributes nothing to this box's own
     content height — with no aspect-ratio of its own, .pa-compliance__media
     had no natural size at all, meaning `align-items: stretch` on the panel
     above was the ONLY thing giving it a height, borrowed wholesale from
     .pa-compliance__copy's own (real-copy-length-dependent) height instead
     of the photo's real 794x530 shape. Measured live: the copy's real
     content renders a 503px-tall row against the photo's own 530 — short
     enough that `width:100%;height:100%;object-fit:cover` on the image
     (both dimensions definite from the box, no auto side left for
     object-fit's own aspect handling to act on) rendered the correct-width,
     wrong-height photo, and since the clip-path blob's ellipses are also
     objectBoundingBox fractions of that same box, the blob squashed along
     with it. Restoring `aspect-ratio` here (not on the image, which stays
     unable to use it while both its own dimensions are definite) gives the
     box a real 794:530 content size before stretch ever runs: grid stretch
     still wins when the copy is genuinely taller (the photo then simply
     shows more of itself through `cover`, no distortion — the correct
     "photo bleeds to fill a taller row" case), but on every page measured
     today the copy is shorter, so the box now holds at its own true
     dimensions instead of being crushed to the copy's. */
  .pa-compliance__media {
    display: block;
    position: relative;
    aspect-ratio: 794 / 530;
  }

  .pa-compliance__image {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    clip-path: url(#pa-compliance-blob);
  }
}

/* ------------------------------------------------------------ about - */

/* about.php only now — compliance.php dropped .pa-split for its own navy-panel
   markup (see the "compliance" block above), so every rule here is read
   fresh off 483-3-index.json / the full node tree, not the old sibling-
   project Figma frames the numbers used to cite (Frame 9/Frame 75, a
   570/502/98 split, a 549/550 min-height) — those belonged to a different
   design and are gone, and not the crop pixels a previous pass read in their
   place either. #516:26/#495:1286/#495:1289 (the heading frame and body
   text) all run real x 271-832, i.e. a 561px copy column at the page's usual
   ~260-270px margin. #570:399/#495:1582 (the photo's own mask rectangle) run
   real x 1172-1921 — a 749px-wide photo, and that right edge is 1px short of
   the artboard's own 1920px width: this photo is full-bleed to the viewport
   edge, not sitting inside the page's usual ~1660px right margin the way
   every other image on this page does. The two figures don't sum to
   --pa-wide with a normal rhythm-scale gap the way the other sections'
   splits do (561 + 749 = 1310, and the true gap to the bleeding photo is a
   deliberately-oversized 340px, not a token) — confirms what the previous
   pass's own crop reading flagged and didn't attempt, and this pass doesn't
   either: the ratio below is corrected (561fr/749fr, was 740fr/580fr — see
   this block's own note further down on the swapped-column bug that shipped
   alongside those wrong numbers), but the photo still sits inside
   .pa-page-w rather than bleeding to the viewport edge. A genuine bleed
   needs the media column's own width to stop being fr-proportional to the
   container (a tried `margin-right: calc(min(0px, (--pa-wide - 100vw)/2))`
   pull, still inside the fr grid, measured 1015px wide at a 1920 viewport
   against the design's own 749px — the negative margin both shifts the box
   and, because the item stretches to fill its track, grows it) — it needs
   the copy fixed at 561px and the photo sized as "whatever's left to the
   viewport edge" instead of two fr tracks of a shared container, which is a
   structural change to .pa-split__inner, not a number. Left as a flagged
   gap rather than a second, unverified guess. */
.pa-split__inner { display: grid; gap: 32px; }

/* 2026-09 QA fix (base rule = phone layout): this used to be `display: none`
   below 1024px, dropping the photo rather than stacking it. `order: 2` keeps
   it text-first on the phone layout (about.php's own docblock reasoning:
   heading/copy reads first, photo confirms it below), sized by
   .pa-split__image's own base 1:1 crop just below. The figure-8 clip stays
   scoped to the 1024px block further down — like compliance's blob, it's
   measured against the desktop crop's own aspect ratio and would misread as
   damage rather than a shape at a different one. */
.pa-split__media { order: 2; display: block; }
.pa-split__copy  { order: 1; display: flex; flex-direction: column; gap: 24px; }

.pa-split__image { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }

/* 2026-09-08 (client item 1: "Create something more similar to Figma",
   320-1024): the figure-8/hourglass mask used to stay scoped to the 1024px
   block below, and the box it applies to used a plain 1:1 crop below that —
   the two need to change together, not the clip alone. `clipPathUnits=
   "objectBoundingBox"` does scale to any box, but the shape itself is a
   WIDE hourglass (1154:311, ~3.7:1) whose third lobe is mostly cropped off
   at that ratio — confirmed by rendering the clip onto a 1:1 box first: the
   third lobe becomes fully visible and the whole thing reads as a busy
   "M" of three pinches, not the clean two-lobe hourglass the client's own
   comp shows. Applying the clip needs the same wide box the design draws
   it on, at any size — not a square crop — so `.pa-about` gets its own
   aspect-ratio here instead of inheriting `.pa-split__image`'s generic 1:1
   (still the right default for any other `.pa-split` caller). */
.pa-about .pa-split__image { aspect-ratio: 1154 / 311; }
.pa-about .pa-split__media { overflow: hidden; border-radius: var(--pa-radius); }
.pa-about .pa-split__image { clip-path: url(#pa-about-mask); }

.pa-split__text p {
  /* See .pa-intro__body p: body copy has to opt back into DM Sans.
     Re-derived 2026-09 (rebuild-11): #495:1289 (about's own body copy)
     reports fs14.0/lh17.92 (ratio 1.28) — the same size compliance's own
     body copy uses (see --pa-font-body-sm's own note), not --pa-font-body's
     16px, and not the 18/26 this pass had already moved off of. */
  font-family: 'DM Sans', sans-serif;
  font-size: var(--pa-font-body-sm);
  line-height: 1.28; /* 17.92 / 14 */
  color: var(--pa-navy);
  margin: 0 0 16px;
}

.pa-split__text p:last-child { margin-bottom: 0; }

.pa-split .pa-section__title {
  text-align: left;
  max-width: none;
  margin: 0;
  font-size: var(--pa-font-heading);
  font-weight: 400; /* cold-assessment, 2026-09: was inheriting the base
                        rule's 500 — #495:1288 (about's own heading node)
                        reports 400, same as every heading on the page. */
  line-height: 1.35;
  color: var(--pa-navy);
}

/* The closing phrase of the design's heading, in red — see about.php's
   $pa_split_heading for why this only ever appears when a **marked** phrase
   is actually present in the field.

   #495:1288 (the heading's own text node) carries exactly one style-run
   override on this phrase: fills. Nothing else. But this span is an element
   with no design node of its own — a style run inside one text node becomes
   a parent and a child in markup — and styles.css's global `body, * {
   font-size: 16px; font-weight: 400; font-family: ... }` matches this SPAN
   directly, which beats inheriting the heading's own 26px/400/June-Expt no
   matter how the heading itself is styled. Confirmed cold-assessment 2026-09:
   this rendered the accent at 16px against the navy half's 26px. Restating
   the non-colour properties as `inherit` is what the design's single-property
   override (fills only) actually implies — the rest should track whatever
   the heading is set to, not a hard-coded duplicate of today's value. */
.pa-about__accent {
  color: var(--pa-red);
  font-size: inherit;
  font-weight: inherit;
  font-family: inherit;
}

/* 1024, not 768: the measured 561/80/749 split (see this block's own note
   above) leaves the copy a ~230px column at 768, well under where a heading
   this long can wrap without breaking mid-word. Stacked — the phone
   treatment — holds until there is room for both columns. */
@media (min-width: 1024px) {
  .pa-split__inner {
    grid-template-columns: minmax(0, 561fr) minmax(0, 749fr);
    align-items: start;
    gap: 80px;
  }

  /* 2026-09-08: 1154/311, not 749/312 — #495:1582's own real dimensions per
     the unlocked API (see about.php's docblock and the 1280px block below).
     This contained (1024-1279) layout never bleeds the photo past the page
     edge, but it should still crop it to the design's own real proportions
     rather than the previous, now-stale reading's letterbox ratio. */
  .pa-split__media { order: 1; position: relative; display: block; aspect-ratio: 1154 / 311; }
  .pa-split__copy  { order: 2; }
  /* --reverse only swaps which content (copy vs media) sits in the narrow
     vs wide column via `order` — the column widths themselves (narrow
     first, wide second) don't flip. A previous pass also swapped
     grid-template-columns here, which combined with the order swap below
     put the copy into the wide column and the photo into the narrow one —
     backwards from the design (confirmed live: copy rendered 740px, photo
     580px, before this fix). about.php is --reverse's only caller today. */
  .pa-split--reverse .pa-split__media { order: 2; }
  .pa-split--reverse .pa-split__copy  { order: 1; }

  /* Out of flow so it fills its container. Left in flow its own intrinsic
     height sets the row, which stretched the section however tall the photo's
     native aspect made it — the aspect-ratio on the container above is what
     gives it something definite to fill without letting the copy decide the
     height.
     Selected via the parent because the shared `.pa-split img { height: auto }`
     reset is (0,1,1) and beats a bare `.pa-split__image`. */
  .pa-split__media .pa-split__image {
    position: absolute;
    inset: 0;
    height: 100%;
    aspect-ratio: auto;
  }

  /* 2026-09 (shape recovery): the figure-8 clip is back, this time built
     from a traced Figma render rather than the crop's own pixels — see
     about.php's docblock and design/shapes/495-1582-about-mask.svg for the
     derivation (three same-diameter circles unioned, not two, with the
     third mostly cropped off by the photo's own real right edge). Applied
     to .pa-split__image itself, not the media box: clip-path needs the
     element it's shaping, and the mask's aspect ratio (749x311, "wide
     letterbox") only matches .pa-split__image at this breakpoint and up —
     see .pa-split__image's own base 1:1 crop just below. The figure-8 clip
     stays scoped to the 1024px block below, matched to that box's own
     aspect ratio the way compliance's blob is scoped to its own. */
  .pa-about .pa-split__media { overflow: hidden; border-radius: var(--pa-radius); }
  .pa-about .pa-split__image { clip-path: url(#pa-about-mask); }
}

/* 2026-09-08 (client: "use the three ball version that is currently loading
   on mobile and load it in the middle of the column").

   A `@media (min-width: 1280px)` block used to live here that pulled the
   About photo out of the contained grid and ran it past the page's right
   edge — #495:1582 is 1154x311 at x=1171 on the 1920 frame, so the design
   genuinely does bleed it 405px off-frame, and two rounds of client feedback
   were spent getting that overhang to scale properly.

   It is gone. The mask (about.php's #pa-about-mask) is a chain of THREE
   circles, and bleeding the box off the right edge is what cut the third one
   away — on a 1920 screen the client saw two lobes and a slice, which is
   what the design's own frame shows too and which the client has now called
   badly. The contained 1024px grid above already renders all three, which is
   what phone width has been showing all along, so desktop simply uses the
   same layout: the photo sits inside its own column at the grid's own
   561fr/749fr split, at the mask's full width, no overhang and nothing
   clipped.

   This is a deliberate divergence from the artboard, asked for directly, and
   it takes `.pa-about`'s `overflow-x: hidden` with it — nothing overflows
   any more. The centring below is the second half of the same instruction. */

/* The photo's box is short (aspect 1154/311, so ~218px against a copy column
   that runs 400-500px on these pages) and `align-items: start` on the shared
   .pa-split grid parked it against the top of the row, leaving a long empty
   gap beneath it. Centred against the copy instead — "in the middle of the
   column". Scoped to .pa-about so .pa-split's other callers keep top
   alignment. */
@media (min-width: 1024px) {
  .pa-about .pa-split__media { align-self: center; }
}

/* ---------------------------------------------------------- testimonials - */

/* #570:401 "Group 14" is a Figma organisational layer that happens to also
   hold the FAQ section below this one and the tile grid/CTA band further
   down — an authoring convenience, not a shared visual scope. Nothing here
   should be read as applying past this section.

   This section's own design (index y 3660-4760) draws no heading or
   sub-line above the quote — the quote itself carries the section, unlike
   every other one on the page. th_pa_heading()'s defaults for
   pa_testimonials_heading/_sub still render (every other practice-area page
   depends on that default existing, and a screen-reader user gets a
   landmark before the carousel instead of dropping straight into a
   blockquote), so testimonials.php keeps them in the markup and adds
   .pa-vh rather than deleting them.

   #483:194 - the quote: fs40/lh54.39 (ratio 1.36), June Expt 400, navy,
   left-aligned in a 785px-wide box. Scaled with a clamp that lands on the
   design's own 40px at a 1280px viewport and a readable ~22px at 320 —
   there is no mobile comp to defer to for this one. line-height is a ratio
   rather than a second clamp, so it tracks the font-size at every width.

   #483:200 - the byline: fs17/lh23.8 (ratio 1.4), June Expt 400 (not the
   old design's bold) — small enough it does not need its own mobile step.

   #483:186/187 "fieldlink_testimonial-quotes.svg" - the giant outlined
   quotation mark. Already exported and shipped at
   assets/images/fieldlink_testimonial-quotes.svg (two Path children,
   483:189/190 — a genuine two-glyph mark, not one vector), and already used
   this same way for the homepage's own testimonials block (see
   assets/css/styles.css's `.testimonials .testimonials__wrapper:before`,
   same 590x445 asset). Applied as a CSS background, not an <img>: it sits
   behind the text and must neither steal its contrast nor be announced to a
   screen reader, and a background-image gets both for free.

   Geometry: 590x445, right/bottom edges close to the quote's own bottom-right
   corner (mark bottom 4431 vs. the byline's own bottom 4436 — 5px apart), so
   it is anchored to that corner with plain right:0/bottom:0 rather than a
   measured left/top offset. Desktop-only (1280+), the same call the
   homepage's own copy makes at its 992px cutoff (`.testimonials
   .testimonials__wrapper:before { display: none }`): under the design's own
   container width the mark reads as "behind the text"; at any narrower
   width the slide's text still runs the full column and would sit on top of
   it instead of beside it.

   #570:395/397 is a second, much larger pale-blue shape — the design's own
   `fieldlink_link-shape_down.svg` wave, the same asset already in this
   theme (assets/images/fieldlink_link-shape_down.svg) and the same one the
   homepage's own `.testimonials:before` (styles.css) uses.

   2026-09-08 (client round 2, item 2 — "the blue background still does not
   match", reported three times running, including "around the testimonial
   and FAQ the wave edges and coverage are wrong"). This used to carry a
   from-scratch recipe reverse-engineered off the homepage's own fixed-px
   rule (a `vw`-converted `-26.04vw -5.208vw` position, `200vw auto` size, a
   925px fixed-height band to stop the wash tracking the section's own
   content height) — still our own derivation, just a more elaborate one.
   The client's direction this round is explicit: stop adjusting our own
   shape and use the site's, the way `.section-list-find:before`
   (styles.css) already applies its wave — absolutely positioned, full
   size, `background-size: 120%`, `background-position: top`, `z-index:
   -1`. Replaced with exactly that recipe, position tuned per section (the
   wash enters from the left behind the quote here — crop 07 — and from the
   top-left across both FAQ columns below — crop 08) rather than reasoning
   through a second homepage rule by hand. White base stays (not restated
   below): the SVG's own fill IS #D1F2FF, so a pale-blue background-color
   underneath it would be indistinguishable from the image everywhere.

   Gated to 1280px, matching every other decorative shape on this page that
   has no comp below it — the design gives no basis for a mobile crop, and
   `inset: 0` (full box, not a fixed-height band) means the wash now tracks
   whatever height the section's real content renders at instead of needing
   a hand-measured cap, the same way `.section-list-find:before` tracks its
   own section's real height. */
.pa-testimonials {
  position: relative;
}

@media (min-width: 1280px) {
}

/* #495:1188 — fs12/lh14.4 navy "Testimonials", the section's own constant
   label. Same treatment/background as .pa-faq-eyebrow (navy on this page's
   pale-blue wash) rather than .pa-searches__eyebrow's lime (that eyebrow
   sits on the green Completed Searches panel, not this section's own
   background). */
.pa-testimonials__eyebrow {
  position: relative;
  z-index: 1;
  margin: 0 0 20px;
  font-size: var(--pa-font-eyebrow);
  font-weight: 400;
  line-height: 1.2;
  color: var(--pa-navy);
}

@media (min-width: 1280px) {
  .pa-testimonials__eyebrow { margin-bottom: 45px; }
}

.pa-testimonials__grid { display: grid; gap: 48px; }

.pa-testimonial {
  margin: 0;
  text-align: left;
  position: relative;
}

.pa-testimonial__quote {
  /* Above the quote-mark background and clear of it. */
  position: relative;
  z-index: 1;
  /* The theme italicises blockquote; none of the design's quotes are italic. */
  font-style: normal;
  font-weight: 400;
  color: var(--pa-navy);
  quotes: none;
  max-width: 785px; /* #483:194's own text box, inside the ~1380px container */
  margin: 0 0 20px;
  font-size: clamp(1.375rem, 1rem + 1.875vw, 2.5rem); /* 22px -> 40px at 1280 */
  line-height: 1.36; /* 54.39 / 40 */
}

.pa-testimonial__author {
  position: relative;
  z-index: 1;
  font-weight: 400; /* not the old design's bold — #483:200 reports 400 */
  /* The theme's global `figure figcaption` rule sets both of these directly
     on the element (italic, centered); an ancestor's text-align does not
     override a more specific rule on the element itself, so both need to be
     restated here even though .pa-testimonial already sets text-align. */
  font-style: normal;
  text-align: left;
  color: var(--pa-navy);
  margin: 0;
  font-size: 17px;
  line-height: 1.4; /* 23.8 / 17 */
}

@media (min-width: 1280px) {
  .pa-testimonial::before {
    content: '';
    position: absolute;
    right: 0;
    bottom: 0;
    z-index: 0;
    width: 590px;
    height: 445px;
    background: url('../images/fieldlink_testimonial-quotes.svg') no-repeat right bottom / contain;
    pointer-events: none;
    /* 2026-09: this used to carry `filter: brightness(0.75)`, added on the
       (once-true) assumption that the mark sits on this section's own
       pale-blue wash — same #d1f2ff as the asset's own stroke, so unfiltered
       it would be invisible against itself. The wash's own fixed-height cap
       (this file's ::before above .pa-testimonials__eyebrow) means that at
       this element's actual position — bottom:0/right:0, i.e. the far
       right edge of a ~1380px container — the wash never reaches out this
       far (confirmed by rendering: the pixels behind this mark, at every
       measured point, are plain white, not #d1f2ff). Darkening a pale-blue
       stroke against a WHITE backdrop is what read as "grey" (client-
       reported) instead of the comp's own pale blue — #d1f2ff at
       brightness(0.75) rounds to #9db6bf, confirmed as this mark's actual
       rendered colour before this fix. No filter needed: the asset's own
       stroke colour is already the design's intended pale blue against
       white. */
  }
}

/* ---------------------------------------------- testimonials carousel - */

/* The dot-capsule pagination effect (the translate-<n> classes, the sliding
   :before capsule, the curve connectors) is the site's own, unscoped, and
   already loads with styles.css on this page — it is reused as-is from there,
   nothing below duplicates it. This block only wires up the carousel that
   effect sits on top of: .pa-testimonials__slider is the Swiper container,
   initialised in assets/js/practice-area.js with the same option family as
   the homepage's own testimonials slider (assets/js/main.js's initSlider()).
   See that file for why the handler queries its own .swiper-pagination
   instead of the site's page-wide jQuery one.

   wrapperClass/slideClass in that init point Swiper at .pa-testimonials__grid
   and .pa-testimonial directly, instead of the default swiper-wrapper/
   swiper-slide. Those two default class names carry unconditional
   display:flex / width:100% rules in swiper-bundle.min.css that would apply
   the instant the stylesheet loads, whether or not the script after it ever
   runs — which would leave three of the four quotes clipped off-screen on a
   slow or failed script load. Pointing Swiper at this page's own classes
   means the carousel layout below only turns on once Swiper has actually
   run and stamped .swiper-initialized on the container; until then (and if
   the script never loads at all) .pa-testimonials__grid keeps the ordinary
   stacked layout defined above, so all four quotes stay fully readable with
   no JS. */
.pa-testimonials__slider.swiper-initialized {
  position: relative;
  overflow: hidden;
}

.pa-testimonials__slider.swiper-initialized .pa-testimonials__grid {
  display: flex;
  flex-wrap: nowrap;
  gap: 0;
}

.pa-testimonials__slider.swiper-initialized .pa-testimonial {
  flex-shrink: 0;
  width: 100%;
}

/* Pagination spacing/position (margin-top, position:relative !important) is
   already set, unscoped, by styles.css — deliberately not repeated here.
   Alignment is page-specific, though: swiper-bundle.min.css centers the
   bullet row (`.swiper-pagination{text-align:center}`) by default, and
   #483:201 sits the capsule flush left under the quote instead. */
.pa-testimonials__slider .swiper-pagination {
  text-align: left;
}

/* 2026-09-08 (client round 2, item 1): this rule used to also set
   `border-radius: 53px`, on the theory that #483:201's capsule (cornerRadius
   53 on a 164x48 box) was a deliberate departure from styles.css's own
   `.swiper-pagination{border-radius:50%}`. Client feedback: "You already
   have the code for this. No reason to screw this up" — the site's own
   mechanism has no capsule background/radius invention at all beyond what
   styles.css already draws (`.swiper-pagination{background:#fff;height:48px;
   border-radius:50%}`, individual 48x48 circular bullets, and the red
   `:before` dot sliding between translate-<n> classes). Removed so this
   slider renders with exactly the same shape styles.css already gives every
   other pagination widget on the site, per "copy the site's own code wherever
   it exists" — not a page-specific correction of it. */

/* swiper-bundle.min.css's own .swiper-pagination-bullets.swiper-pagination-
   horizontal rule sets width:100% on the pagination element. The homepage's
   testimonials slider (styles.css, scoped to .testimonials__wrapper) undoes
   that with width:auto so the pill hugs its dots instead of stretching edge
   to edge; this page has no .testimonials__wrapper ancestor, so without the
   same override here the capsule's background (.swiper-pagination{height:
   48px;border-radius:50%} in styles.css) stretched across the full slide
   width, and border-radius:50% on that wide-flat box drew it as an elongated
   oval rather than a pill around the dots. Copies the site's own fix,
   scoped to this slider instead of duplicating it in styles.css. */
.pa-testimonials__slider .swiper-pagination-bullets.swiper-pagination-horizontal,
.pa-testimonials__slider .swiper-horizontal > .swiper-pagination-bullets {
  width: auto !important;
  display: inline-block;
}

/* If Swiper's script never runs (blocked/failed load — the same case
   .pa-testimonials__slider.swiper-initialized above guards for), the two
   classes above never get added, so the width:auto override doesn't match
   and testimonials.php's empty <div class="swiper-pagination"></div> falls
   back to the plain .swiper-pagination rule in styles.css (height:48px;
   border-radius:50%, no width) with no CSS class to catch it. A block-level
   div with no explicit width fills the slide, so the same stretched-oval
   capsule from before reappears — just with no dots inside it, since Swiper
   never rendered any. Nothing needs a pill with zero bullets in it, so hide
   it outright rather than fighting the width again. */
.pa-testimonials__slider .swiper-pagination:empty {
  display: none;
}

/* 2026-09 (client-reported: "the outline is missing" on the pagination
   dots). Confirmed by rendering, not guessed: styles.css's shared capsule
   effect draws its connector between adjacent dots (the site's own
   `.swiper-pagination-bullet:not(:last-child):before/:after`) from
   `background-image: url(/wp-content/uploads/2024/01/curve-1.svg)` — a
   file living in the WP media library, not this theme's own assets/
   folder, so it does not travel with the codebase and 404s on any
   environment whose media library does not already carry that 2024-01
   upload (confirmed here: it 404s on this local dev environment outright).
   With that image missing, every bullet is a plain white 48px circle with
   no border on a white pagination pill (styles.css's own
   `.swiper-pagination-bullet { background:#fff; ... }`, no `border`) — so
   nothing distinguishes one dot from the next or from the pill itself,
   which is exactly "the outline is missing": there IS a browser default
   focus ring (blue, native) on the focused dot, because nothing here resets
   or replaces it, and a screenshot taken mid-focus reads as "a red dot
   inside a blue ring" — but that is the FOCUS state, not the resting one,
   and the task after this comment is to stop the resting state from
   depending on it to look intentional.

   The design's own comp for this widget (#483:201 "If we need pagination"
   and its children, y 4543-4591) is not a new bar-style indicator — its
   four "48x14" shapes are literally `curve-1.svg` frames again (same name,
   same 48-wide size), i.e. a captured snapshot of this exact site
   mechanism (dot circles + curve connectors + red capsule), with the
   connector's own fill already #D1F2FF — this page's own --pa-pale-blue —
   confirmed by fetching the real asset. So the fix is not a new shape, it
   is making the existing one resilient: the same asset, inlined as a data
   URI scoped to this slider only, so it renders regardless of which
   environment's media library it runs against. `do not alter the site's
   existing sliders` is why this is scoped to `.pa-testimonials__slider`
   rather than fixed at the shared, unscoped rule in styles.css — the
   homepage and success-stories sliders keep depending on the uploads file
   exactly as before. */
.pa-testimonials__slider .swiper-pagination .swiper-pagination-bullet:not(:last-child):before,
.pa-testimonials__slider .swiper-pagination .swiper-pagination-bullet:not(:last-child):after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='35'%3E%3Cpath d='M0 0 Q20 5 40 25 T80 25 T120 0' stroke='transparent' fill='%23D1F2FF'/%3E%3C/svg%3E");
}

/* A deliberate, visible focus state (required — see this file's shared
   :focus-visible outline just above .pa-crumbs__link), rather than leaving
   this slider's dots to whatever the browser's un-styled default focus
   ring happens to be. Same treatment as every other interactive element on
   this page (3px solid --pa-blue, 3px offset) instead of a one-off, so the
   resting dot (fixed above) and the focused one both read as deliberate
   rather than the focus ring being mistaken for part of the resting
   appearance. */
.pa-testimonials__slider .swiper-pagination-bullet:focus-visible {
  outline: 3px solid var(--pa-blue);
  outline-offset: 3px;
}

/* 2026-09 through 2026-09-08 (superseded, client round 2 item 1): this block
   used to first give every bullet and the capsule a navy box-shadow ring
   below 1280 (on the theory the design had no comp down there), then replace
   that with a pale-blue `background` painted straight onto the capsule below
   1280, reasoning #483:201's pagination motif is "a plain pale-blue backdrop
   behind plain white circles". Client round 2 item 1 says plainly: "You
   already have the code for this. No reason to screw this up" — the site's
   own `.swiper-pagination` (styles.css) already gives every pagination
   widget on the site a white `background`, `height:48px`, `border-radius:
   50%` at every width, with no width-gated variant. Overriding that to
   pale-blue below 1280 was this page inventing a width-specific appearance
   the site's own mechanism doesn't have. Removed outright (not just
   commented) — nothing here should keep re-deriving a "backdrop" that
   styles.css already supplies unconditionally. */

/* -------------------------------------------------------------- CTA band - */

/* #495:1597 — a pale-blue panel, 1379 wide: --pa-panel again, the same width
   the searches panel above uses. Renders twice per page (cta.php's own
   docblock explains why, including why it emits no id), so nothing here can
   assume there is only one on the page — hence :last-child below rather than
   a page-level assumption.

   #495:1598 — the heading, fs56/lh76.15, fontWeight 400 (June Expt's one
   loaded weight — see the H1 pill's own note). #495:1599-1603 — the two
   buttons, 160x84, radius 40, fs16, 24px apart, centred in a content block
   that in turn sits centred in the panel's own 324px height (70px of space
   above and below, symmetrical — flex centring below reproduces that without
   hard-coding the panel's own height, so a wrapped heading still centres).

   #495:1604-1609 — the right-hand motif, clipped to a 548-wide box flush with
   the panel's right edge and running its full height. 2026-09 (shape
   recovery): now a single traced SVG (design/shapes/495-1606-cta-motif.svg),
   not positioned circles — see that file and cta.php's own docblock for the
   derivation. Superseded readings, in order: "three rotated squares" (no
   vectorPaths in this export to rule that out from a bounding box alone),
   then "ten same-size circles in three diagonal strings" (closer, but the
   real shape's pieces actually merge into five disjoint silhouettes, not
   ten separate identical dots at a repeatable offset). Desktop-only
   (1280+): the fixed pixel numbers below are only valid once --pa-panel caps
   the container at the design's own 1379px, same as the hero photo and the
   compliance panel's own fixed-px geometry. */

.pa-cta:last-child { padding-bottom: 0; }

.pa-cta__panel {
  position: relative;
  max-width: var(--pa-panel);
  margin: 0 auto;
  background: var(--pa-pale-blue);
  border-radius: var(--pa-radius);
  overflow: hidden;
  padding: 32px 24px;
}

.pa-cta__copy {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.pa-cta__heading {
  font-size: clamp(1.5rem, 1rem + 3vw, 2.25rem);
  font-weight: 400;
  line-height: 1.2;
  color: var(--pa-navy);
  margin: 0;
}

.pa-btn--lime { background: var(--pa-lime); color: var(--pa-navy); }
.pa-btn--red  { background: var(--pa-red);  color: var(--pa-white); }

/* min-height + centred padding reproduces the 160x84/radius-40 box without a
   fixed width, so a longer label (a page override, a translation) still
   renders as a pill instead of clipping. */
.pa-cta .pa-btn {
  min-height: 56px;
  padding: 0 24px;
  border-radius: 40px;
  font-size: 14px;
  font-weight: 400;
  line-height: 1;
}

.pa-cta__motif { display: none; }

@media (min-width: 768px) {
  .pa-cta__panel { padding: 40px 32px; }

  .pa-cta__copy { max-width: 500px; }
}

@media (min-width: 1280px) {
  .pa-cta__panel {
    display: flex;
    align-items: center;
    padding: 70px 30px;
  }

  .pa-cta__copy { max-width: 700px; }

  .pa-cta__heading {
    font-size: 56px;
    line-height: 76px; /* 76.15 */
  }

  .pa-cta .pa-btn-row { gap: 24px; } /* 485 - (301 + 160) */

  .pa-cta .pa-btn {
    min-height: 84px;
    padding: 0 36px;
    font-size: 16px;
  }

  .pa-cta__motif {
    display: block;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 548px;
    overflow: hidden;
  }

  /* The recovered shape's own box is 554x733 (design/shapes/495-1606-cta-
     motif.svg) — taller than this 548-wide container because the design
     positions it centred on the panel, not flush with its top: node
     495:1606 (the motif) sits at real y=3120, but the "Mask group" that
     clips it to what's visible (495:1604, exactly 548x324 — the panel's
     own box) starts 208px lower, at real y=3328. So the motif's own local
     y=208 is what lines up with the panel's top edge, not y=0 — getting
     this wrong (an earlier version of this rule anchored the SVG's y=0 to
     the container's top) showed only the half-circle at the motif's very
     top and cropped away the two wavy chains entirely, which is why
     docs/design-refs/06-cta-band.png reads as far more "full" than a
     naive top-anchor produces. Scaled by 548/554 (this container's own
     width against the shape's native width) since the two aren't quite
     equal: 208 * (548/554) = ~206px. */
  .pa-cta__motif svg {
    display: block;
    position: absolute;
    top: -206px;
    left: 0;
    width: 548px;
    height: 725px; /* 733 * 548/554 */
  }
}

/* --------------------------------------------------------- category tiles - */

/* Hub pages only (children.php returns early on a category page). The
   standalone "Practice Areas" eyebrow was removed on 2026-10-02. The
   26px/lh34 heading remains navy, left-aligned in a 428px text box; there is no
   panel behind it, unlike the searches or CTA bands, so it sits directly on
   the page background.

   #495:1470 etc. ("Frame 92") — the four cards, 327x222 photo (top corners
   radius 30) over a 74px #638573 label bar (bottom corners radius 30,
   fs20/lh34 lime label + a white 20x20 arrow-up-right icon, 30px padding
   each side, 20px top/bottom), 24px apart, 4 across at the design's own
   1380px container width (4*327 + 3*24 = 1380). No per-tile colour
   variation in this design — the old sibling-project's dark-first-tile
   convention is gone. */

.pa-tiles-section .pa-section__title {
  text-align: left;
  max-width: 428px; /* #493:994's own text box */
  margin: 0;
  font-size: var(--pa-font-heading);
  font-weight: 400;
  line-height: 1.31; /* 34 / 26 */
  color: var(--pa-navy);
}

.pa-tiles {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 24px;
  margin-top: 32px;
}

@media (min-width: 1280px) {
  .pa-tiles { margin-top: 50px; }
}

@media (min-width: 768px) {
  .pa-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Three across, not the design's four: the hub has six categories since the
   2026-09-22 restructure, and four across left two orphaned on a second row.
   Two rows of three was the agreed layout. The photo keeps the card's own
   327/222 ratio, so the cards simply grow wider and taller. */
@media (min-width: 1280px) {
  .pa-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.pa-tile {
  display: flex;
  flex-direction: column;
  text-decoration: none;
  border-radius: var(--pa-radius);
  overflow: hidden; /* clips the image's hover scale to the card's own corners */
}

.pa-tile:hover { text-decoration: none; }

.pa-tile__media {
  position: relative;
  /* The classic padding-bottom aspect-ratio hack, not the `aspect-ratio`
     property: .pa-tile is a flex column (below), and an aspect-ratio height
     on a flex item is not "definite" early enough for an absolutely
     positioned img child's own height:100% to resolve against — it measured
     out at a circular 1500px tall instead of the intended box. A percentage
     padding is always resolved against the parent's WIDTH, a different axis
     entirely, so there is no circularity to hit. 222 / 327 is the design's
     own photo-square ratio, so a narrower phone column keeps the same shape
     instead of the design's fixed pixels. */
  height: 0;
  padding-bottom: 67.89%; /* 222 / 327 */
  overflow: hidden;
  background: var(--pa-navy); /* shows while the photo loads */
}

.pa-tile__image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* wp_get_attachment_image() prints width/height attributes, and the UA
     stylesheet derives a default aspect-ratio from those (here, the "large"
     size's 4:3ish crop) — which otherwise wins over inset:0/height:100%
     above and shrinks the image short of the box instead of filling it.
     `auto` does not reliably clear this (it measured out at a circular
     1500px tall in testing); pinning the SAME ratio .pa-tile__media itself
     uses does, because it makes every sizing path the box could take land
     on numbers that already agree with inset:0's own 100%/100%. */
  aspect-ratio: 327 / 222;
  object-fit: cover;
}

.pa-tile__body {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 20px 30px;
  background: var(--pa-green);
  /* 2026-09-08 (client item 12: "Missing rounded bottoms on 3 of 4 practice
     areas"): CSS grid stretches every `.pa-tile` (a grid item) to the
     tallest tile in its row by default — confirmed by rendering, all four
     tiles measured the same 299px overall height even though only the
     "Structured Cabling" tile's own two-line label actually needs it. A
     flex column (`.pa-tile`) with no flex-grow on its children leaves any
     such extra height as blank space AFTER the last child, so the other
     three tiles' green label bar stopped short of the card's own bottom
     edge — the outer `.pa-tile { border-radius; overflow: hidden }` still
     rounds that corner, it just rounds an empty, invisible strip below the
     visibly-square-cornered green rectangle instead of the rectangle
     itself. `flex: 1` makes this bar consume all the leftover height
     (its own `align-items: center` keeps the label vertically centred
     regardless), so its green fill always reaches the card's real bottom
     corner. */
  flex: 1;
}

.pa-tile__label {
  font-size: 20px;
  font-weight: 400;
  line-height: 1.7; /* 34 / 20 */
  color: var(--pa-lime);
}

.pa-tile__arrow {
  flex: none;
  width: 20px;
  height: 20px;
  color: var(--pa-white);
}

/* Same bug as .pa-roles__tick further down this file and .pa-services__arrow
   above — styles.css's global `body, * { color: ... }` matches this SVG's
   <path> directly, so it rendered navy instead of inheriting white. The
   design's own stroke on this arrow (#495:1467-1469 etc.) is white
   (RGB 1,1,1), not red — checked directly in the node tree — so white is
   what this restores, not a switch to red. */
.pa-tile__arrow path { color: inherit; }

/* ---------------------------------------------------------------- roles - */

/* Category pages only — 483:3 is the hub's artboard, and the hub shows the
   tile grid (further up this file) in this exact spot instead, so nothing
   here was drawn. Designed instead from the two things this page already
   does with "a repeated small item": the lime service cards (each one a
   rounded-rect block, navy heading text, an accent-coloured icon) and the
   green Completed Searches panel's own lime cards (the same fill/radius/text
   pairing, at a smaller size, tiled in a grid). A role name is smaller still
   — a label with an icon, no title/body split — so it takes that same
   fill/radius/colour language and drops to one line per card rather than
   inventing a fourth treatment.
   pa_roles_heading and pa_children_heading used to default to the identical
   string ("We can meet all of your {area} staffing needs") because this
   section and the tile grid are the same slot on the page, one or the other.
   The 2026-09-11 client review split them — "Typical {area} roles we support"
   here, "Explore our {area} practice areas" over the tiles — but the shared
   slot is what the shared treatment rests on, not the shared wording, so the
   eyebrow-over-left-aligned-heading treatment below is lifted from
   .pa-tiles-section wholesale (same class shape, same 428px column, same
   32px/50px gap to what follows) rather than keeping the old centred
   50px-heading treatment that belonged to the sibling design's different
   layout. */
.pa-roles-section .pa-section__title {
  text-align: left;
  max-width: 428px;
  margin: 0;
  font-size: var(--pa-font-heading);
  font-weight: 400;
  line-height: 1.31; /* 34 / 26 — same ratio .pa-tiles-section's own title uses */
  color: var(--pa-navy);
}

.pa-roles__eyebrow {
  margin: 0 0 20px;
  font-size: var(--pa-font-eyebrow);
  font-weight: 400;
  line-height: 1.2;
  color: var(--pa-navy);
}

@media (min-width: 1280px) {
  .pa-roles__eyebrow { margin-bottom: 45px; }
}

.pa-roles {
  display: grid;
  gap: 12px;
  margin-top: 32px;
}

@media (min-width: 1280px) {
  .pa-roles { margin-top: 50px; }
}

.pa-roles__col {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* One chip per role — the lime-card idiom at label size: --pa-radius (every
   coloured block on this page shares that one radius, a chip included, not
   a smaller one scaled down for its size) and the same lime/navy fill and
   text pairing services.php and searches.php both use. */
.pa-roles__item {
  display: flex;
  align-items: center;
  gap: 15px;
  background: var(--pa-lime);
  border-radius: var(--pa-radius);
  padding: 15px 20px;
}

/* Red, not lime-on-lime: the same role the arrow plays on a service card and
   the glyph plays on a searches card — an accent colour that reads against
   the lime fill instead of disappearing into it. */
.pa-roles__tick {
  flex: none;
  width: 26px;
  height: 26px;
  color: var(--pa-red);
}

/* styles.css ships a global, unscoped `body, * { color: ... }` — a rule that
   directly matches the <circle> itself, not just an ancestor, so it wins over
   .pa-roles__tick's own color no matter how much more specific that class
   selector is (a directly-matched rule always beats an inherited one; see
   .pa-faq__question's own note above, the same bug against the same global
   rule). Without this the tick renders the page's default ink colour instead
   of red, on every practice-area page, all the time — not a state to leave
   looking intentional. */
.pa-roles__tick circle { color: inherit; }

/* nowrap is what makes the label measurable: with it, scrollWidth is the
   width the string actually wants and clientWidth is the room it has, which
   is the ratio practice-area.js's fitRoleLabels() scales the font-size by
   (2026-09-08, client: every chip on one line, shrinking a chip's own type
   where it has to). `min-width: 0` lets the label be narrower than its
   content inside the flex row, so clientWidth reports the room available
   rather than the text's own width; without it a flex item's automatic
   minimum size is its content, clientWidth == scrollWidth, and the fitter
   would conclude every chip already fits.

   With JS off the label stays on one line and is clipped by the chip's own
   overflow rather than wrapping. That is the deliberate trade: the client
   asked for one line, and a clipped tail is visibly a rendering artefact
   where a wrapped chip just looks like an inconsistent design. */
.pa-roles__label {
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  font-size: 16px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--pa-navy);
}

/* The fitter's own escape hatch — see practice-area.js's ROLE_MIN_FONT_PX.
   Only ever set on a label that cannot hold one line at the floor size. */
.pa-roles__label--wrapped {
  overflow: visible;
  white-space: normal;
}

/* Three columns from 1280, not from 768. At 768 three equal thirds of this
   container are 209px each, which leaves a chip's label about 128px — every
   multi-word role on all four pages needs single-digit type to hold one line
   in that, and the client asked for "a single pill" to shrink, not all of
   them. 1024 is no better: 295px tracks put "Structured Cabling Project
   Manager" at the 12px floor exactly. So 768-1279 keeps the phone treatment,
   one full-width column per list, where every label fits at the stylesheet's
   own size and nothing is shrunk at all. */
@media (min-width: 1280px) {
  /* minmax(0, 1fr), not a bare 1fr. `1fr` is `minmax(auto, 1fr)`, and that
     `auto` minimum is the track's max-content size — so the column carrying
     "Structured Cabling Project Manager" grew to fit its longest chip and
     took the other two columns' width with it: measured 258/297/366 at 768
     and 365/365/409 at 1280, against a design that draws three equal thirds.
     It gets worse once the labels are `white-space: nowrap` (see
     .pa-roles__label), because max-content then means the whole string.

     A zero minimum makes the track a true equal third, and it is also what
     gives fitRoleLabels() a real ceiling to measure against — with the
     blowout in place a label's clientWidth always equalled its scrollWidth
     and the fitter concluded every chip already fitted. */
  .pa-roles { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 30px; }
}

@media (min-width: 1280px) {
  .pa-roles__item { padding: 17px 24px; }
  .pa-roles__label { font-size: 18px; }
}

/* ---------------------------------------------------- completed searches - */

/* #495:1209 — the green panel, 1379 wide: --pa-panel again, the same width
   the CTA band's panel uses further down the page.

   #495:1191/1192 — a lime eyebrow ("Completed Searches", fs12 = the eyebrow
   token) over a white 26px heading (fs26 = --pa-font-heading), 45px apart,
   40px above the card grid. Both text nodes report fontWeight 400 in the
   export (font family June Expt has one weight loaded — see the H1 pill's
   own note on that) — not the bold this block used under the old design.

   #495:1263 — the four cards (Frame 180/181/177/179), 2x2, lime fill, 30px
   radius (--pa-radius), 20px column gap / 24px row gap, ~21px of padding on
   every edge (measured against both rows independently, not assumed), 40px
   between each card's title and its story.

   Left out: #495:1529, decorative circular line-work in the panel's lower
   left. Corrected 2026-09 (rebuild-11) — it does NOT bleed 62px past the
   panel's own left edge; that number came from the mask vector's own
   (unclipped) bounding box, and what the mask actually reveals is also
   bounded by the rectangle it clips (#495:1528), which starts 4px inside the
   panel edge — see searches.php's own docblock for the full reasoning and
   the crop confirmation. It is still left out, for a narrower reason than
   before: the export carries no vectorPaths/fillGeometry for #495:1527, only
   its bounding box, so the chain-of-circles curve itself still has nothing
   to derive from. The cards use the panel's full width rather than reserving
   a gutter for it. If this needs to render, it has to come in as an exported
   asset (SVG/PNG of node 495:1527 composited against 495:1528's lime fill)
   — the API is what can produce that, not this index. */

.pa-searches__panel {
  position: relative;
  max-width: var(--pa-panel);
  margin: 0 auto;
  background: var(--pa-green);
  border-radius: var(--pa-radius);
  padding: 28px 20px;
  overflow: hidden; /* crops the motif's own left-edge bleed — see below */
}

/* 2026-09 (shape recovery): #495:1527's decorative line-work, hidden below
   1280px where the panel is too narrow to have this gutter (the two-column
   card grid uses the panel's full width there) — see searches.php's own
   docblock for the shape's derivation and this element's real position.
   472x454 native (the shape's own local box); the offset below is that
   box's real position relative to the panel's own BORDER edge (real
   x=209 vs panel x=271 => -62px; real y=2679 vs panel y=2503 => 176px),
   adjusted for the panel's own 1280px padding (30px left / 30px top) since
   position:absolute here is relative to the panel's PADDING box, not its
   border box: -62 - 30 = -92, 176 - 30 = 146. */
.pa-searches__motif { display: none; }

@media (min-width: 1280px) {
  /* 2026-09-08 (client item 9): width/height follow the new tight viewBox
     (264.19 x 419.35, see searches.php's own docblock) 1 unit = 1px, same
     convention the old 472x454 box used. left re-anchored so the shape's
     own real position (computed by walking its full ancestor transform
     chain back to the page origin: real x≈227, i.e. -44px from the panel's
     own 271px inset) lands in roughly the same visual spot the previous
     box occupied — verified by rendering, not re-measured against a second
     independent source.

     2026-09-08 (client round 2, item 3: "Yellow circles overlap the
     text" — top:108 put the shape's own top-left corner, and since this
     path's ink runs edge-to-edge in its own 419px-tall viewBox (confirmed:
     no internal margin, the path's minimum y is 0), that top value was also
     the top of the visible ink. Checked against the node geometry rather
     than nudged: #495:1192 (the heading) sits 195px below the panel's own
     top edge in the design (2898.35 - 2703.09, both in the same Figma
     coordinate space) — confirmed against this page's own live layout,
     which measures the same 195px from panel top to heading bottom. The
     heading's own `.pa-searches__intro` also carries a 24px margin-bottom
     below that. 108px put the motif's own ink starting 87px ABOVE the
     heading's bottom edge, i.e. squarely under the third line of text.
     Moved to 220px (195 + 24 + a small buffer), clearing the heading with
     room matching the comp's own gap (crop 05, docs/design-refs/
     05-searches.png — the motif's topmost stroke sits just clear of
     "roles", not overlapping it). */
  .pa-searches__motif {
    display: block;
    position: absolute;
    left: -44px;
    top: 220px;
    width: 264px;
    height: 419px;
    pointer-events: none;
  }
}

.pa-searches__intro {
  /* Belt-and-suspenders alongside the motif's own repositioning above: an
     absolutely positioned sibling with z-index:auto paints after ordinary
     in-flow content regardless of DOM order, so a positioned descendant of
     its own (z-index:1) keeps the heading on top even if a future content
     change (a longer heading, a narrower panel) shortens the gap the
     repositioning fix above assumes. Same pattern .pa-testimonials__eyebrow
     already uses against the wash behind it. */
  position: relative;
  z-index: 1;
  margin: 0 0 24px;
}

.pa-searches__eyebrow {
  margin: 0 0 12px;
  font-size: var(--pa-font-eyebrow);
  font-weight: 400;
  line-height: 1.2;
  color: var(--pa-lime);
}

.pa-searches-section .pa-section__title {
  text-align: left;
  max-width: 425px; /* #495:1192's own text box */
  margin: 0;
  font-size: var(--pa-font-heading);
  font-weight: 400;
  line-height: 1.36; /* 35.36 / 26 */
  color: var(--pa-white);
}

.pa-searches {
  display: grid;
  gap: 20px;
}

.pa-search-card {
  background: var(--pa-lime);
  color: var(--pa-navy);
  border-radius: var(--pa-radius);
  padding: 20px;
}

/* Re-derived 2026-09 (rebuild-11): #495:1252 "Frame 183" (the title row) is
   `{ display: flex; flex-direction: row; gap: 15px }` over a 20x20 red dot
   (#495:1254/1255, fill #ff363b) then the title text (#495:1253, fs18) — a
   row this pass had dropped entirely, leaving titles as plain text with no
   glyph. All four cards agree on the same dot/gap pair. */
.pa-search-card__title {
  display: flex;
  /* 2026-09-08 (client item 2: "Red dot is always aligned to top of text") —
     was `align-items: center`, which verticaly centred the dot against the
     WHOLE title block including its second line once a title wraps (e.g.
     "BICSI Technician, Crew Lead"). flex-start pins the dot to the first
     line every time, wrapped or not. */
  align-items: flex-start;
  gap: 15px;
  margin: 0 0 20px;
  font-size: 18px; /* #495:1253 — not on the type ramp, this is the only place it's used */
  font-weight: 400;
  line-height: 1.36; /* 24.48 / 18 */
  color: var(--pa-navy);
}

/* 2026-09-08: now an inline <svg> (circle + checkmark, currentColor fill —
   see searches.php's own docblock for the real geometry this replaces a
   plain-circle guess with), so this rule only sets its size/colour, the
   same pattern .pa-roles__tick uses for its own icon just below. */
.pa-search-card__dot {
  flex: none;
  width: 20px;
  height: 20px;
  color: var(--pa-red);
}

/* Same bug as .pa-roles__tick circle/.pa-tile__arrow path/.pa-services__arrow
   path elsewhere in this file: styles.css's global `body, * { color: ... }`
   matches this <circle> directly, so it painted the page's navy ink instead
   of inheriting .pa-search-card__dot's red. */
.pa-search-card__dot circle { color: inherit; }

/* The title text is its own span so the dot above can sit beside it in a
   flex row — #495:1253 is one plain text node with no run of its own, so
   this span has no design node either. Left with no rule, it was exposed
   directly to styles.css's global `body, * { font-size: 16px; color: ... }`
   (color landing on #1f3d47 via th-job-board's own `span { color }` reset,
   not even styles.css's), instead of inheriting the title's 18px navy.
   Restated as `inherit`. */
.pa-search-card__title-text {
  font-size: inherit;
  font-weight: inherit;
  font-family: inherit;
  color: inherit;
}

.pa-search-card__text {
  /* DM Sans has to be opted back into — see .pa-intro__body p. */
  font-family: 'DM Sans', sans-serif;
  margin: 0;
  font-size: var(--pa-font-small); /* fs13.3 — the token's own "card body copy" use */
  font-weight: 400;
  line-height: 1.35; /* 17.92 / 13.3 */
  color: var(--pa-navy);
}

@media (min-width: 768px) {
  .pa-searches { grid-template-columns: repeat(2, 1fr); gap: 24px 20px; }
}

@media (min-width: 1280px) {
  .pa-searches__panel { padding: 30px 25px 22px 30px; }

  .pa-searches__intro { margin-bottom: 40px; }

  .pa-searches__eyebrow { margin-bottom: 45px; }

  /* The single biggest geometry miss on the page (cold-assessment, 2026-09):
     below this breakpoint the grid is left fluid on purpose (no design frame
     to check it against), but at the design width the four cards are a
     FIXED 433px, not a share of the row. #495:1251/1257/1214/1245 (the four
     card FRAMEs) all report width:433, x=739/1192/739/1192 — a 20px column
     gap (1192-(739+433)) and a 24px row gap (3018-(2738+256)), not the 20px
     flat gap this rule already had right. Left fluid, the two columns split
     whatever the panel's own 1325px content box leaves them (~653px each —
     50% wider than drawn).
     The cluster also doesn't reach the panel's own left content edge: it
     sits flush against the RIGHT edge instead (739+433*2+20 = 1625 = the
     panel's own 1325px content box's right edge, padding included), leaving
     ~440px of green open on the left. That gap is real in the comp — it's
     where #495:1527's decorative chain-of-circles line-work sits (left out
     here, see this section's own comment above: no vectorPaths in this
     export to derive it from) — so right-aligning the fixed-width grid
     reproduces the comp's actual composition, missing only the artwork
     neither this pass nor the last one had geometry to draw. */
  .pa-searches {
    grid-template-columns: repeat(2, 433px);
    gap: 24px 20px;
    justify-content: end;
  }

  .pa-search-card { padding: 21px; }

  .pa-search-card__title { margin-bottom: 40px; }
}

/* ------------------------------------------------------------------ FAQ - */

/* 2026-09 rebuild against 483:3, index y 4700-5600 (82 nodes). Every number
   below is read straight off #494:1003-1042/#495:1406-1449 (the two "Frame
   27/28" column groups), not the old sibling-project's beige-card comp this
   replaces outright (12px cards, mint/lavender glyphs, an arch — none of it
   is in this design).

   #495:1455 "Frame 188" (eyebrow + both columns) is 1381 wide at x=270 —
   --pa-panel again (1380px, the same inset every other colour panel on this
   page uses), not the wider --pa-wide the section's own .pa-page-w sets. Kept
   as its own .pa-faq-inner rather than swapping .pa-page-w's own width, since
   .pa-page-w is shared with every other section on the page. */
.pa-faq-inner { max-width: var(--pa-panel); margin: 0 auto; }

/* #570:395 (see the testimonials section's own note above) — the same wave,
   extended to this section because the design's own wash rectangle
   (570:395) visually falls behind both.

   2026-09-08 (client round 2, item 2): same replacement as
   .pa-testimonials::before above — this used to carry its own from-scratch
   vw-derived offset (`-26.04vw -53.39vw`, `200vw auto`), reasoned as "the
   same wave, shifted down by the design's own 925px testimonials/FAQ
   split". Client direction: use the site's own `.section-list-find:before`
   recipe (styles.css) instead of a page-specific derivation —
   `background-size: 120%`, position tuned per section rather than
   vw-calculated against a rectangle in the design file. Crop 08 shows the
   wave entering from the top-left across both FAQ columns, wider than the
   testimonial crop's, hence `background-position: top left` here too but
   against this section's own (taller, two-column) box. White base for the
   same reason as .pa-testimonials — see its own comment.

   2026-09 (client item 4: "Hide the blue background on mobile", 320-768):
   confirmed still gated to min-width:1280px, matching .pa-testimonials::
   before just above and "must not swamp a phone screen" — the design gives
   no basis for a mobile crop. */
@media (min-width: 1280px) {
}

/* #495:1189 — fs12/lh14.4, the section's own small constant label (not
   th_pa_heading()'s long per-page sentence, which stays in the markup as a
   hidden <h2> — see faq.php's own docblock). Same treatment as
   .pa-searches__eyebrow, different colour: navy on this pale background
   rather than lime on searches' green panel, and its own measured gap below
   (42.6px, #495:1189's own bottom to #494:1005's top — close to but not the
   same figure searches uses, so kept separate rather than reused). */
.pa-faq-eyebrow {
  margin: 0 0 12px;
  font-size: var(--pa-font-eyebrow);
  font-weight: 400;
  line-height: 1.2;
  color: var(--pa-navy);
}

.pa-faq-cols { display: grid; gap: 30px; }

/* #494:1005/#495:1407 — fs26/lh35.36 (ratio 1.36, the same the section
   headings elsewhere use), navy, June Expt's one loaded weight. This is now
   an <h2> (see faq.php) so it needs the section-title reset undone: no
   center-align, no max-width clamp, no auto margins. */
.pa-faq-col__label {
  text-align: left;
  max-width: none;
  font-size: var(--pa-font-heading);
  font-weight: 400;
  line-height: 1.36;
  color: var(--pa-navy);
  margin: 0 0 20px;
}

/* #494:1007/#495:1409 "Frame 18/19" — the navy pill itself, --pa-radius
   (fill_224895b8 reports the same 30px corner radius every other panel on
   this page uses). The pill is the item, not the button inside it, so an
   open question and its answer read as one surface. 10px between items,
   read off the gap between #494:1006's stacked "Frame 23" children. */
.pa-faq-item {
  background: var(--pa-navy);
  border-radius: var(--pa-radius);
}

.pa-faq-item + .pa-faq-item { margin-top: 10px; }
.pa-faq-item__heading { margin: 0; }

/* #494:1008/#494:1009 "Frame 17" — question row: fs15, June Expt 400 (not
   the old comp's bold DM Sans), white on the navy pill. 30px padding on
   every side (question text starts 30px in from the pill edge on both axes,
   e.g. x=300 inside a pill at x=270) — closed height 30+24+30=84, matching
   #495:1409's own 84px "Frame 19".

   The 30px bottom pad only belongs to a *closed* row: an open row's pill is
   212px tall (#494:1007), which is 30 top + 24 question row + 20 gap + the
   answer's own height + 30 bottom — so the toggle's own bottom padding drops
   to 0 once aria-expanded is true and .pa-faq__panel supplies the rest
   (below), rather than both elements each claiming a 30px bottom edge. */
.pa-faq__toggle {
  appearance: none;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background: transparent;
  border: 0;
  border-radius: inherit;
  padding: 20px;
  font: inherit;
  font-size: 15px;
  font-weight: 400;
  line-height: 1.36; /* 20.4 / 15 */
  color: var(--pa-white);
  text-align: left;
  cursor: pointer;
}

.pa-faq__toggle[aria-expanded="true"] { padding-bottom: 0; }

/* th-job-board's app.css ships a global, unscoped `input, p, span { color:
   #1f3d47 }` — no plugin/component scoping at all, so it reaches this span
   too. A directly-matched rule always wins over an inherited one no matter
   how much more specific the ancestor's own rule is, so .pa-faq__toggle's
   own white doesn't reach here without this.

   The same mechanism also catches font-size, one layer down: styles.css's
   own global `body, * { font-size: 16px }` matches this span directly too,
   overriding the 15px it should inherit from .pa-faq__toggle — measured
   rendering the question one point larger than the design's #494:1008. Only
   the colour half of this bug had been caught before. */
.pa-faq__question {
  color: inherit;
  font-size: inherit;
  font-weight: inherit;
  font-family: inherit;
}

/* #494:1011/#495:1451 "Rectangle 11" — a 24px circle (radius 30 on a 24px
   box renders a full circle same as --pa-radius-pill does on the taller
   pills elsewhere). Re-derived 2026-09 (rebuild-11): a per-row converter dump
   of every glyph in #495:1455 shows red on exactly one node, #494:1011 — the
   one row the design draws pre-opened ("How fast can you crew a project?")
   — and lime (#d9ff1a) on all nine others, employer and job-seeker columns
   alike:

     .pa-faq-item (closed) #494:1016 -> Rectangle 11 #494:1020 { background: #d9ff1a }
     .pa-faq-item (closed) #494:1024 -> Rectangle 11 #495:1348 { background: #d9ff1a }
     .pa-faq-item (closed) #494:1032 -> Rectangle 11 #495:1353 { background: #d9ff1a }
     .pa-faq-item (closed) #494:1040 -> Rectangle 11 #495:1358 { background: #d9ff1a }
     .pa-faq-item (open)   #494:1007 -> Rectangle 11 #494:1011 { background: #ff363b }
     .pa-faq-col--seek, every row      -> Rectangle 11 #495:1451/1422/1430/1438/1446 { background: #d9ff1a }

   So the colour is the accordion's OPEN state, not the column — the previous
   reading (red = employer column, lime = job-seeker column) had every closed
   employer row wrong; only the row that starts open is red. #494:1012/
   #495:1423 "Vector" is a 2px-stroke, round-capped, 6px-long horizontal navy
   line and nothing else: every glyph in the design, open row or closed,
   employer or job-seeker, draws the same plain dash — there is no drawn "+"
   anywhere in 483:3 to copy for the collapsed state. The rotated second dash
   below (forming a "+" when collapsed, matching the design's single "−" once
   a row is open) is this pass's own addition for the affordance the static
   comp doesn't draw. */
.pa-faq__glyph {
  position: relative;
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--pa-lime);
}

.pa-faq__toggle[aria-expanded="true"] .pa-faq__glyph { background: var(--pa-red); }

.pa-faq__glyph::before,
.pa-faq__glyph::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 10px;
  height: 2px;
  border-radius: 1px;
  background: var(--pa-navy);
  transform: translate(-50%, -50%);
}

.pa-faq__glyph::after { transform: translate(-50%, -50%) rotate(90deg); }
.pa-faq__toggle[aria-expanded="true"] .pa-faq__glyph::after { display: none; }

/* #494:1014 — the answer: fs14/lh18.23 (ratio 1.3), DM Sans (body copy needs
   the explicit family — see the token block's own note on the theme's June
   Expt reset), white. 20px above it (the gap between the question row and
   the answer, #494:1008 bottom to #494:1014 top) then the pill's own 30px
   side/bottom padding — see .pa-faq__toggle's note on why the toggle itself
   contributes 0 of that bottom edge once open. */
.pa-faq__panel { padding: 20px; }

.pa-faq__answer p {
  font-family: 'DM Sans', sans-serif;
  font-size: 14px;
  line-height: 1.3;
  color: var(--pa-white);
  margin: 0 0 12px;
}

.pa-faq__answer p:last-child { margin-bottom: 0; }

@media (min-width: 768px) {
  /* start, not stretch: the design's two columns have different numbers of
     questions and do not run to a matched height. */
  .pa-faq-cols { grid-template-columns: repeat(2, 1fr); align-items: start; }
}

@media (min-width: 1280px) {
  .pa-faq-eyebrow { margin-bottom: 43px; }

  /* The design's own 30px side padding (e.g. question text at x=300 inside a
     pill at x=270) reads as cramped on a phone or tablet, where
     .pa-faq-item's width is much narrower than the design's 679px column —
     20px carries those layouts instead, stepping up to the measured 30px at
     the width the design itself is drawn at.
     .pa-faq__toggle[aria-expanded="true"]'s padding-bottom:0 (above) still
     wins here without repeating it: an attribute selector outranks this
     plain-class rule's specificity regardless of source order. */
  .pa-faq__toggle { padding: 30px; }
  .pa-faq__panel { padding: 20px 30px 30px; }
}

/* ----------------------------------------------------------------- jobs - */

.pa-jobs__head { display: grid; gap: 16px; margin-bottom: 24px; }
.pa-jobs__list { list-style: none; margin: 0; padding: 0; }

.pa-jobs__row {
  display: grid;
  gap: 8px;
  padding: 20px 0;
  border-bottom: 1px solid var(--pa-blue);
}

.pa-jobs__title {
  font-size: 18px;
  font-weight: 700;
  line-height: 26px;
  color: var(--pa-blue);
  text-decoration: none;
}

.pa-jobs__location { font-size: 14px; font-weight: 300; color: var(--pa-blue); }

.pa-jobs__apply {
  justify-self: start;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: -0.24px;
  color: var(--pa-orange);
  text-decoration: none;
}

.pa-jobs__all { justify-self: start; }

@media (min-width: 768px) {
  .pa-jobs__head { grid-template-columns: 1fr auto; align-items: center; }
  .pa-jobs__all { justify-self: end; }
  .pa-jobs__row { grid-template-columns: 1fr 180px 120px; align-items: center; gap: 24px; }
  .pa-jobs__apply { justify-self: end; }
}

/* ---------------------------------------------------------------- hover - */

/*
 * The design specifies no hover states — no component variants, no prototype
 * interactions — so these follow the convention the theme already uses:
 * links go orange, buttons invert to the other brand colour.
 *
 * All of it sits behind `hover: hover` so a touch device never latches a
 * hover state after a tap, and nothing here moves layout: only colour,
 * transform and shadow, so hovering a tile cannot reflow the grid.
 *
 * Buttons swap colour rather than fading opacity. A fade lowers contrast
 * exactly when the user is about to act, and every swap below lands on a pair
 * that passes AA:
 *   white on blue    11.56:1
 *   blue on orange     5.47:1  (--pa-orange is aliased to --pa-red, #ff363b —
 *                               navy #00003d on red, recomputed 2026-09)
 *   blue on white    11.56:1
 */

@media (hover: hover) and (pointer: fine) {

  /* Buttons ---------------------------------------------------------- */
  .pa-btn--orange:hover,
  .pa-btn--orange:focus-visible {
    background: var(--pa-blue);
    color: #fff;
  }

  /* Not white-on-orange, which is 3.59:1 — below the 4.5:1 body-text
     threshold. Blue (navy) on orange (red) is 5.47:1. */
  .pa-btn--blue:hover,
  .pa-btn--blue:focus-visible {
    background: var(--pa-orange);
    color: var(--pa-blue);
  }

  /* CTA band's own pair — navy on lime/red both pass AA (14.5:1 and 6.9:1). */
  .pa-btn--lime:hover,
  .pa-btn--lime:focus-visible {
    background: var(--pa-navy);
    color: var(--pa-white);
  }

  .pa-btn--red:hover,
  .pa-btn--red:focus-visible {
    background: var(--pa-navy);
    color: var(--pa-lime);
  }

  .pa-btn--white:hover,
  .pa-btn--white:focus-visible {
    background: var(--pa-blue);
    color: #fff;
  }

  .pa-btn:active { transform: translateY(1px); }

  /* Category tiles --------------------------------------------------- */
  /* The whole tile is one link, so the whole tile responds: the photo
     pushes in slightly and the arrow travels the way it points. */
  .pa-tile__image {
    transition: transform 0.35s cubic-bezier(0.2, 0.6, 0.2, 1);
  }

  .pa-tile:hover .pa-tile__image,
  .pa-tile:focus-visible .pa-tile__image {
    transform: scale(1.05);
  }

  .pa-tile__arrow { transition: transform 0.25s ease; }
  .pa-tile:hover .pa-tile__arrow,
  .pa-tile:focus-visible .pa-tile__arrow {
    /* The icon already points up-right; move it that way. */
    transform: translate(3px, -3px);
  }

  /* FAQ -------------------------------------------------------------- */
  /* 2026-09: the sibling project's cream item-tint and orange glyph-fill
     belonged to that design's white card; this design's item is a solid
     navy pill (see the rebuilt rules above), so on hover the glyph itself
     inverts — white circle, navy dash — rather than reusing colours that no
     longer read against the new background. */
  .pa-faq__glyph,
  .pa-faq__glyph::before,
  .pa-faq__glyph::after { transition: background-color 0.15s ease; }
  .pa-faq__toggle:hover .pa-faq__glyph { background: var(--pa-white); }
  .pa-faq__toggle:hover .pa-faq__glyph::before,
  .pa-faq__toggle:hover .pa-faq__glyph::after { background: var(--pa-navy); }

  /* Service cards ---------------------------------------------------- */
  /* The arrow travels the way it points, and the label picks up the
     underline it does not carry at rest. */
  .pa-services__arrow { transition: transform 0.25s ease; }
  .pa-services__link:hover .pa-services__arrow,
  .pa-services__link:focus-visible .pa-services__arrow {
    transform: translateX(4px);
  }

  .pa-services__link:hover .pa-services__link-label {
    text-decoration: underline;
    text-underline-offset: 4px;
  }

  /* Body-copy links --------------------------------------------------- */
  /* .pa-extra__body a and .pa-compliance__text a were missing from this list
     entirely (2026-09, invented-elements-sweep follow-up) — the other four
     body-copy link selectors already had this hover, so on hover these two
     just sat there with no colour change at all: :focus-visible already
     covered them (line ~370 above), but a mouse user got no affordance,
     and .pa-compliance__text a sits white-on-navy, where a static underline
     alone is a weaker signal than everywhere else on this list. */
  .pa-intro__body a:hover,
  .pa-split__text a:hover,
  .pa-services__body a:hover,
  .pa-partner__body a:hover,
  .pa-extra__body a:hover,
  .pa-compliance__text a:hover {
    color: var(--pa-orange);
    text-decoration-thickness: 2px;
  }

  /* Show more -------------------------------------------------------- */
  .pa-showmore { transition: color 0.15s ease; }
  .pa-showmore:hover { color: var(--pa-orange); text-decoration-thickness: 2px; }

  /* Jobs ------------------------------------------------------------- */
  .pa-jobs__title { transition: color 0.15s ease; }
  .pa-jobs__title:hover { color: var(--pa-orange); text-decoration: underline; }
  .pa-jobs__apply { transition: color 0.15s ease; }
  .pa-jobs__apply:hover { color: var(--pa-blue); text-decoration: underline; }
  .pa-jobs__row { transition: background-color 0.15s ease; }
  .pa-jobs__row:hover { background: rgba(31, 61, 71, 0.03); }
}

/* ------------------------------------------------------- reduced motion - */

@media (prefers-reduced-motion: reduce) {
  /* Colour still changes — that is the affordance — but nothing moves. */
  .pa-btn,
  .pa-tile__image,
  .pa-tile__arrow,
  .pa-faq__toggle,
  .pa-faq__glyph,
  .pa-showmore,
  .pa-jobs__title,
  .pa-jobs__apply,
  .pa-jobs__row,
  .pa-services__arrow,
  .pa-intro__body a,
  .pa-split__text a,
  .pa-services__body a,
  .pa-partner__body a,
  .pa-extra__body a,
  .pa-compliance__text a {
    transition: none;
  }

  .pa-tile:hover .pa-tile__image,
  .pa-tile:hover .pa-tile__arrow,
  .pa-services__link:hover .pa-services__arrow,
  .pa-btn:active {
    transform: none;
  }
}

/* ------------------------------------------------------ partner handoff - */

/* Digital Infrastructure only. The section is the page, so it is centred and
   set in the intro's measure rather than the full 1170 — 958px is the same
   column the intro uses, and it keeps the two paragraphs at a readable line
   length instead of running them edge to edge.

   Type sizes match .pa-intro__body deliberately. This is the page's body
   copy; there is no other. */

.pa-partner__body p,
.pa-partner__lead {
  font-size: clamp(1rem, 0.9rem + 0.55vw, 1.5rem);
  line-height: 1.46;
  color: var(--pa-blue);
  margin: 0 0 20px;
}

.pa-partner__lead {
  margin: 32px 0 0;
  text-align: center;
}

.pa-partner__body p:last-of-type { margin-bottom: 0; }

/* The paragraph under the mark. It needs the mark's own bottom margin, which
   the logo link does not carry — the link's 12px padding is a hit target, not
   spacing. */
.pa-partner__body--after { margin-top: 24px; }

/* The logo is the page's only call to action, so it is given the room a
   button would get. 44px is the minimum target; the mark's own height at
   these widths clears it, and the padding guarantees it if the client ever
   swaps in a squatter file. */
.pa-partner__link {
  display: block;
  width: fit-content;
  margin: 24px auto 0;
  padding: 12px;
  min-height: 44px;
  border-radius: 4px;
  transition: opacity 0.2s ease;
}

.pa-partner__link:hover { opacity: 0.75; }

.pa-partner__logo {
  display: block;
  width: 240px;
  max-width: 100%;
  height: auto;
}

@media (min-width: 768px) {
  .pa-partner__logo { width: 300px; }
}

/* The labelled button under the mark. The mark says which brand; this says
   what happens when you click it. Same destination, so the two read as one
   call to action rather than a choice. */
.pa-partner__cta {
  margin: 20px 0 0;
  text-align: center;
}

@media (prefers-reduced-motion: reduce) {
  .pa-partner__link { transition: none; }
}

/* -------------------------------------------------------- visually hidden - */

/* The theme declares .screen-reader-text with an empty rule block, so anything
   using it stays on screen. This is the working one. */
.pa-vh {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---------------------------------------------------------------- extra - */

/* A prose block under a heading of its own, between the services and
   Compliance. It borrows the intro's type rather than inventing any: the
   client asked for prose rather than a designed component, and body copy that
   set itself apart from the body copy above it would read as the component he
   did not want. The heading is left-aligned because it is a section of the
   page's argument rather than a band title over centred content. */
.pa-extra .pa-section__title {
  text-align: left;
  max-width: none;
  margin: 0 0 24px;
  font-size: clamp(1.5rem, 1.05rem + 1.6vw, 2.25rem);
}

.pa-extra__body p {
  font-size: clamp(1rem, 0.9rem + 0.55vw, 1.5rem);
  line-height: 1.46;
  color: var(--pa-blue);
  margin: 0 0 20px;
}

.pa-extra__body p:last-of-type { margin-bottom: 0; }

/* --------------------------------------------------- credential card - */

/* Directly under the heading: the heading asks why you should trust Equiliem
   with these roles and this answers it, before the body copy elaborates. It
   used to sit after the copy, where it had nothing to attach to and read as a
   stray mark at the bottom of a long column — a rule above it grouped it no
   better, it only drew a line around the problem.

   The corner-cut is the services cards' shape (0 20px 20px 20px), so the card
   reads as part of this design rather than a new object introduced for one
   credential. */
.pa-credential {
  display: flex;
  align-items: center;
  gap: 18px;
  background: #fff;
  border-radius: 0 20px 20px 20px;
  padding: 16px 22px 16px 18px;
  align-self: start;
}

.pa-credential__mark {
  display: block;
  width: 64px;
  height: auto;
  flex: none;
}

.pa-credential__label {
  margin: 0;
  font-size: 15px;
  line-height: 20px;
  color: var(--pa-navy); /* cold-assessment, 2026-09: this is the "compliance"
                             instance of the four-section --pa-ink mismatch —
                             the credential card's own text, not
                             .pa-compliance__text (which is white-on-navy and
                             was already correct). Measured fill is #00003d. */
}

/* Neither the bold title run nor the dimmed detail run has a design node of
   its own — the credential label is one text node with two style runs
   (weight and, further down the crop, opacity), and each run becomes an
   element in markup with nothing to map it to. Both <strong> and <span> are
   matched directly by a global reset — styles.css's `body, * { font-size:
   16px; color: ... }` for <strong>, and separately th-job-board's own
   `input, p, span { color: #1f3d47 }` for <span> — which wins over
   inheriting .pa-credential__label's own 15px/navy no matter which element
   is more specific in the abstract. font-size only matters below 992px
   (.pa-credential__label is 16px from there up, matching the reset by
   coincidence); color is wrong at every width. */
.pa-credential__label strong {
  display: block;
  font-weight: 600;
  font-size: inherit;
  font-family: inherit;
  color: inherit;
}
.pa-credential__label span {
  opacity: 0.72;
  font-size: inherit;
  font-weight: inherit;
  font-family: inherit;
  color: inherit;
}

@media (min-width: 992px) {
  .pa-credential__mark { width: 72px; }
  .pa-credential__label { font-size: 16px; line-height: 22px; }
}

/* ------------------------------------------------------------------ team - */

/* 40/60 rather than the 32/50 every other section's heading takes. Circular
   portraits have no bounding box, so the same gap reads tighter here than it
   does under a heading sitting above a card or a block of text. */
.pa-team-section .pa-section__title { margin-bottom: 40px; }

@media (min-width: 1280px) {
  .pa-team-section .pa-section__title { margin-bottom: 60px; }
}

/* "Meet the {area} staffing team". Approved 2026-08-25.

   The rows are elements, not wrapping. At most four to a row and the rows
   balanced against each other — 5 is 3+2, 7 is 4+3 — which wrapping cannot
   produce: it fills each row to capacity and makes 5 into 4+1, leaving one
   portrait alone under a row of four. th_pa_team_rows() decides the split and
   the template emits a .pa-team__row for each.

   Below 1024 those rows go display:contents and their people flow back into
   one wrapping list, so a phone gets an even two-up and a tablet a three-up
   rather than a desktop split crushed into half the width. */

.pa-team {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: center;
  gap: 34px 24px;
}

.pa-team__row { display: contents; }

.pa-team__m {
  flex: 0 0 calc(50% - 12px);
  max-width: 200px;
  text-align: center;
}

/* The white ring, then a hairline of the page's blue at 14%. Two shadows
   rather than a border: a border would sit inside the circle and eat 5px of
   the photograph. */
.pa-team__ring {
  width: 118px;
  height: 118px;
  border-radius: 50%;
  overflow: hidden;
  margin: 0 auto;
  background: #fff;
  box-shadow: 0 0 0 4px #fff, 0 0 0 5px rgba(31, 61, 71, 0.14);
}

.pa-team__photo {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.pa-team__name {
  font-size: 17px;
  font-weight: 700;
  line-height: 1.25;
  color: var(--pa-blue);
  margin: 18px 0 0;
  text-wrap: balance;
}

.pa-team__title {
  font-size: 14px;
  font-weight: 400;
  line-height: 1.35;
  color: rgba(31, 61, 71, 0.72);
  margin: 4px 0 0;
  text-wrap: balance;
}

@media (min-width: 600px) {
  .pa-team { gap: 34px 40px; }
  .pa-team__m { flex: 0 0 calc(33.333% - 27px); }
}

@media (min-width: 1024px) {
  /* align-items, not justify-content: the wrapper is a column at this width,
     so it is align-items that centres each row across the page. */
  .pa-team {
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: center;
    gap: 40px;
  }

  .pa-team__row { display: flex; justify-content: center; gap: 40px; }
  .pa-team__m { flex: 0 0 200px; }
}

/* ---------------------------------------------------------------------------
   "Related Practice Areas" — the tile strip at the foot of a blog post.

   The tiles and their grid are the hub pages', untouched. The only thing that
   needed solving was width. A blog post's body column is 618px, and three tiles
   across that would be 196px each — the tile is drawn at ~370 and splits
   `216px body + 1fr media`, so at 196 the body eats everything and the
   photograph disappears.

   The strip therefore spans the whole article area rather than the text column.
   The theme wraps the post and its sidebar in .inner-article__content-wrapper:
   max-width 1150px, padding 40px, so its content box is 1070px, and the post
   body already begins at that box's left edge. Widening the section to the box
   width — and no repositioning, because the left edge is already right — puts
   the strip across post and sidebar together.

   Expressed against the wrapper's own numbers rather than the sidebar's, so a
   sidebar that changes width does not move this. It does depend on that
   wrapper staying 1150/40; if the blog layout is ever reworked, this is the
   line to revisit. `main.blog-article-page` carries overflow-x: hidden, which
   is the backstop if it is ever wrong.

   Two earlier attempts are worth not repeating. Stacking the tiles one per row
   fixed the starved photograph by abandoning the three-column design. A
   viewport full-bleed (`margin-inline: calc(50% - 50vw)`) assumes the parent is
   centred on the page; this one is not — the article sits left of a sidebar —
   so the strip slid 234px off the left edge and was clipped.
   --------------------------------------------------------------------------- */

.pa-related {
  margin: 48px 0 8px;
  padding-top: 32px;
  border-top: 1px solid #d8d8d8;
  box-sizing: border-box;
}

/* Only widen where there is something to widen into. The sidebar sits beside
   the post from 1024 up; below that the layout is a single column, the post
   body is already the full content width, and widening would leave the strip
   ending 25px short of the text above it. 1024 is also where .pa-tiles goes to
   three columns, so the two changes arrive together. */
@media (min-width: 1024px) {
  .pa-related {
    /* min() so this still holds between 1024 and the wrapper's 1150 max-width,
       where the wrapper is simply as wide as the viewport allows. */
    width: calc(min(1150px, 100vw) - 80px);
    max-width: calc(100vw - 40px);
  }
}

.pa-related__title {
  font-size: 24px;
  line-height: 1.25;
  margin: 0 0 20px;
}

/* The blog's article styles set their own colour on descendants, which turned
   the tile labels navy — invisible on the dark first tile, and readable on the
   orange ones only by accident. Restated at a specificity the article cannot
   beat. */
.pa-related .pa-tile .pa-tile__label { color: #fff; }

/* Steve's October copy introduces hero actions and descriptive gateway cards.
   These extend the existing brand components; the hub's changed order is
   deliberate and the specialty pages keep their prior section order. */
.pa-hero__description { max-width: 900px; margin-top: 30px; }
.pa-hero__description p { font-size: 22px; line-height: 1.6; margin: 0; }
.pa-hero__actions { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 24px; }
.pa-hero__actions .pa-btn { font-size: 18px; line-height: 1.4; min-height: 49px; }
.pa-intro > .pa-page-w > .pa-section__title { margin-bottom: 30px; }
.pa-services__after { margin-top: 30px; }
@media (min-width: 1280px) {
  /* Follow the cards' right-aligned row (two 444px cards and a 24px gap). */
  .pa-services__after {
    grid-column: 2;
    justify-self: end;
    width: 100%;
    max-width: 912px;
    margin-top: 5px; /* Together with the layout's 25px row gap: 30px. */
  }
}
.pa-services__after p, .pa-tiles__intro p { font-size: 18px; line-height: 1.7; }
.pa-tiles__intro { max-width: 900px; margin-bottom: 30px; }
.pa-tile__body--described { flex-direction: column; align-items: flex-start; justify-content: flex-start; }
.pa-tile__body--described .pa-tile__label { font-size: 22px; font-weight: 700; }
.pa-tile__description { font-size: 18px; line-height: 1.6; color: var(--pa-white); }
.pa-tile__cta { font-size: 18px; line-height: 1.5; color: var(--pa-white); margin-top: auto; padding-top: 8px; }
.pa-tile__body--described .pa-tile__arrow { align-self: flex-end; }
@media (max-width: 767px) {
  .pa-hero__description p { font-size: 20px; }
  .pa-tile__body--described { padding: 24px; }
}

/* Keep practice-area body copy and controls at Zack's 18px readable floor.
   The inherited Figma sizes ran as low as 12px; this intentionally takes
   precedence over those older values while leaving larger headings alone. */
.pa-intro__body p { font-size: clamp(18px, calc(14.4px + 0.55vw), 24px); }
.pa-services__text,
.pa-services__link-label,
.pa-compliance__text p,
.pa-split__text p,
.pa-searches__eyebrow,
.pa-search-card__text,
.pa-testimonials__eyebrow,
.pa-testimonial__author,
.pa-faq-eyebrow,
.pa-faq__toggle,
.pa-faq__question,
.pa-faq__answer p,
.pa-showmore,
.pa-btn,
.pa-cta .pa-btn { font-size: 18px; }

/* ------------------------------------------- Steve's 2026-10-08 round - */

/* Success stories run to two paragraphs and a "Key impact" line, where the
   old searches were one paragraph. */
.pa-search-card__text + .pa-search-card__text { margin-top: 14px; }
.pa-search-card__impact strong { font-family: inherit; font-weight: 700; color: inherit; font-size: inherit; }

/* One story (Electronic Security) spans both columns instead of leaving the
   right half of the grid empty. At 1280+ the columns are a fixed 433px, so the
   lone card is their combined 886px, right-aligned like the pair it replaces. */
@media (min-width: 768px) {
  .pa-searches--single .pa-search-card { grid-column: 1 / -1; }
}

/* Environments and project types, below the role chips: the same chips under
   a small heading per list, laid out on the roles' own three-column grid. */
.pa-settings { display: grid; gap: 32px; margin-top: 40px; }
.pa-settings__title {
  margin: 0 0 16px;
  font-size: 22px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--pa-navy);
}
.pa-settings__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 12px;
}
@media (min-width: 1280px) {
  .pa-settings { margin-top: 50px; gap: 40px; }
  .pa-settings__list { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px 30px; }
}

/* "Specialized expertise backed by Equiliem" carries the Equiliem logo,
   centred under the photo (Steve, 2026-10-08, his screenshot's arrow). On the
   phone layout it follows the photo; from 1024 the copy spans two rows and the
   logo takes the second row of the photo's column. */
.pa-about__logo { order: 3; justify-self: center; display: block; width: 180px; max-width: 100%; height: auto; }
@media (min-width: 1024px) {
  .pa-about .pa-split__inner { row-gap: 24px; }
  .pa-about .pa-split__copy  { grid-column: 1; grid-row: 1 / span 2; }
  .pa-about .pa-split__media { grid-column: 2; grid-row: 1; }
  .pa-about .pa-about__logo  { grid-column: 2; grid-row: 2; align-self: start; }
}
