/* Kit 1 — The Workbook. Tokens are implementation-ready values from
   "Paperclip Law - Brand Kits.html" (design tokens appendix) — do not
   invent new values here, pull any additions from that doc. */

:root {
  /* Section air, one value for every room (Chad picked option B, 2026-10-05,
     after comparing with the new Halo Concepts site): 160px at 1920 (was
     116), 80px on phones (was 64). The homepage team and close bands used
     to run tighter (72 / 88px), which made the middle of the page read
     packed; they share this rhythm now. */
  --pl-section-air: clamp(5rem, 8.5vw, 10rem);
  --pl-primary: #0E6B80;   /* petrol teal — headers, buttons */
  --pl-logo: #00324E;      /* confirmed logo ink — sampled from plogo1 itself */
  --pl-accent: #EE7A70;    /* coral — decorative fills, rules, borders */
  /* The brand coral only reaches 2.74:1 on white, so it fails WCAG AA on every
     eyebrow, role and link it was being used for. This is the same coral
     darkened to clear 4.5:1 (4.90:1 on white, 4.55:1 on the cream card fill);
     use it for anything that is read, keep --pl-accent for anything decorative.
     Nothing coral clears AA on the aqua band — use --pl-logo there. */
  --pl-accent-text: #C64438;
  --pl-butter: #FFD34D;    /* section bars, highlights */
  --pl-aqua: #BFDDDE;      /* card fills, banners */
  --pl-peach: #F6DBCA;     /* card fills, callouts */
  --pl-bg: #FFFFFF;        /* white ground — Elizabeth's 07-22 call, was cream */
  --pl-card: #FDFBF7;      /* the old cream lives on as the card fill on white */
  --pl-ink: #1a1a1a;
  --pl-ink-soft: #4a4a4a;

  /* Direction C, promoted from the homepage-only trial to the base.
     Prata is retired: it was only ever the interior pages' heading face,
     which is what made the homepage look like a different site. */
  /* Direction 2 migration, stage 1 (2026-09-20): titles move to Bricolage
     Grotesque at the token, not by listing selectors - every h2/h3 already
     reading var(--pl-font-display) picks it up here. Montserrat stays as the
     fallback rather than sans-serif, so anything mid-load still renders in
     the closest match instead of the OS default. */
  --pl-font-display: 'Bricolage Grotesque', 'Montserrat', sans-serif;
  --pl-font-body: 'Nunito Sans', sans-serif;

  --pl-radius-card: 12px;
  --pl-radius-btn: 8px;
  --pl-shadow: 0 1px 2px rgba(26, 26, 26, 0.04), 0 4px 16px rgba(26, 26, 26, 0.06);

  /* Content shell. Raised 1120 -> 1280 -> 1400 -> 1680 over the build. Safe to
     go this wide because prose line length is capped separately (70ch in
     sections, 62ch in cards, 760px in article.page), so a wider shell buys
     layout room without producing unreadable line lengths. */
  --pl-max-width: 1680px;
  --pl-gutter: clamp(1.25rem, 4vw, 3rem);
}

* { box-sizing: border-box; }

/* scroll-padding keeps in-page anchor targets (#services, #team) clear of the
   sticky header, which would otherwise land on top of the section heading. */
html { scroll-behavior: smooth; scroll-padding-top: 6.5rem; }

body {
  margin: 0;
  font-family: var(--pl-font-body);
  font-size: 16px;
  line-height: 1.6;
  background: var(--pl-bg);
  color: var(--pl-ink);
}

img { max-width: 100%; display: block; }

h1, h2, h3, h4, h5, h6 {
  font-family: var(--pl-font-display);
  color: var(--pl-logo);
  font-weight: 600;
  letter-spacing: -0.5px;
  line-height: 1.25;
  margin: 0 0 0.6em;
}
h3, h4, h5, h6 { letter-spacing: -0.2px; }
/* Instrument Serif is the sitewide h1 face (Chad, 2026-09-20): the homepage and
   the practice heroes moved to it with Direction 2, and the inner pages follow
   so the site has ONE serif. It replaces Playfair Display (sitewide since
   2026-08-04). It ships in weight 400 only and runs narrower and lighter than
   Playfair did, so the size steps up about a tenth to hold the same presence. */
h1 {
  font-family: 'Instrument Serif', Georgia, serif;
  font-weight: 400;
  letter-spacing: -0.01em;
  line-height: 1.08;
  font-size: clamp(2.6rem, 5.4vw, 4.4rem);
}
h2 { font-size: clamp(1.8rem, 3.4vw, 2.6rem); }
h3 { font-size: 1.35rem; }
h4, h5, h6 { font-size: 1.05rem; }

p { margin: 0 0 1em; color: var(--pl-ink-soft); }

a { color: var(--pl-accent-text); }

ul, ol {
  margin: 0 0 1.25em;
  padding-left: 1.25em;
  color: var(--pl-ink-soft);
}
li { margin-bottom: 0.4em; }
li > ul, li > ol { margin-top: 0.4em; margin-bottom: 0; }

blockquote {
  margin: 1.5em 0;
  padding: 0.25em 1.25em;
  border-left: 3px solid var(--pl-accent);
  color: var(--pl-ink-soft);
  font-style: italic;
}

table {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 1.5em;
}
th, td {
  text-align: left;
  padding: 0.6em 0.8em;
  border-bottom: 1px solid var(--pl-aqua);
}
th { font-family: var(--pl-font-body); color: var(--pl-primary); }

.pl-label {
  font-family: var(--pl-font-display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 2px;
  text-transform: uppercase;
}

/* Lede — the bold subhead line landing pages carry under the H1
   (was an h4 in the Elementor source, e.g. "Your Source For Estate
   Planning In Vancouver"). Reused across every /lp/ page rebuild. */
.lede {
  font-family: var(--pl-font-body);
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--pl-logo);
  max-width: 46ch;
}

.pl-wrap {
  max-width: var(--pl-max-width);
  margin: 0 auto;
  padding: 0 var(--pl-gutter);
}

/* Buttons */
.pl-btn {
  display: inline-block;
  font-family: var(--pl-font-body);
  font-weight: 700;
  font-size: 0.9rem;
  padding: 0.8rem 1.7rem;
  /* Pill, to match the header CTA. Set on .pl-btn rather than on
     --pl-radius-btn because that token is also used by things that are not
     buttons and should stay at 8px. */
  border-radius: 999px;
  text-decoration: none;
  border: 2px solid var(--pl-logo);
  cursor: pointer;
  transition: transform 200ms ease, box-shadow 200ms ease;
}
.pl-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 18px rgba(1, 75, 108, 0.22);
}
.pl-btn--primary { background: var(--pl-logo); color: #fff; }
.pl-btn--outline { background: transparent; color: var(--pl-logo); }

/* Tags / pills */
.pl-tag {
  display: inline-block;
  font-family: var(--pl-font-body);
  font-weight: 700;
  font-size: 0.7rem;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  padding: 0.4rem 0.9rem;
  border-radius: 20px;
}
/* Aqua surfaces are light enough that neither the petrol teal (4.26:1) nor even
   the darkened coral (3.41:1) clears AA on them. Anything set on aqua takes the
   logo ink instead: the aqua pills, the homepage's closing band, and the inset
   CTA card the interior pages use. */
.pl-tag--aqua { background: var(--pl-aqua); color: var(--pl-logo); }
.pl-tag--peach { background: var(--pl-peach); color: #8a4a35; }
.pl-tag--butter { background: var(--pl-butter); color: #5c430a; }

/* Text link — quiet coral, underline only on hover (the old permanent
   2px border-bottom bar read as a clunky double underline) */
.pl-link {
  font-family: var(--pl-font-body);
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--pl-accent-text);
  text-decoration: none;
}
.pl-link:hover {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}

/* Cards — cream fill so they read as warm figures on the white ground
   (white-on-white was the contrast failure fixed once already on 07-16;
   the white-page palette makes the tinted fill the durable fix). */
.pl-card {
  background: var(--pl-card);
  border: 1px solid var(--pl-aqua);
  border-radius: var(--pl-radius-card);
  padding: var(--pl-gutter);
  box-shadow: var(--pl-shadow);
}

/* Header / nav */
/* Sticky so the "Let's Chat" CTA travels with the reader on the single-scroll
   homepage. Full-bleed bar, content still held to the grid by the inner. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--pl-bg);
  border-bottom: 1px solid var(--pl-aqua);
}
/* Three zones. 1fr auto 1fr centres the nav on the PAGE rather than in
   whatever space the logo and the actions happen to leave over, so the
   centring holds as either side cluster changes width. The old flex bar put
   the phone at x=655 — the dead middle — with 489px of nothing beside it. */
.site-header__inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1rem;
  /* 80, not the 72 this bar was first built at. Restoring the lockup to its
     proper 46px left only 13px clear above and below it, so the logo filled
     64% of the bar and read as cramped. At 80 it sits at 57% with 17px clear,
     and the bar is still 7px shorter than the one it replaced. */
  height: 80px;
  padding: 0 var(--pl-gutter);
  max-width: var(--pl-max-width);
  margin: 0 auto;
}
.site-header__logo { display: block; justify-self: start; }
/* 46px, not the 40px the first pass at this bar used. At 40 the lockup lost
   noticeable weight against the rest of the header, and the wordmark under the
   mark is small enough that the last few pixels of height are the difference
   between it reading as type and reading as a smudge. */
.site-header__logo img {
  display: block;
  height: 46px;
  width: auto;
}

/* display:none on desktop keeps it out of the tab order, where the drawer it
   controls does not exist. Under 900px it becomes visually hidden but still
   focusable — as display:none it was unreachable by keyboard entirely, which
   made the mobile menu openable by pointer only. */
.nav-toggle-checkbox { display: none; }
/* 44px of touch target around a 24px mark. The bars carry an explicit width
   now rather than filling the label, so the box can grow without them. */
.nav-toggle-label {
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  margin-left: auto;
  margin-right: -0.6rem;
  cursor: pointer;
}
.nav-toggle-label span {
  display: block;
  width: 24px;
  height: 2px;
  background: var(--pl-primary);
}
/* align-items:center is load-bearing. Flex defaults to stretch, so the plain
   links grew to the height of the padded CTA and their text sat at the top of
   that box, 8px above the pill's and the phone's optical centre. */
.site-nav {
  display: flex;
  align-items: center;
  gap: 1.9rem;
  justify-self: center;
}
/* Every top-level target is 44px tall by construction rather than by padding
   patched on later — three of the four used to be 22px. */
.site-nav__link {
  font-family: var(--pl-font-body);
  font-weight: 700;
  font-size: 0.94rem;
  color: var(--pl-logo);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 44px;
  white-space: nowrap;
}
.site-nav__link:hover { color: var(--pl-accent-text); }
/* Drawer only. On desktop the real link and its hover menu do the work. */
.nav-sub-checkbox,
.site-nav__areas-toggle { display: none; }

.site-nav__caret {
  width: 8px;
  height: 8px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-1px, -1px);
  transition: transform 180ms ease;
}

/* Practice-area menu. Opens on hover and on focus, which needs no JS; Escape
   closes it from main.js. The trigger stays a real link to /#services so the
   keyboard and the pointer both still have somewhere to go. */
.site-nav__item--menu { position: relative; display: flex; align-items: center; align-self: stretch; }
.site-nav__menu {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%) translateY(6px);
  display: grid;
  grid-template-columns: repeat(3, minmax(168px, 1fr));
  gap: 0.15rem 1.4rem;
  padding: 1.1rem;
  background: var(--pl-bg);
  border: 1px solid var(--pl-aqua);
  /* 14px like the site's other popovers (service sheets, team bubbles),
     not the 12px card radius: panels that pop are one family now. */
  border-radius: 14px;
  box-shadow: 0 18px 40px -18px rgba(0, 50, 78, 0.35);
  opacity: 0;
  visibility: hidden;
  transition: opacity 160ms ease, transform 160ms ease;
}
/* The tail: the menu is a speech bubble answering "What We Do", same
   grammar as every other popover on the site. ::before is the hover
   bridge, so the tail lives on ::after. */
.site-nav__menu::after {
  content: '';
  position: absolute;
  top: -8.5px;
  left: 50%;
  margin-left: -8px;
  width: 16px;
  height: 16px;
  background: var(--pl-bg);
  border-left: 1px solid var(--pl-aqua);
  border-top: 1px solid var(--pl-aqua);
  transform: rotate(45deg);
  border-radius: 3px 0 0 0;
}
/* The panel sits below the bar, so without a bridge the pointer crosses a dead
   strip on its way down and the menu shuts under the cursor. */
.site-nav__menu::before {
  content: '';
  position: absolute;
  top: -14px;
  left: 0;
  right: 0;
  height: 14px;
}
.site-nav__item--menu:hover .site-nav__menu,
.site-nav__item--menu:focus-within .site-nav__menu {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
}
.site-nav__item--menu:hover .site-nav__caret,
.site-nav__item--menu:focus-within .site-nav__caret {
  transform: rotate(225deg) translate(-2px, -2px);
}
.site-nav__menu-group {
  font-family: var(--pl-font-body);
  font-weight: 700;
  /* 0.66rem rendered 10.56px - below the 11px functional-text floor the
     design detector flagged 2026-08-04. Matches .pl-label's 0.72rem now. */
  font-size: 0.72rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--pl-ink-soft);
  margin: 0 0 0.35rem;
  padding: 0 0.5rem;
}
.site-nav__menu a {
  display: block;
  font-family: var(--pl-font-body);
  font-weight: 400;
  font-size: 0.86rem;
  line-height: 1.3;
  color: var(--pl-logo);
  text-decoration: none;
  padding: 0.5rem;
  border-radius: 6px;
}
.site-nav__menu a:hover { background: var(--pl-card); color: var(--pl-accent-text); }

/* Right cluster. The number is the quiet half of the pair; one pill only. */
.site-header__actions {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  justify-self: end;
}
.site-header__tel {
  font-family: var(--pl-font-display);
  font-weight: 600;
  font-size: 0.875rem;
  color: var(--pl-logo);
  text-decoration: none;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 0.25rem;
}
.site-header__tel:hover { color: var(--pl-accent-text); }
.site-header__tel-short { display: none; }
.site-header__cta {
  font-family: var(--pl-font-display);
  font-weight: 600;
  font-size: 0.875rem;
  background: var(--pl-logo);
  color: #fff;
  border: 1px solid var(--pl-logo);
  border-radius: 999px;
  padding: 0 1.4rem;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  white-space: nowrap;
  transition: background 180ms ease, border-color 180ms ease;
}
.site-header__cta:hover { background: #004a70; border-color: #004a70; }
.site-nav__drawer-cta { display: none; }

/* Footer — deep logo-ink band, real firm info */
.site-footer {
  background: var(--pl-logo);
  color: #fff;
  margin-top: 4rem;
  font-family: var(--pl-font-body);
  font-size: 0.9rem;
}
.site-footer__bar {
  max-width: var(--pl-max-width);
  margin: 0 auto;
  padding: 1.6rem var(--pl-gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem 2.5rem;
  flex-wrap: wrap;
}
.site-footer p { color: rgba(255, 255, 255, 0.82); }
.site-footer a {
  color: #fff;
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.35);
  padding-bottom: 1px;
}
.site-footer a:hover { color: var(--pl-butter); border-bottom-color: var(--pl-butter); }
.site-footer__nav {
  list-style: none;
  margin: 0;
  padding: 0;
  color: rgba(255, 255, 255, 0.82);
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem 1.6rem;
  font-size: 0.88rem;
}
.site-footer__nav li { margin: 0; }
.site-footer__nav a { border-bottom: none; }
.site-footer__brand-lockup img {
  display: block;
  height: 40px;
  width: auto;
}
.site-footer__reach {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem 1.4rem;
  font-size: 0.88rem;
}
.site-footer__reach > a { border-bottom: none; }
.site-footer__reviews {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  vertical-align: middle;
  border-bottom: none;
}
.site-footer__reviews svg {
  width: 13px;
  height: 13px;
  color: var(--pl-butter);
}
.site-footer__social {
  list-style: none;
  /* The padding below supplies the spacing between icons, so the row carries
     no gap and is pulled back to keep its original left edge. */
  margin: 0 0 0 -0.8rem;
  padding: 0;
  display: flex;
  gap: 0;
}
.site-footer__social a {
  display: inline-flex;
  border-bottom: none;
  padding: 0.8rem;
  color: rgba(255, 255, 255, 0.82);
  transition: color 160ms ease;
}
.site-footer__social a:hover { color: var(--pl-butter); }
.site-footer__social svg { width: 19px; height: 19px; }
.site-footer__legal { border-top: 1px solid rgba(255, 255, 255, 0.18); }
.site-footer__legal-row {
  max-width: var(--pl-max-width);
  margin: 0 auto;
  padding: 1.1rem var(--pl-gutter);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.site-footer__legal p {
  margin: 0;
  color: rgba(255, 255, 255, 0.65);
  font-size: 0.8rem;
}
@media (max-width: 760px) {
  .site-footer__bar { flex-direction: column; align-items: flex-start; }
}
/* Direction 2 migration, stage 1 (2026-09-20), ported from /labs/polish:
   the phone footer "looked disorganized" - left aligned, nav wrapping 3/3/1,
   phone and email crammed onto one row, two cramped legal lines. Replaces
   the old 640px pass below (which only shrank the wide-row spacing rather
   than re-laying it out): one centred column, the nav as an even two-column
   grid with real tap heights, phone and email each on their own line, 46px
   social targets, legal lines centred. Plain single-class selectors are
   enough here - same specificity as the desktop rules above, later in the
   file - so the doubled ".site-footer .site-footer__x" hack in the lab isn't
   needed. flex-direction: column still comes from the 760px rule above,
   which this range also matches (700 < 760); everything else here overrides
   it directly. */
@media (max-width: 700px) {
  .site-footer__bar { align-items: center; text-align: center; gap: 1.2rem; padding-top: 2rem; padding-bottom: 1.4rem; }
  .site-footer__brand-lockup img { width: 134px; height: auto; }
  .site-footer__nav { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1rem; width: 100%; max-width: 330px; margin: 0; padding: 0; }
  .site-footer__nav li { margin: 0; }
  .site-footer__nav li:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .site-footer__nav a { display: block; padding: 0.6rem 0.25rem; font-size: 1rem; }
  .site-footer__reach { flex-direction: column; align-items: center; gap: 0; width: 100%; padding-top: 1.1rem; border-top: 1px solid rgba(255, 255, 255, 0.18); }
  .site-footer__reach > a { font-size: 1.1rem; padding: 0.45rem 0.5rem; }
  .site-footer__social { justify-content: center; gap: 0.5rem; margin: 0.6rem 0 0; padding: 0; }
  .site-footer__social a { display: grid; place-items: center; width: 46px; height: 46px; }
  .site-footer__social svg { width: 22px; height: 22px; }
  .site-footer__legal-row { flex-direction: column-reverse; align-items: center; text-align: center; gap: 0.7rem; }
  .site-footer__legal-row p { margin: 0; font-size: 0.875rem; line-height: 1.6; }
  .site-footer__legal-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.2rem 0.5rem; }
  .site-footer__reviews { flex-basis: 100%; justify-content: center; }
}

main { padding: 0; }

/* Hidden sitewide (Chad, 2026-08-19): the trail read as clutter under the
   new heroes. The BreadcrumbList JSON-LD on those pages stays - Google
   still gets the trail, visitors get the cleaner page. Delete this one
   rule to bring the visible trail back everywhere. */
.pl-breadcrumb { display: none !important; }
.pl-breadcrumb {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 0 auto;
  padding: 1.25rem var(--pl-gutter) 0;
  max-width: var(--pl-max-width);
  font-family: var(--pl-font-body);
  font-size: 0.8rem;
}
.pl-breadcrumb li { display: flex; align-items: center; gap: 0.4rem; }
.pl-breadcrumb li:not(:last-child)::after { content: '/'; color: var(--pl-aqua); }
.pl-breadcrumb a { color: var(--pl-ink-soft); text-decoration: none; }
.pl-breadcrumb a:hover { color: var(--pl-primary); }
.pl-breadcrumb [aria-current="page"] { color: var(--pl-primary); font-weight: 700; }

.page, .post {
  max-width: 760px;
  margin: 0 auto;
  padding: 3rem var(--pl-gutter);
}
.pl-label--eyebrow { display: block; margin-bottom: 0.5rem; color: var(--pl-accent-text); }
.post__categories {
  margin-top: 2rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--pl-aqua);
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.post time {
  font-family: var(--pl-font-body);
  font-weight: 700;
  font-size: 0.8rem;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--pl-accent-text);
}
.post__hero {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: var(--pl-radius-card);
  margin: 1rem 0 2rem;
}

/* Interim styling for the Elementor forms carried over from WordPress
   (contact, inquire, wills-made-simple, form-incorporation). These
   classes are consistent across every migrated form, so this fixes
   all of them at once, ahead of the full Phase 2 rebuild. */
.elementor-form {
  max-width: 480px;
  margin-top: 1.5rem;
}
.elementor-field-group { margin-bottom: 1.25rem; }
.elementor-field-label {
  display: block;
  font-family: var(--pl-font-body);
  font-weight: 700;
  font-size: 0.8rem;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--pl-primary);
  margin-bottom: 0.4rem;
}
.elementor-field,
.elementor-field-textual {
  width: 100%;
  font-family: var(--pl-font-body);
  font-size: 1rem;
  color: var(--pl-ink);
  background: #fff;
  border: 1px solid var(--pl-aqua);
  border-radius: 8px;
  padding: 0.7rem 0.9rem;
}
textarea.elementor-field { min-height: 120px; resize: vertical; }
.elementor-field:focus,
.elementor-field-textual:focus {
  border-color: var(--pl-primary);
}
.elementor-button {
  display: inline-block;
  font-family: var(--pl-font-body);
  font-weight: 700;
  font-size: 0.9rem;
  background: var(--pl-primary);
  color: #fff;
  border: none;
  border-radius: var(--pl-radius-btn);
  padding: 0.8rem 1.9rem;
  cursor: pointer;
}
.elementor-button:hover { opacity: 0.85; }

/* Honeypot. Must be genuinely removed from the page rather than moved
   off-screen: an off-screen field is still reachable by keyboard and by a
   screen reader, so a real person could land in it and have their enquiry
   silently discarded as spam. Bots parse the HTML and fill it regardless. */
.form-gotcha { display: none; }

/* Shown only when a form has no endpoint yet. Without this, submitting an
   unwired form does nothing at all, and someone with a real legal matter
   would reasonably believe they had just contacted a lawyer. */
.form-notice,
.form-aside {
  margin-top: 1rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--pl-aqua);
  border-left: 3px solid var(--pl-accent-text);
  background: var(--pl-card);
  font-size: 0.95rem;
}
.form-notice a,
.form-aside a { font-weight: 700; }

/* Live status region for the async enquiry-form submit (main.js "Enquiry
   forms"). Empty and untouched until JS sets text into it, so no stray box
   shows up before there is anything to say. */
.form-status:empty { display: none; }
.form-status {
  margin-top: 1rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--pl-aqua);
  border-left: 3px solid var(--pl-primary);
  background: var(--pl-card);
  font-size: 0.95rem;
}
.form-status--error {
  border-color: var(--pl-accent-text);
  border-left-color: var(--pl-accent-text);
  color: var(--pl-accent-text);
}

/* The no-solicitor-client-relationship warning, sat directly above the submit
   button. It belongs here rather than only on the terms page because nobody
   reads the terms page before typing out their matter. Quiet, but not so
   quiet it fails contrast. */
.form-consent {
  margin: 0 0 1rem;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--pl-ink-soft);
  max-width: 60ch;
}

/* Button + text-link pairs (hero, closing CTAs) — a plain inline .pl-btn
   next to a .pl-link with no wrapper only had a collapsed whitespace
   character between them (a few px, no vertical alignment), which read as
   the two controls being squished together. */
.pl-actions {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  flex-wrap: wrap;
  margin-top: 1.5rem;
}

/* Work hero — photo band behind service page titles, coral overlay
   matches --pl-primary so pages without a photo still read fine. */
/* .work-hero (stock photo under a teal wash) retired 2026-08-17 - practice
   pages now use the homepage's words-only .ask hero, see work.njk. */

/* --- Practice pages: the homepage treatment ------------------------------ */
/* The practice hero: words only, centred (Chad, 2026-08-19). Two photo
   treatments were tried and rejected the same day (offset aqua plate:
   "too small and basic"; right-edge aqua ground panel: "so bad") - do not
   re-pitch either. The photo front matter survives on the files.
   The golden-hour gradient tried here 2026-08-19 moved to the card band
   the same day (Chad: better under the cards than behind the title). */
.ask--work {
  padding-top: clamp(2.5rem, 4.5vw, 3.75rem);
  padding-bottom: clamp(2.5rem, 4.5vw, 3.75rem);
  text-align: center;
}
/* The photo wall (Chad's Fuser reference, 2026-08-19): small photo cards
   flanking the centred words like polaroids pinned beside a headline -
   three stacked left, two right, each with its own slight tilt and drift
   so the wall reads hung-by-hand rather than templated. overflow-x on the
   section guards the tilted corners; the walls vanish below 1100px. */
.ask--walled { position: relative; overflow-x: clip; }
.ask--walled .pl-wrap { position: relative; }
/* Anchored to the TEXT COLUMN, not the viewport (placement pass, same day:
   pinning to the edges left a gulf of white between walls and words on wide
   screens and the even spacing read templated). max() keeps them on-screen
   at 1100-1300px; above that they travel with the headline. Sizes, gaps and
   drifts all vary per card so nothing lines up. */
.ask__wall {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: clamp(190px, 16vw, 250px);
}
/* Anchor tuning: 660 read too far from the copy, 625 too close - 645 it is. */
.ask__wall--left { left: max(3.5rem, calc(50% - 645px)); }
.ask__wall--right { right: max(3.5rem, calc(50% - 645px)); transform: translateY(-42%); }
.ask__wall img {
  display: block;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 12px;
  box-shadow: 0 2px 5px rgba(26, 26, 26, 0.10), 0 10px 24px rgba(26, 26, 26, 0.14);
  background: #fff;
  /* The white rim keeps overlapped cards reading as separate prints. */
  border: 3px solid #fff;
}
/* Chad's alignment call: the top and bottom cards' CENTRES sit on the
   middle card's left edge (which starts at 16%), so top = 16% - 90%/2 and
   bottom = 16% - 94%/2. Overlap pass same day: each card shingles over the
   one above (negative top margins, later card on top), compacting the
   stacks so the walls tuck in closer to the headline. */
.ask__wall--left img:nth-child(1) { width: 90%; margin-left: -29%; transform: rotate(-2.5deg); }
.ask__wall--left img:nth-child(2) { width: 106%; margin-left: 16%; margin-top: -38px; position: relative; z-index: 1; transform: rotate(1.75deg); }
.ask__wall--left img:nth-child(3) { width: 94%; margin-left: -31%; margin-top: -34px; position: relative; z-index: 2; transform: rotate(-1.5deg); }
.ask__wall--right img:nth-child(1) { width: 104%; margin-left: -12%; transform: rotate(2.25deg); }
.ask__wall--right img:nth-child(2) { width: 92%; margin-left: 14%; margin-top: -36px; position: relative; z-index: 1; transform: rotate(-2deg); }
@media (min-width: 1100px) {
  /* Room for the three-card stack so the walls never crowd the words. */
  .ask--walled {
    padding-top: clamp(3.25rem, 5vw, 4.5rem);
    padding-bottom: clamp(3.25rem, 5vw, 4.5rem);
    min-height: 540px;
    display: grid;
    align-items: center;
  }
}
@media (max-width: 1099.98px) {
  .ask__wall { display: none; }
}
.ask--work .ask__words { max-width: 62ch; margin-inline: auto; }
.ask--work h1 { max-width: 20ch; margin-inline: auto; }
.ask--work .ask__eyebrow { justify-content: center; }
.ask--work .ask__actions { justify-content: center; }
/* The lede's box is narrower than the words column (42ch) and left-anchored
   by default - centre the box itself, not just the text inside it. */
.ask--work .ask__lede { margin-inline: auto; }

/* "What we help with": the card grammar, sized for a list rather than for
   the homepage's three big doors. Cream cards on the aqua wash, wire-free -
   the practice pages have no per-service marks. */
/* The situation pills (Chad's mock, 2026-08-19): centred header, persona
   pills, and a prioritised trio per pill. Navy filled = active, outlined =
   resting; the slot label is the coral eyebrow voice. Sets swap with a soft
   rise; the full grid stays for no-JS. */
.areas--filtered .areas__q { text-align: center; }
.areas__eyebrow {
  text-align: center;
  font-family: var(--pl-font-body);
  font-weight: 800;
  font-size: 0.72rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--pl-accent-text);
  margin: 0 0 0.5rem;
}
.areas__lede {
  text-align: center;
  color: var(--pl-ink-soft);
  margin: 0.75rem auto 0;
  max-width: 52ch;
}
.help-pills {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin: 1.5rem 0 2.25rem;
}
.help-pill {
  font-family: var(--pl-font-body);
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--pl-logo);
  background: #fff;
  border: 1px solid rgba(0, 50, 78, 0.30);
  border-radius: 999px;
  padding: 0.65rem 1.4rem;
  cursor: pointer;
  transition: background 180ms ease, color 180ms ease, border-color 180ms ease, transform 180ms ease;
}
.help-pill:hover { border-color: var(--pl-logo); transform: translateY(-1px); }
/* The chosen persona goes butter (2026-08-21). Yellow had one job on these
   pages - the stamp - and this gives it a second one that carries meaning
   rather than decoration: butter is the "this is the one you picked" colour,
   and it separates selection from the teal that everything else on the page is
   already drawn in.

   #0C5F72 and not white: butter is a light fill, so it needs dark ink. That
   pairing measures 5.07:1 and is the same one settled on the process stamp. */
.help-pill[aria-pressed="true"] {
  background: var(--pl-butter);
  border-color: #EFC53A;
  color: #0C5F72;
}
.help-card__slot {
  font-family: var(--pl-font-body);
  font-weight: 800;
  font-size: 0.68rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--pl-accent-text);
  margin: 0 0 0.55rem;
}
/* Doubled selectors on purpose: the sets carry .help-grid too, and its
   display:grid rule sits LATER in this file - at single-class specificity
   it wins and every set renders at once (the same cascade trap as the
   peach band; it put a 12-card wall in front of Chad). */
.help-grid.help-set { display: none; }
.help-grid.help-set.is-current { display: grid; animation: helpset-in 260ms ease; }
@keyframes helpset-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}
/* JS flips the section to filtered mode; the full grid steps aside. */
.areas--work.is-filtered .help-grid--all { display: none; }
@media (prefers-reduced-motion: reduce) {
  .help-grid.help-set.is-current { animation: none; }
  .help-pill:hover { transform: none; }
}

/* The card band ground: back on the .areas aqua wash. Everything tried here
   2026-08-19 and rejected same-day - full peach ("way too loud"; also note
   the base .areas rule sits ~700 lines later and wins the cascade unless
   you double the class: .areas.areas--work), then the Outseta golden-hour
   gradient, 145deg #FBD5CE > #FBEFE7 36% > #FDF3E3 62% > #FFE8A8 ("cool but
   not professional"). Do not re-pitch either; the gradient recipe is kept
   here in case a marketing surface ever wants it. */
.areas--work { padding-bottom: clamp(3rem, 5vw, 4.5rem); }
.help-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: clamp(1rem, 1.8vw, 1.5rem);
}
.help-card {
  background: var(--pl-card);
  border: 1px solid var(--pl-aqua);
  border-radius: var(--pl-radius-card);
  box-shadow: var(--pl-shadow);
  padding: 1.35rem 1.4rem 1.25rem;
  position: relative;
  overflow: hidden;
  transition: transform 220ms ease, box-shadow 220ms ease;
}
.help-card h3 { font-size: 1rem; margin: 0 0 0.35rem; }
.help-card p { font-size: 0.92rem; color: var(--pl-ink-soft); margin: 0; max-width: none; }

/* The cards wake up (Chad, 2026-08-19: the practice pages read "plain
   jane"). Same rest / stir / go grammar as the homepage:
   rest - cards cascade in one by one when the band first scrolls into view
          (armed only when JS runs and motion is allowed, same contract as
          .steps--armed, so no-JS and reduced-motion never hide a card);
   stir - hover lifts the card and a coral wire draws itself across the top
          edge, the door-mark draw translated to a rule. */
.help-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--pl-accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 340ms cubic-bezier(0.22, 1, 0.36, 1);
}
.help-card:hover, .help-card:focus-within {
  transform: translateY(-4px);
  box-shadow: 0 3px 8px rgba(26, 26, 26, 0.10), 0 16px 34px rgba(26, 26, 26, 0.14);
}
.help-card:hover::before, .help-card:focus-within::before { transform: scaleX(1); }
.help-grid--armed .help-card {
  opacity: 0;
  transform: translateY(16px);
}
.help-grid--armed.is-run .help-card {
  opacity: 1;
  transform: translateY(0);
  transition:
    opacity 480ms ease calc(var(--card-i, 0) * 110ms),
    transform 480ms cubic-bezier(0.22, 1, 0.36, 1) calc(var(--card-i, 0) * 110ms);
}
/* Hover transitions take over after the entrance has run its course. */
.help-grid--armed.is-run.is-done .help-card {
  transition: transform 220ms ease, box-shadow 220ms ease;
}
@media (prefers-reduced-motion: reduce) {
  .help-card, .help-card::before { transition: none; }
  .help-card:hover, .help-card:focus-within { transform: none; }
}

/* ---- Practice pages: the split hero (2026-09-20, Chad's pick, option B) ----
   Words left in the homepage's voice, one real photo right as a wave card in
   the family colour of the homepage card that leads here. Replaces the
   centred words + five-photo wall; the .ask__wall / .ask--walled rules above
   are now dead and can go in the next cleanup. Every rule is under
   .ask.ask--work.ask--split so nothing reaches the homepage hero. */
.ask.ask--work.ask--split { padding-block: clamp(2.5rem, 4vw, 4.5rem) clamp(3rem, 5vw, 5rem); }
.whero { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); gap: clamp(2.5rem, 5vw, 6rem); align-items: center; }
.ask.ask--work.ask--split .ask__words { max-width: none; margin-inline: 0; text-align: left; }
.ask.ask--work.ask--split .ask__eyebrow { justify-content: flex-start; }
.ask.ask--work.ask--split h1 {
  font-family: 'Instrument Serif', Georgia, serif; font-weight: 400;
  font-size: clamp(3rem, 5vw, 6rem); line-height: 1.04; letter-spacing: -0.01em;
  color: #00324E; max-width: none; margin-inline: 0; text-wrap: balance;
}
.ask.ask--work.ask--split h1 em { font-style: italic; font-weight: 400; color: var(--pl-accent-text); }
.ask.ask--work.ask--split .ask__lede { font-size: clamp(1.08rem, 1.05vw, 1.2rem); line-height: 1.6; max-width: 42ch; margin-inline: 0; }
.ask.ask--work.ask--split .ask__actions { justify-content: flex-start; }
.whero__card { position: relative; border-radius: 28px; overflow: hidden; aspect-ratio: 5 / 4; box-shadow: 0 6px 14px rgba(26, 26, 26, .06), 0 24px 56px rgba(26, 26, 26, .14); }
.whero__card img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
/* 2026-10-02, Elizabeth: "straight lines or a colour band". Chad picked the
   band: the mark IS the foot, a straight block in the card's colour with an
   8px lighter stripe on top, symbol and label inside it. Replaces .whero__wave. */
.whero__mark { position: absolute; left: 0; right: 0; bottom: 0; display: flex; align-items: center; gap: .9rem; padding: 1.2rem 2rem 1.4rem; background: var(--w-fill); color: var(--w-ink); font: 700 clamp(1.1rem, 1.2vw, 1.35rem)/1.2 var(--pl-font-display); }
.whero__mark svg { width: 44px; height: 44px; flex: none; }
.whero__card--teal   { --w-fill: #0E6B80; --w-light: #BFDDDE; --w-ink: #fff; }
.whero__card--coral  { --w-fill: #EE7A70; --w-light: #F6DBCA; --w-ink: #00324E; }
.whero__card--butter { --w-fill: #FFD34D; --w-light: color-mix(in srgb, #FFD34D 45%, #FFFFFF); --w-ink: #00324E; }
@media (max-width: 900px) {
  .whero { grid-template-columns: minmax(0, 1fr); gap: 2.25rem; }
  .ask.ask--work.ask--split h1 { font-size: clamp(2.6rem, 9.5vw, 3.8rem); }
  .whero__card { aspect-ratio: 4 / 3; border-radius: 22px; max-width: 640px; }
  .whero__mark { padding: 1rem 1.25rem 1.1rem; gap: .7rem; }
  .whero__mark svg { width: 34px; height: 34px; }
}

/* ---- Practice pages: the prioritised trio as WAVE CARDS (2026-09-20) ----
   Chad picked this from three roughs (wave cards / a dotted path / one block
   with a rail). The old trio cards were 140px tall with 15px text on a 1920
   screen, the weakest band on the page. Same family as the homepage service
   cards: white card, a foot in the card's colour, the slot label as a pill
   inside the SOLID colour. Ink: white on teal, navy on coral and butter. The
   no-JS full grid keeps the plain card. 2026-10-02, Elizabeth: "straight lines
   or a colour band"; Chad picked the band, so the foot is a straight block with
   a lighter stripe on top and the wave SVG is gone. The foot is 28px shorter
   than the wave box was (24px on the phone) and the paragraph's bottom margin
   grows by the same amount, so every card keeps its old height. */
.areas--filtered .areas__lede { font-size: 1.1rem; max-width: none; }
.areas--filtered .help-pill { font-size: 1rem; }
.areas--filtered .help-pills { margin: 1.6rem 0 2.6rem; }
.help-grid.help-set { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(1.25rem, 2.2vw, 2.5rem); }
.help-card--wave {
  display: flex; flex-direction: column; text-align: center;
  min-height: 330px; padding: 2.4rem 2.2rem 0;
  background: #fff; border: 0; border-radius: 24px;
  box-shadow: 0 2px 6px rgba(26, 26, 26, .05), 0 18px 44px rgba(26, 26, 26, .10);
}
.help-card--wave::before { content: none; }
.help-card--wave:hover, .help-card--wave:focus-within { transform: none; box-shadow: 0 2px 6px rgba(26, 26, 26, .05), 0 18px 44px rgba(26, 26, 26, .10); }
.help-card--wave h3 { font-size: clamp(1.25rem, 1.35vw, 1.5rem); line-height: 1.2; margin: 0 0 .7rem; }
.help-card--wave > p { font-size: 1.08rem; line-height: 1.55; color: var(--pl-ink); margin: 0 0 calc(1.5rem + 28px); }
.help-card--teal   { --w-fill: #0E6B80; --w-light: #BFDDDE; --w-ink: #fff; }
.help-card--coral  { --w-fill: #EE7A70; --w-light: #F6DBCA; --w-ink: #00324E; }
.help-card--butter { --w-fill: #FFD34D; --w-light: color-mix(in srgb, #FFD34D 45%, #FFFFFF); --w-ink: #00324E; }
.help-card__foot { position: relative; margin: auto -2.2rem 0; height: 90px; display: flex; align-items: center; justify-content: center; background: var(--w-fill); }
.help-card--wave .help-card__slot {
  position: relative; margin: 0; width: max-content; white-space: nowrap;
  font-size: .9rem; letter-spacing: .1em; color: var(--w-ink);
  border: 1.5px solid var(--w-ink); border-radius: 999px; padding: .5rem 1.2rem;
}
@media (max-width: 1100px) {
  .help-card--wave { padding: 2rem 1.4rem 0; min-height: 320px; }
  .help-card__foot { margin-inline: -1.4rem; }
  .help-card--wave > p { font-size: 1rem; }
  .help-card--wave .help-card__slot { font-size: .8rem; padding: .45rem .9rem; }
}
@media (max-width: 820px) {
  .help-grid.help-set { grid-template-columns: minmax(0, 1fr); max-width: 520px; margin-inline: auto; }
  .help-card--wave { min-height: 0; padding-top: 1.9rem; }
  .help-card__foot { height: 82px; }
  .help-card--wave > p { margin-bottom: calc(1.5rem + 22px); }
  .help-card--wave .help-card__slot { font-size: .85rem; padding: .5rem 1.1rem; }
}

/* The deep read: the migrated prose, kept for the visitor who wants it and
   for search, collapsed behind a native <details>. Title and prose share one
   62ch column (no auto-centring drift), and the migrated H2/H3s are stepped
   down so they read as sub-headings under the page, not as rival page
   titles. */
.deep { padding: clamp(2.5rem, 4vw, 3.5rem) 0; }
.deep__box {
  border: 1px solid var(--pl-aqua);
  border-radius: var(--pl-radius-card);
  background: var(--pl-card);
}
.deep__title {
  cursor: pointer;
  list-style: none;
  padding: 1.25rem 1.5rem 1.25rem 3.1rem;
  position: relative;
  font-family: var(--pl-font-display);
  font-weight: 600;
  font-size: 1.08rem;
  color: var(--pl-logo);
  margin: 0;
}
.deep__title::-webkit-details-marker { display: none; }
.deep__title::before {
  content: '';
  position: absolute;
  left: 1.35rem;
  top: 1.55rem;
  width: 0.55rem;
  height: 0.55rem;
  border-right: 2px solid var(--pl-accent-text);
  border-bottom: 2px solid var(--pl-accent-text);
  transform: rotate(-45deg);
  transition: transform 200ms ease;
}
.deep__box[open] .deep__title::before { transform: rotate(45deg); top: 1.4rem; }
.deep__title:hover { color: var(--pl-primary); }
.deep__hint {
  display: block;
  font-family: var(--pl-font-body);
  font-weight: 400;
  font-size: 0.86rem;
  color: var(--pl-ink-soft);
  margin-top: 0.15rem;
}
/* The card spans the shell (a 62ch box stranded on a 1920 screen was the
   complaint); the prose inside flows into newspaper columns so each line
   stays a readable measure. Headings never straddle a column break. */
.page--deep {
  max-width: none;
  margin: 0;
  padding: 1.25rem 3.1rem 1.6rem;
  border-top: 1px solid var(--pl-aqua);
  columns: 2;
  column-gap: clamp(2rem, 4vw, 4rem);
  column-rule: 1px solid #ECE6DA;
}
.page--deep h2 { font-size: 1.15rem; margin: 1.6em 0 0.5em; break-after: avoid; }
.page--deep h3 { font-size: 1rem; margin: 1.3em 0 0.4em; break-after: avoid; }
.page--deep p, .page--deep li { font-size: 0.97rem; break-inside: avoid; }
.page--deep p, .page--deep ul, .page--deep ol { max-width: none; }
.page--deep > :first-child { margin-top: 0; }
@media (min-width: 1500px) { .page--deep { columns: 3; } }
@media (max-width: 900px) { .page--deep { columns: 1; column-rule: none; } }
@media (max-width: 560px) {
  .deep__title { padding-left: 2.6rem; }
  .deep__title::before { left: 1.05rem; }
  .page--deep { padding-left: 1.25rem; padding-right: 1.25rem; }
}

.section { padding: 3.5rem var(--pl-gutter); }
.section > .pl-label { color: var(--pl-accent-text); }
/* Cap running prose at a comfortable line length — sections are as wide
   as the full 1120px grid, which reads badly for plain paragraphs/lists
   once a page has more copy than the homepage's short intro blurbs. */
.section p, .section ul, .section ol { max-width: 70ch; }
/* White, truly centred ending (Chad's call 2026-08-04): the aqua inset
   card is retired sitewide, matching the homepage's white close. The old
   version also only half-centred: the h2 centred while the paragraph sat
   in a left-pinned 70ch column and the actions never centred at all. */
.section--cta {
  text-align: center;
  margin: 0 auto 3rem;
  max-width: calc(var(--pl-max-width) - 2 * var(--pl-gutter));
}
.section--cta p { margin-left: auto; margin-right: auto; }
.section--cta .pl-actions { justify-content: center; }
.section--cta .pl-link { display: block; margin-top: 1rem; }

.card-grid, .post-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1rem;
  margin-top: 1.5rem;
}
.card-grid__item {
  text-decoration: none;
  color: var(--pl-ink);
}
.card-grid__item h3 { margin: 0; font-size: 1.1rem; }

/* The shared .card-grid auto-fits on a 200px minimum, which is right for the
   two and three card groups on the landing pages but puts all six practice
   areas in a single 235px-wide row and overflows the page. The /work/ index is
   the only six-item grid on the site, so it gets an explicit column count
   instead of widening the minimum for everything. */
.card-grid--areas { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 900px) { .card-grid--areas { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .card-grid--areas { grid-template-columns: 1fr; } }

.post-grid { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.post-grid__item {
  text-decoration: none;
  color: var(--pl-ink);
  display: block;
}
.post-grid__item time {
  display: block;
  font-family: var(--pl-font-body);
  font-weight: 700;
  font-size: 0.75rem;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--pl-accent-text);
  margin-bottom: 0.5rem;
}
/* The card titles are h2 in the markup (our-thoughts.njk, categories.njk), so
   the old h3-only rule never applied and the global h2 clamp (up to 2.6rem)
   ran "Representation" out of a 280px card. */
.post-grid__item h2,
.post-grid__item h3 { margin: 0; font-size: 1.35rem; line-height: 1.25; overflow-wrap: break-word; }

.team-profile {
  display: flex;
  align-items: center;
  gap: 2rem;
  margin-bottom: 2rem;
}
.team-profile__photo {
  width: 160px;
  height: 160px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}
.team-profile__intro h1 { margin-bottom: 0.3em; }
.team-profile__role { color: var(--pl-accent-text); margin-bottom: 0.5em; }
@media (max-width: 560px) {
  .team-profile { flex-direction: column; text-align: center; gap: 1.25rem; }
}


/* FAQ accordion — native <details>/<summary>, no JS needed */
.faq-group { margin-bottom: 2.5rem; }
.faq-group:last-child { margin-bottom: 0; }
.faq-item {
  border-bottom: 1px solid var(--pl-aqua);
  padding: 1rem 0;
}
.faq-item summary {
  cursor: pointer;
  font-family: var(--pl-font-body);
  font-weight: 700;
  color: var(--pl-primary);
  list-style: none;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::before {
  content: '+';
  display: inline-block;
  width: 1em;
  color: var(--pl-accent-text);
}
.faq-item[open] summary::before { content: '\2212'; }
.faq-item p { margin: 0.75rem 0 0; }

/* Testimonial cards (Wall of Love) */
.testimonial-grid { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.testimonial-grid .pl-card p { font-style: italic; }
.testimonial-grid cite {
  display: block;
  margin-top: 1rem;
  font-style: normal;
  font-family: var(--pl-font-body);
  font-weight: 700;
  font-size: 0.85rem;
  color: var(--pl-primary);
}
.testimonial-grid cite span { display: block; font-weight: 400; color: var(--pl-ink-soft); font-size: 0.8rem; }

/* Drawer breakpoint raised from 640 to 900: the three zones plus a six-item
   menu need the room, and between 641 and 900 the old bar was already tight. */
@media (max-width: 900px) {
  .site-header__inner {
    display: flex;
    gap: 0.75rem;
    height: 62px;
  }
  .site-header__logo img { height: 32px; }
  .nav-toggle-checkbox {
    display: block;
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .nav-toggle-checkbox:focus-visible + .nav-toggle-label {
    outline: 3px solid var(--pl-accent-text);
    outline-offset: 4px;
  }
  .nav-toggle-label { display: flex; margin-left: 0; }
  .site-header__actions { margin-left: auto; gap: 0.6rem; }
  /* The number becomes the pill. On a phone it is the one channel that works
     today, and "Call" fits a 62px bar where the full number does not. */
  .site-header__tel {
    background: var(--pl-logo);
    color: #fff;
    border: 1px solid var(--pl-logo);
    border-radius: 999px;
    padding: 0 1.05rem;
    min-height: 40px;
    font-size: 0.85rem;
  }
  .site-header__tel:hover { color: #fff; }
  .site-header__tel-full { display: none; }
  .site-header__tel-short { display: inline; }
  .site-header__cta { display: none; }

  .site-nav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    /* Load-bearing. justify-self:center on the desktop rule still applies to
       this box once it is absolutely positioned, and any alignment other than
       normal makes an abspos box with left:0/right:0 shrink-to-fit and centre
       rather than fill — the drawer came out 283px wide, inset 46px a side,
       instead of full-bleed. */
    justify-self: stretch;
    flex-direction: column;
    /* stretch, not centre: stacked, these are full-width rows with dividers,
       and centring would shrink each one to its own text width */
    align-items: stretch;
    gap: 0;
    padding: 0.4rem var(--pl-gutter) 1.3rem;
    background: var(--pl-bg);
    border-bottom: 1px solid var(--pl-aqua);
    box-shadow: var(--pl-shadow);
  }
  /* :has() rather than a sibling combinator so the DOM can read in visual
     order (logo, nav, actions, toggle) instead of being shaped by the
     selector. Already used elsewhere in this file for body:has(.close). */
  .site-header__inner:has(.nav-toggle-checkbox:checked) .site-nav { display: flex; }

  .site-nav__link {
    min-height: 50px;
    font-size: 1rem;
    border-bottom: 1px solid var(--pl-aqua);
  }
  .site-nav__item--menu { display: block; align-self: auto; }
  .site-nav__item--menu .site-nav__link { display: flex; }
  .site-nav__caret { display: none; }
  /* Drawer shape for the areas list. It used to be always open here, on the
     grounds that a nested expand buries the six areas a level deeper - that
     was reversed 2026-08-25, see the toggle rules below. This rule still
     carries everything BUT the visibility: flattened out of the hover
     popover, indented, no shadow. */
  .site-nav__menu {
    position: static;
    display: block;
    transform: none;
    /* Every one of these undoes a desktop value that has no business in the
       drawer, and they are explicit because leaving them inherited is what
       produced a bug I could not reproduce (Chad on a real phone, 2026-08-25:
       expanded services "push off screen, I can only see the very end").
       The desktop rule is a centred popover - left:50%, translateX(-50%), and
       a grid of three 168px minimums, so a 504px floor. Block layout ignores
       the template and static ignores the offsets in Chromium, which is why
       375 and 390 measured clean here. Any engine that keeps even one of them
       gives a 549px box shifted half its width left, which is the reported
       symptom exactly. Cleared rather than relied upon. */
    grid-template-columns: none;
    left: auto;
    right: auto;
    max-width: 100%;
    opacity: 1;
    visibility: visible;
    padding: 0.5rem 0 0.7rem 0.9rem;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background: none;
  }
  .site-nav__menu::before { display: none; }
  .site-nav__menu-group { padding: 0.5rem 0.5rem 0; }
  .site-nav__menu a { min-height: 44px; display: flex; align-items: center; }
  /* The areas list starts CLOSED (Chad, 2026-08-25). It was deliberately
     always-open here on the grounds that a nested expand buries the six areas
     a level deeper - but always-open costs six rows of the drawer before the
     visitor reaches Who We Are or Contact, and on a phone the drawer is the
     whole nav. Closed by default, one tap to open.
     The anchor steps aside for a label: a trigger that navigates cannot also
     expand. Nothing is lost - the six links inside are the real destinations
     and /#services only ever pointed at a summary of them. */
  .site-nav__item--menu .site-nav__link--areas { display: none; }
  .nav-sub-checkbox {
    display: block;
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .nav-sub-checkbox:focus-visible + .site-nav__areas-toggle {
    outline: 3px solid var(--pl-accent-text);
    outline-offset: -3px;
  }
  .site-nav__item--menu .site-nav__areas-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    cursor: pointer;
  }
  /* Overrides the blanket caret hide in the drawer the caret is the
     only thing saying this row does something. */
  .site-nav__areas-toggle .site-nav__caret { display: block; }
  .site-nav__item--menu .site-nav__menu { display: none; }
  .site-nav__item--menu:has(.nav-sub-checkbox:checked) .site-nav__menu {
    display: block;
    grid-template-columns: none;
    transform: none;
    left: auto;
    right: auto;
    max-width: 100%;
  }
  .site-nav__item--menu:has(.nav-sub-checkbox:checked) .site-nav__areas-toggle .site-nav__caret {
    transform: rotate(-135deg) translate(-1px, -1px);
  }
  .site-nav__drawer-cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 50px;
    margin-top: 1rem;
    background: var(--pl-logo);
    color: #fff;
    border-radius: 999px;
    font-family: var(--pl-font-display);
    font-weight: 600;
    font-size: 0.94rem;
    text-decoration: none;
  }
}

/* Skip link + keyboard focus + reduced motion */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--pl-primary);
  color: #fff;
  font-family: var(--pl-font-body);
  font-weight: 700;
  padding: 0.7rem 1.2rem;
  border-radius: 0 0 8px 0;
  text-decoration: none;
}
.skip-link:focus { left: 0; }
:is(a, button, summary, input, select, textarea):focus-visible {
  outline: 3px solid var(--pl-accent-text);
  outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  /* Both still arrive, they just do not travel: the row opens at full height
     and the coral mark is simply there. That is the point of building these
     as transitions rather than keyframes. */
  .area::details-content { transition: none; }
  /* Same deal as .area::details-content above: the deep-page accordion
     (work.njk's <details class="deep__box">) still opens, its chevron just
     stops rotating on the way. */
  .deep__title::before { transition: none; }
  .pl-btn, .site-header__cta { transition: none; }
  .pl-btn:hover, .site-header__cta:hover { transform: none; }
  /* The menu still opens, it just stops sliding and rotating on the way. */
  .site-nav__menu, .site-nav__caret { transition: none; }
}

/* Aqua-surface text override. Aqua is light enough that neither the petrol teal
   (4.26:1) nor even the darkened coral (3.41:1) clears AA on it, so anything set
   on an aqua CTA surface takes the logo ink. Placed here deliberately: it ties
   on specificity with `.section > .pl-label` above, so it has to come later to
   win. Covers the homepage's full-bleed band and the inset card interior pages
   use. */
:is(.close, .section--cta) :is(.pl-label, .pl-link) { color: var(--pl-logo); }

/* ===========================================================================
   HOMEPAGE — "Waiting Room Antidote"
   The category ships a stock hero, a tracked eyebrow over every band, and a
   grid of matching icon cards. None of those appear below. Scale carries the
   hierarchy; the clip's own bent wire is the only ornament.
   =========================================================================== */

/* --- 1. The question ----------------------------------------------------- */
/* No eyebrow, no image. The doors are the hero. */
.ask { padding: clamp(3rem, 5.5vw, 4.75rem) 0 clamp(2.75rem, 4.5vw, 4rem); }
/* One centred column: words, then the film full width beneath them
   (Elizabeth, 2026-08-21 - see "The centred homepage" near the end of this
   file). The words-left / film-right split this replaces is gone, not gated.
   The film still does NOT autoplay: poster at rest, muted preview on hover,
   sound on click (main.js). */
.ask__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
}
/* --- eyebrow --- */
/* Eyebrow: the coral dash is gone (Chad, 2026-08-17) and the words carry
   the coral instead - readable coral, since this is small type. The <i>
   stays in the markup for now, collapsed, so the templates need no edit. */
/* Eyebrow: no dash, coral text (Chad, 2026-08-19 - promoted from the shapes
   lab to the default; the first colour move on the base site since the
   video-state revert). The coral text tone clears AA at 4.9:1. */
.ask__eyebrow { display: flex; align-items: center; margin: 0 0 1.375rem; }
.ask__eyebrow i { display: none; }
.ask__eyebrow span {
  font-family: var(--pl-font-body);
  font-weight: 700;
  /* Direction 2 migration, stage 1 (2026-09-20): raised to the 13px floor -
     nothing on the homepage renders smaller than this. */
  font-size: 0.8125rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--pl-accent-text);
}
/* --- actions --- */
.ask__actions {
  display: flex;
  align-items: center;
  gap: 1.375rem;
  flex-wrap: wrap;
  margin-top: 2.125rem;
}
.ask__or { font-size: 0.94rem; color: var(--pl-ink-soft); }
.ask__or a {
  color: var(--pl-logo);
  font-weight: 700;
  text-decoration: none;
  border-bottom: 2px solid var(--pl-aqua);
}
.ask__or a:hover { border-bottom-color: var(--pl-accent-text); }
@media (max-width: 640px) {
  /* Calling is the higher-intent channel here and it was a 110x22 inline link
     sitting 4px under a 53px button - easy to miss, easier to mis-tap. The
     target grows through a pseudo-element so the underline stays tight against
     the number instead of being pushed down by padding. */
  .ask__or a { position: relative; }
  .ask__or a::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    translate: 0 -50%;
    height: 44px;
  }
}
.ask__words { min-width: 0; }
.ask__film { margin: 0; min-width: 0; }
.film__frame { position: relative; }
.ask__film video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: var(--pl-radius-card);
  background: var(--pl-card);
  cursor: pointer;
}
/* Playfair now comes from the base h1 rule (sitewide since 2026-08-04);
   only the hero-specific scale and measure live here. This rule is shared
   with work.njk's .ask--work hero (see the "centred homepage" block later
   in this file), so the Instrument Serif swap for the real homepage hero is
   NOT added here - it would leak onto every practice page's h1 too. It lives
   in its own .home .ask h1 rule instead (Direction 2 migration, stage 1,
   2026-09-20). */
.ask h1 {
  /* Re-fit 2026-08-11 for Elizabeth's headline ("The legal stuff, minus the
     law-firm act." - 40 chars vs the old 32): the old 5.1vw/4.25rem scale
     could only wrap it in 3 lines, and because the measure below is in ch it
     shrinks with the font, so no font-size alone could fix it. 57px at a
     1280 viewport is the measured 2-line ceiling; the clamp caps just under
     it so the hero keeps the old two-line shape at a slightly smaller size. */
  font-size: clamp(2.6rem, 4.45vw, 3.55rem);
  line-height: 1.08;
  letter-spacing: -0.015em;
  text-wrap: balance;
  margin-bottom: 0;
  max-width: 17ch;
}
/* The teal clears AA as LARGE text only (4.26:1 on white). Safe at 42px+,
   never reuse it for body copy. */
/* The hero glows (Chad, 2026-08-17): the same halo language as the cards,
   carried up. A peach glow behind "law-firm act" and a butter glow behind
   the film. Blurred layers behind, never on, so the type and video stay
   crisp and the colour reads as light. */
.ask h1 em {
  font-style: italic;
  color: var(--pl-primary);
  position: relative;
  isolation: isolate;
}
[data-style="shapes"] .ask h1 em::before {
  content: '';
  position: absolute;
  inset: 42% -6% 4% -6%;
  border-radius: 999px;
  background: rgba(246, 219, 202, 0.95);
  filter: blur(14px);
  z-index: -1;
  pointer-events: none;
}
.film__frame video { position: relative; z-index: 1; }
.ask__lede {
  font-size: 1.09rem;
  line-height: 1.75;
  max-width: 42ch;
  margin: 1.625rem 0 0;
}

/* .ask__alt removed with the "would rather just talk" line it styled. Its job
   is now done by .ask__actions, where the phone sits beside a real button
   instead of being a 21px inline link. */

/* --- The boot ------------------------------------------------------------- */
/* A white curtain with the logo, which then flies up and docks into its
   exact place in the nav as the page reveals. Once per session, skipped for
   reduced motion, hidden without JS (noscript), and main.js carries a hard
   failsafe so this can never cover the site for more than ~2.5s. */
.boot {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 280ms ease;
}
.boot--off { display: none; }
.boot.is-fading { opacity: 0; pointer-events: none; }
.boot__logo {
  width: 196px;
  height: auto;
  opacity: 0;
  animation: boot-in 420ms ease 120ms forwards;
}
.boot.is-flying .boot__logo {
  transition: transform 580ms cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes boot-in {
  from { opacity: 0; scale: 0.94; }
  to { opacity: 1; scale: 1; }
}

/* --- The film bubble ------------------------------------------------------ */
.hello {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 70;
}
.hello__rest {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  opacity: 0;
  transform: translateY(10px) scale(0.85);
  transform-origin: bottom right;
  transition: opacity 320ms ease, transform 420ms cubic-bezier(0.34, 1.45, 0.64, 1);
}
.hello.is-in .hello__rest { opacity: 1; transform: none; }
.hello__label {
  background: #fff;
  border: 1px solid var(--pl-aqua);
  border-radius: 999px;
  padding: 0.45rem 0.85rem;
  font-family: var(--pl-font-body);
  font-weight: 700;
  font-size: 0.78rem;
  color: var(--pl-logo);
  box-shadow: 0 2px 8px rgba(26, 26, 26, 0.12);
  white-space: nowrap;
}
.hello__bubble {
  position: relative;
  width: 86px;
  height: 86px;
  padding: 0;
  border: 3px solid #fff;
  border-radius: 50%;
  overflow: hidden;
  cursor: pointer;
  background: var(--pl-card);
  box-shadow: 0 2px 6px rgba(26, 26, 26, 0.14), 0 12px 30px rgba(26, 26, 26, 0.22);
  transition: transform 240ms ease;
}
.hello__bubble:hover { transform: scale(1.05); }
.hello__preview {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.hello__play {
  position: absolute;
  right: 2px;
  bottom: 2px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--pl-accent-text);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
}
.hello__play svg { width: 14px; height: 14px; }
.hello__dismiss {
  order: -1;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(0, 50, 78, 0.55);
  color: #fff;
  font-size: 0.85rem;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
  transition: opacity 160ms ease;
}
.hello:hover .hello__dismiss,
.hello__dismiss:focus-visible { opacity: 1; }
.hello__player {
  width: min(430px, calc(100vw - 2rem));
  background: #fff;
  border: 1px solid var(--pl-aqua);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 4px 10px rgba(26, 26, 26, 0.10), 0 22px 48px rgba(26, 26, 26, 0.26);
  transform-origin: bottom right;
}
.hello.is-open .hello__rest { display: none; }
.hello__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.7rem 0.6rem 0.7rem 1rem;
}
.hello__head p {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--pl-logo);
  font-family: var(--pl-font-body);
}
.hello__close {
  flex: none;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--pl-card);
  color: var(--pl-logo);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}
.hello__close:hover { background: var(--pl-aqua); }
.hello__film {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #000;
}
@media (max-width: 640px) {
  .hello { right: 12px; bottom: 12px; }
  .hello__bubble { width: 68px; height: 68px; }
  .hello__label { font-size: 0.72rem; padding: 0.35rem 0.7rem; }
}
@media (prefers-reduced-motion: reduce) {
  .hello__rest, .hello__bubble { transition: none; }
}

/* --- 2. What the doors open onto ----------------------------------------- */
.areas {
  /* Loosened 2026-08-04: the old density pass was tuned for the compact
     accordion rows and left this - the heaviest band on the page - with the
     tightest padding. Rooms need air; one rhythm across all bands now. */
  /* Direction 2 migration, stage 1 (2026-09-20): more air again, and one
     hairline instead of a top-and-bottom pair, matching /labs/polish. Kept
     padding-block rather than the old shorthand so this never zeroes inline
     padding on an axis nothing else here sets. Background left alone: this
     class is shared with the practice pages' card band (.areas--work in
     work.njk), and Elizabeth signed off its aqua wash on 2026-08-19 - .home
     .areas below already carries the homepage to white without touching
     that. */
  padding-block: var(--pl-section-air);
  background: rgba(191, 221, 222, 0.22);
  border-top: 1px solid color-mix(in srgb, #0E6B80 16%, transparent);
  border-bottom: 0;
}
/* The question heads this section rather than living in its own band with
   three links down to it: routing to a six-item list one screen below is a
   menu pointing at a menu. */
.areas__q {
  /* Direction 2 migration, stage 1 (2026-09-20): homepage section h2 scale,
     see the matching note at .process/.meet__intro/.close below. */
  font-size: clamp(1.7rem, 2.25vw, 2.7rem);
  line-height: 1.12;
  letter-spacing: -0.028em;
  margin: 0 0 clamp(1.5rem, 2.2vw, 2rem);
}


/* --- The workbook CTA (practice pages) ------------------------------------ */
/* Shown only while site.json's intakeLive is true (work.njk). Sits between
   "What we help with" and the process band, so it reads as an extra route in
   rather than interrupting the fee-before-commitment promise that follows. */
.intake-band {
  padding: clamp(2.5rem, 4vw, 3.5rem) 0;
  /* A butter section bar rather than the aqua hairline every other boundary
     uses. --pl-butter's own note in the token block reads "section bars,
     highlights", and this band is the page's one do-this-now moment - the
     workbook. A 3px rule marks it without tinting 358px of ground, which is
     the loudness that got the peach card band reverted on 08-19. */
  border-top: 3px solid var(--pl-butter);
}
.intake-band h2 { max-width: 30ch; }
.intake-band__lede {
  max-width: 52ch;
  margin: 0.75rem 0 0;
  color: var(--pl-ink-soft);
}

/* --- 3. The process ------------------------------------------------------ */
/* Direction 2 migration, stage 1 (2026-09-20): white ground, per the "every
   section ground stays white" rule in MIGRATION-D2.md. The blush/cream note
   below is now historical - .home .process already carried this to white on
   2026-08-21 (see that rule further down), and this class is homepage-only
   (unlike .areas), so raising it here is safe. One hairline replaces the old
   top-and-bottom pair, matching /labs/polish; no more doubling up. */
.process {
  /* Blush (Chad, 2026-08-17), superseding the cream trialled 2026-08-04. A
     white ground was also tried then and reverted: without a tint the band
     merges with the white team section and the page loses its rooms. Blush
     keeps the room and warms it. Hairlines in the blush family. */
  background: #fff;
  border-top: 1px solid color-mix(in srgb, #0E6B80 16%, transparent);
  border-bottom: 0;
  padding-block: var(--pl-section-air);
}
[data-style="shapes"] .process { background: #FBEFE7; border-color: #EBCFBC; }
[data-style="shapes"] .steps__n, [data-style="shapes"] .steps__note { background: #FBEFE7; }
[data-style="shapes"] .steps__stamp { background: #fff; }
/* 26ch wrapped "Out" onto its own line once the title went Title Case
   (2026-08-17); 34ch keeps it on one line at every desktop width. */
.process > .pl-wrap > h2 { max-width: 34ch; margin-bottom: clamp(1.75rem, 2.8vw, 2.5rem); }
/* Three across. The numerals were always the point - the sequence IS the
   information here - but stacked they read as a list. Side by side they read
   as a path, which is what the section is describing. */
.steps {
  --step-gap: clamp(1.75rem, 3.5vw, 3rem);
  /* Where the numeral's centre sits inside its column. 1.3rem is half the
     2.6rem disc, i.e. hard left, which is the practice-page default. The
     homepage overrides it to 50%. The connector, the envelope and the stamp
     all position off this one value, so they cannot drift apart. */
  --step-anchor: 1.3rem;
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--step-gap);
}
.steps li { margin: 0; position: relative; }
.steps__n {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  font-family: var(--pl-font-display);
  font-weight: 600;
  font-size: 1.05rem;
  line-height: 1;
  color: var(--pl-accent-text);
  border: 2px solid var(--pl-accent-text);
  border-radius: 50%;
  /* the section ground, so the connector appears to pass behind the numeral
     rather than collide with it */
  background: var(--pl-card);
  margin-bottom: 1.1rem;
  position: relative;
  z-index: 1;
}
/* The connector. Each step draws to the NEXT one, so the last step has nothing
   trailing off its right edge.

   1px like every other rule on the page, but CORAL rather than aqua. Aqua on
   this cream ground is 1.39:1, which is invisible at any weight - that was why
   nothing appeared to be happening here. Coral is 4.74:1 and matches the
   numeral rings it joins, so the three steps read as a path rather than as a
   list, without the line thickening into something louder than a rule. */
.steps li:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 1.3rem;
  left: calc(var(--step-anchor) + 1.6rem);
  width: calc(100% + var(--step-gap) - 3.2rem);
  height: 1px;
  background: var(--pl-accent-text);
}
/* The draw, rebuilt 2026-08-04 the way the note left by its failed
   scroll-timeline predecessor prescribed: an IntersectionObserver in main.js
   ("The process") adds .is-run once when the band scrolls into view, and
   every element below choreographs itself off that single class with
   transition delays. No animation-timeline anywhere.

   Progressive by construction: without JS (or with reduced motion) .steps
   never gets .steps--armed, so nothing is ever hidden and step 1 is filled
   from the start. The cascade: numeral 1 pops, the line draws to 2, 2 pops,
   line draws to 3, 3 pops, then numeral 1 fills solid coral - "you are
   here": the visitor reading this section is by definition standing at
   step 1, so the fill quietly says the rest is what happens next. */

/* "You are here": step 1 filled - the resting truth, with or without JS */
.steps li:first-child .steps__n {
  background: var(--pl-accent-text);
  color: #fff;
}

/* Armed (JS + motion allowed): everything starts unpainted */
.steps--armed .steps__n {
  opacity: 0;
  scale: 0.6;
}
.steps--armed li:first-child .steps__n {
  background: transparent;
  color: var(--pl-accent-text);
}
.steps--armed li:not(:last-child)::after {
  transform: scaleX(0);
  transform-origin: left center;
}

/* The run. Delays stagger the choreography off one class flip. */
.steps--armed.is-run .steps__n {
  opacity: 1;
  scale: 1;
  transition: opacity 400ms ease, scale 480ms cubic-bezier(0.34, 1.45, 0.64, 1);
}
.steps--armed.is-run li:nth-child(2) .steps__n { transition-delay: 850ms; }
.steps--armed.is-run li:nth-child(3) .steps__n { transition-delay: 1700ms; }
.steps--armed.is-run li:not(:last-child)::after {
  transform: scaleX(1);
  transition: transform 560ms cubic-bezier(0.4, 0, 0.2, 1);
}
.steps--armed.is-run li:nth-child(1)::after { transition-delay: 380ms; }
.steps--armed.is-run li:nth-child(2)::after { transition-delay: 1280ms; }
.steps--armed.is-run li:first-child .steps__n {
  background: var(--pl-accent-text);
  color: #fff;
  transition:
    opacity 400ms ease, scale 480ms cubic-bezier(0.34, 1.45, 0.64, 1),
    background 300ms ease 2250ms, color 300ms ease 2250ms;
}

/* The note. The visitor's own message rides the line as it draws: fades in
   at numeral 1 as the first connector starts (380ms), lands at 2 as it
   pops, waits out the stamp, rides the second connector to 3, and slips
   away. It lives inside li 1, so left:100% is exactly one column and the
   hop maths follow --step-gap automatically. Animating left is layout
   work, but it is one 2.1s run per visit. Motion-gated: without .is-run
   the note never exists visually, and reduced-motion never arms it. */
.steps__note {
  position: absolute;
  top: 1.3rem;
  left: calc(var(--step-anchor) - 0.6rem);
  width: 1.35rem;
  height: 1.35rem;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--pl-accent-text);
  background: var(--pl-card);
  transform: translateY(-50%);
  opacity: 0;
  z-index: 2;
  pointer-events: none;
}
.steps--armed.is-run .steps__note { animation: note-ride 2100ms linear both; }
@keyframes note-ride {
  0%    { opacity: 0; left: calc(var(--step-anchor) - 0.6rem); }
  14%   { opacity: 0; left: calc(var(--step-anchor) - 0.6rem); }
  18.1% { opacity: 1; left: calc(var(--step-anchor) - 0.6rem); animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); }
  44.8% { left: calc(100% + var(--step-gap) + var(--step-anchor) - 0.6rem); animation-timing-function: linear; }
  61%   { left: calc(100% + var(--step-gap) + var(--step-anchor) - 0.6rem); animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); }
  87.6% { left: calc(200% + var(--step-gap) * 2 + var(--step-anchor) - 0.6rem); opacity: 1; }
  100%  { left: calc(200% + var(--step-gap) * 2 + var(--step-anchor) - 0.6rem); opacity: 0; }
}

/* The stamp. The band's one competitor-proof promise - an answer AND a
   price before commitment - stamps in beside numeral 2 the moment the
   note lands there (~1s into the cascade), with the same overshoot the
   numerals pop with. It stays once placed. */
.steps__stamp {
  position: absolute;
  top: -1.7rem;
  left: calc(var(--step-anchor) + 1.4rem);
  font-family: var(--pl-font-display);
  font-weight: 600;
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  white-space: nowrap;
  /* Back to the brand coral at Chad's call (2026-08-21). It measures 4.34:1
     on this blush at 11.5px, just under the 4.5:1 AA floor for small text -
     the darker #8a4a35 that .pl-tag--peach uses cleared it at 5.98:1 but read
     muddy against the coral the rest of the band is drawn in. Knowingly held.
     The claim itself is in the h3 underneath at 12.42:1, so nothing here is
     the only carrier of anything. If it ever needs to clear AA without losing
     the pigment, white behind the pill puts the same coral at 4.90:1. */
  color: var(--pl-accent-text);
  background: #FBEFE7;
  border: 1px solid #EBCFBC;
  border-radius: 6px;
  padding: 0.3rem 0.6rem;
  transform: rotate(-3deg);
  /* Visible by default, the same way the numerals and the connector are: only
     .steps--armed hides it, and main.js adds that class solely when JS runs
     and motion is allowed. Before this it was opacity:0 in the base rule, so
     reduced-motion and no-JS visitors never saw it at all. The claim itself is
     in the h3 underneath and was never lost - this tag is its emphasis. */
  opacity: 1;
  pointer-events: none;
}
.steps--armed .steps__stamp { opacity: 0; }
.steps--armed.is-run .steps__stamp {
  animation: stamp-in 300ms cubic-bezier(0.34, 1.45, 0.64, 1) 1020ms both;
}
@keyframes stamp-in {
  from { opacity: 0; transform: rotate(-3deg) scale(1.7); }
  to   { opacity: 1; transform: rotate(-3deg) scale(1); }
}

@media (max-width: 780px) {
  /* Stacked steps have no connector to ride and no headroom for the tag. */
  .steps__note, .steps__stamp { display: none; }
}

/* The clip-on-bubble beat was built and removed same day (2026-08-13,
   Chad: envelope yes, wire clip no). If bubble decoration ever comes up
   again, it was a coral clip ::after rotating onto the sheet corner -
   do not re-pitch it. */

/* The homecoming. The envelope drifts in once (.close.is-home, set by
   main.js when the band scrolls into view) and perches on the send
   button's shoulder. Invisible at rest and under reduced motion, which
   never sets the class. */
.close .pl-btn--primary,
.ask .pl-btn--primary { position: relative; }
/* The hero's twin: same badge, no animation - the envelope simply lives
   on the button that writes the note, from the first paint. Doubled class
   so it outranks the base glyph's opacity:0, which is defined later. */
.btn__glyph.btn__glyph--still { opacity: 1; transform: rotate(8deg); }
.btn__glyph {
  position: absolute;
  top: -11px;
  right: -9px;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--pl-accent-text);
  background: var(--pl-card);
  border: 1px solid #EBCFBC;
  border-radius: 6px;
  padding: 3px;
  opacity: 0;
  pointer-events: none;
}
.close.is-home .btn__glyph { animation: note-home 700ms cubic-bezier(0.22, 1, 0.36, 1) 250ms both; }
@keyframes note-home {
  from { opacity: 0; transform: translate(-30px, -38px) rotate(-16deg); }
  60%  { opacity: 1; }
  to   { opacity: 1; transform: translate(0, 0) rotate(8deg); }
}

.steps h3 { font-size: 1.02rem; margin: 0 0 0.35rem; }
.steps p { margin: 0; max-width: none; font-size: 0.94rem; }

@media (max-width: 780px) {
  .steps { grid-template-columns: 1fr; gap: 1.5rem; }
  /* No connector once they stack: a vertical line through three numerals of
     different content heights needs per-item measuring to look right, and it
     earns nothing on a phone. */
  .steps li:not(:last-child)::after { content: none; }
  .steps__n { width: 2.3rem; height: 2.3rem; margin-bottom: 0.8rem; }
}

/* --- 4. Who you would be dealing with ------------------------------------ */
/* Direction 2 migration, stage 1 (2026-09-20): more air, one hairline on
   top, matching /labs/polish. This class is also /team/'s section (see
   team-index.njk), which was already an unbordered white band, so the new
   hairline is the only visible change there. */
.meet {
  padding-block: var(--pl-section-air);
  border-top: 1px solid color-mix(in srgb, #0E6B80 16%, transparent);
}
.meet__intro { max-width: 52ch; margin-bottom: clamp(2rem, 3.2vw, 2.75rem); }
.people { display: grid; gap: clamp(1.5rem, 3vw, 2.5rem); }
/* min(Npx, 100%) rather than a bare minmax floor: a 320px minimum is wider
   than the 261px available inside the gutters on a 320px screen, so the track
   was forced past the viewport and the whole page scrolled sideways. */
/* The two lawyers centred as a pair; the five file-movers spread the full
   band width below them (Chad's call 2026-08-04) - hierarchy by placement:
   the people you hire sit at centre stage, the team that keeps your file
   moving forms the row beneath. Columns stay capped so nobody stretches. */
.people--lead {
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 440px));
  justify-content: center;
  margin-bottom: clamp(2rem, 3.5vw, 3rem);
}
/* Above the stacking breakpoint the cards size to their own content instead
   of to a 440px track (Chad, 2026-08-21: "a little left oriented", and he was
   right - measured 94px). A lawyer card is a 112px portrait plus a name and a
   role, about 260px of ink, and the tagline is visually hidden on
   hover-capable devices, so a 440px track left ~180px of dead space on each
   card's right. The tracks centred; the ink did not. Flex here rather than a
   content-sized grid track: repeat() cannot take max-content in an auto
   repeat, and hard-coding repeat(2, ...) would rot the moment the roster
   gains a third lawyer through the CMS. Same reasoning as .people--support. */
@media (min-width: 901px) {
  .people--lead {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    /* Wider than the 1.5rem inside a card, so the two read as two people
       rather than one long row of photo-name-photo-name. */
    column-gap: clamp(2.5rem, 5vw, 4.5rem);
  }
}
.people--support {
  /* Grid after all, but NOT the shape the old comment here ruled out. That
     objection was to auto-fit plus space-between, where the collapsed phantom
     track's gap pushed the last card off the right edge. With 1fr tracks there
     is no free space left for space-between to distribute: the filled tracks
     stretch and share the band evenly, the empty ones collapse to nothing, and
     the roster stays CMS-editable because the count is still derived.
     What space-between actually cost: at 1440 and 1280 the sixth person wrapped
     alone to the far left with ~1140px of empty band beside them, and at 375
     the 190px basis could not fit two across, so all six stacked one per row
     for 1150px of scroll. */
  display: grid;
  /* min(150px, 100%), never a bare 150px floor - the note at the top of this
     block has said so since the first build and I walked straight into it:
     a hard floor wider than the space inside the gutters forces the track past
     the viewport and the whole page scrolls sideways (measured 43px at 375). */
  /* Flex, not the auto-fit grid, and the reason is the orphan row. The note
     above solved space-between's version of this at 1440 and 1280, where all
     six fit on one line - but it never covered the tablet band. At 768 the
     band takes four tracks, so six people land 4 + 2 and grid left-aligns the
     remainder: measured, that last row sat 179px left of centre.

     1fr tracks are what forces the choice. They are why the row spreads the
     full band (Chad, 2026-08-04) and also why the orphans cannot be centred -
     a grid row cannot centre its own remainder. Flex can, because each line
     justifies independently, and the cards must NOT grow or the two orphans
     would inflate to half the band each while the row above stayed at 155.

     So the basis is fixed and every card is the same width on every line. It
     is set to the width the grid already produced at 1440 (188px, measured),
     so the desktop row is unchanged: six cards, one line, full band. Below
     that the basis clamps down and rows centre. Orphan-proof for any roster
     size, which the hard-coded column counts it replaces would not have been. */
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  margin-top: clamp(2rem, 4vw, 3rem);
  padding-top: clamp(2rem, 4vw, 3rem);
  border-top: 1px solid var(--pl-aqua);
}
/* The basis has to move, and a fixed 188px proves why: at 375 two cards will
   not fit across a 335px band, so all six stacked one per row - the exact
   1150px-of-scroll failure the note above records against space-between. The
   percentage is what fixes it, because it is read against the band: 45% of 335
   is 151 and two fit; by 692 the same 45% is past the cap and every card is
   186 again. Capped at 186 rather than the measured 188 so the desktop row
   keeps 13px of slack - at 188 it filled 1328 of 1329 and one pixel of drift
   in the gap would have wrapped the sixth person onto a line of her own. */
.people--support .person { flex: 0 1 clamp(140px, 45%, 186px); }
/* Above this the grid comes back, unchanged, and the reason is a real trade
   rather than a preference. Uniform card widths, rows that fill the band, and
   a centred remainder cannot all hold at once: a fixed basis gives uniform and
   centred but cannot shrink to fit, so at 1280 it dropped to five and one,
   where the grid had been fitting all six on a line. 1fr can shrink, which is
   why the wide row keeps it - measured, six cards at 163 across 1169.
   1200 is where the grid first fits six (6 x 150 floor + 5 gaps against the
   band), so above it there is no remainder to centre and nothing to fix. */
@media (min-width: 1200px) {
  .people--support {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
  }
  .people--support .person { flex: none; }
}
/* align-content:start is load-bearing. Each card is a grid item that stretches
   to the row height, and its own rows then stretch to fill, so cards with
   shorter blurbs pushed their name and photo to different baselines across the
   row. Two of the five have no bio at all, which made the stagger obvious. */
.person { display: grid; align-content: start; text-decoration: none; color: inherit; }
/* start, not center: the two blurbs are different lengths, and centring each
   against its own photo put the two names on visibly different baselines
   across the row. */
.people--lead .person {
  grid-template-columns: auto 1fr;
  gap: 1.5rem;
  align-items: start;
}
.person__photo { border-radius: 50%; object-fit: cover; background: var(--pl-peach); }
.people--lead .person__photo { width: 112px; height: 112px; }
.people--support .person__photo { width: 64px; height: 64px; margin-bottom: 0.65rem; }
.people--support .person { min-width: 0; }
.person__photo--empty { display: block; }
.person__meta { display: block; }
.person__name {
  display: block;
  font-family: var(--pl-font-display);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--pl-logo);
  transition: color 160ms ease;
}
.people--lead .person__name { font-size: 1.08rem; }
.people--support .person__name { font-size: 0.94rem; }
.person:hover .person__name { color: var(--pl-accent-text); }
.person__role {
  display: block;
  /* Direction 2 migration, stage 1 (2026-09-20): raised to the 13px floor. */
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--pl-ink-soft);
  margin: 0.3rem 0 0.45rem;
}
.person__line { display: block; font-size: 0.9rem; color: var(--pl-ink-soft); max-width: 42ch; }
.people--support .person__line { font-size: 0.85rem; }

.person__photo { transition: box-shadow 200ms ease; }
/* NOW DEAD, removed 2026-09-20 (Direction 2 migration cleanup): .person__figure
   and the .person__bubble speech-bubble family (the discoverability badge,
   the hover-pop rules, the touch open/close variant) - the pre-migration
   homepage was the only page that ever nested a .person__bubble inside a
   .person, and src/_includes/home/team-block.njk (stage 4) replaced that
   markup, so .person__figure:has(.person__bubble) can never match anywhere on
   the site any more. /team/'s own cards (team-index.njk) never emitted this
   wrapper either. The .person:hover/.focus-visible .person__photo ring below
   is real, current /team/ behaviour and stays; so does .person__line's
   screen-reader-only treatment on hover-capable and touch devices, which is
   unconditional (not gated on the bubble) and therefore still live. */
@media (hover: hover) and (pointer: fine) {
  .person__line {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .person:hover .person__photo,
  .person:focus-visible .person__photo {
    box-shadow: 0 0 0 3px var(--pl-accent);
  }
}
@media (hover: none) {
  .person__line {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

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

/* Section 5 was the testimonials band. Removed 2026-08-04 with its markup;
   /kind-words/ has its own .testimonial-grid styles and is unaffected. */

/* --- 6. The close -------------------------------------------------------- */
.close {
  /* Plain white (Chad's call 2026-08-04): the aqua band, then an inset card
     in aqua/cream/white were all trialled and dropped.
     Direction 2 migration, stage 1 (2026-09-20): the process band's border-
     bottom that used to carry the boundary above is gone (it doubled up with
     this section's own hairline) - .close now carries its own border-top,
     same as the other three rooms. Air raised to match. */
  background: #fff;
  text-align: center;
  padding-block: var(--pl-section-air);
  border-top: 1px solid color-mix(in srgb, #0E6B80 16%, transparent);
}
body:has(.close) .site-footer { margin-top: 0; }
.close h2 { margin-bottom: 0.4em; }
.close__lede { font-size: 1.02rem; color: var(--pl-logo); max-width: 46ch; margin: 0 auto 2rem; }
.close__actions { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center; }
.close .pl-btn--outline { background: rgba(255, 255, 255, 0.55); }
.close__note {
  margin: 1.75rem auto 0;
  max-width: 46ch;
  font-size: 0.92rem;
  color: var(--pl-logo);
}
.close__where { margin: 1rem 0 0; font-size: 0.92rem; color: var(--pl-logo); }
.close__where a {
  color: var(--pl-logo);
  font-weight: 700;
  text-decoration: none;
  border-bottom: 1px solid rgba(0, 50, 78, 0.35);
}

/* The header phone rules that used to sit here have moved up into the header
   block. They were written for the old flex bar and their margin-left:auto
   was the thing pushing the number into the middle of it; left here they
   would also have won on the cascade against the new grid. */

@media (max-width: 900px) {
  .people--lead .person { grid-template-columns: 1fr; gap: 0.85rem; }
  /* Side by side everywhere below desktop (Chad, 2026-08-25). They stacked
     before because the tagline sat inline and needed a 320px floor; it lives
     in the tapped bubble now, so a card is a portrait, a name and a role.

     Centred flex rather than auto-fit, because auto-fit counts repetitions
     using the track's MAX when that max is definite: minmax(320px, 440px) asks
     whether two 440s fit and returns one track, which is why 768 was still
     stacking two 440px cards. Measured, not assumed.

     The basis is a percentage so it tracks the band: 45% is 151 across a 335
     phone and 311 on a tablet, capped at 300 so two never sprawl. Flex also
     leaves free space for justify-content, so a third lawyer would centre
     under the pair instead of orphaning left. */
  .people--lead {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
  }
  .people--lead .person { flex: 0 1 clamp(150px, 45%, 300px); }
}
/* The two lawyers go side by side on a phone (Chad, 2026-08-25). They could
   not before: the card carried its tagline inline, so a 320px minimum track
   was the floor and only one fit across 335. The tagline lives in the tapped
   bubble now, which leaves a portrait, a name and a role - about 150px of it.

   auto-fit with a cap, not repeat(2, ...): this file already records that
   hard-coding two rots the moment the roster gains a third lawyer through the
   CMS. A capped track also leaves free space for justify-content:center on
   .people--lead to distribute, so a third would centre under the pair rather
   than orphan itself against the left edge the way the support row used to.

   96px portrait rather than 112: two 112s plus the gap come to 248 of a 335
   band and the name had nowhere to go. */
@media (max-width: 640px) {
  /* 96px rather than 112: two 112s plus the gap come to 248 of a 335 band and
     the name had nowhere to go. Phones only - a tablet has room for the full
     portrait. */
  .people--lead .person__photo { width: 96px; height: 96px; }
  .steps li { grid-template-columns: 1fr; gap: 0.5rem; }
  .close__actions .pl-btn { width: 100%; }
}

/* Homepage section headings sit a full step below the global display h2.
   The flatness complaint was about dynamic range, not size: at 2.6rem every
   band shouted equally, which reads as bulk rather than as clean.
   Direction 2 migration, stage 1 (2026-09-20): rescaled again to match
   /labs/polish's picked values now that the display face is Bricolage
   Grotesque rather than Montserrat - the old clamp was tuned for the old
   face and read small next to Instrument Serif in the hero above it. */
.process > .pl-wrap > h2,
.meet__intro h2 {
  font-size: clamp(1.7rem, 2.25vw, 2.7rem);
  line-height: 1.12;
  letter-spacing: -0.028em;
}
.close h2 {
  font-size: clamp(1.9rem, 2.6vw, 3.1rem);
  line-height: 1.1;
  letter-spacing: -0.03em;
}

/* ---------------------------------------------------------------------------
   Templates store
   --------------------------------------------------------------------------- */

/* Shown while site.storeLive is false. Deliberately loud: Elizabeth reviews
   this page with invented prices on it, and a quiet caption would be missed. */
.store-notice {
  margin: 1.5rem 0 0;
  padding: 1rem 1.15rem;
  border: 1px solid var(--pl-accent-text);
  border-left: 4px solid var(--pl-accent-text);
  background: var(--pl-card);
  max-width: 62ch;
}

.store-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 420px));
  gap: clamp(1.25rem, 2.5vw, 2rem);
  margin-top: 2rem;
}
.store-card {
  display: flex;
  flex-direction: column;
  padding: 1.9rem 1.7rem 1.6rem;
  /* var(--pl-cream) was a token that never existed - cards rendered
     transparent. Now the same cream card language as the homepage doors. */
  background: var(--pl-card);
  border: 1px solid var(--pl-aqua);
  border-radius: var(--pl-radius-card);
  box-shadow: var(--pl-shadow);
  transition: box-shadow 260ms ease;
}
.store-card:hover {
  box-shadow: 0 2px 3px rgba(26, 26, 26, 0.05), 0 12px 24px rgba(26, 26, 26, 0.10);
}
.store-card__cat {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--pl-accent-text);
  margin-bottom: 0.5rem;
}
.store-card h2 {
  font-size: clamp(1.1rem, 1.6vw, 1.3rem);
  letter-spacing: -0.3px;
  line-height: 1.3;
  margin: 0 0 0.5rem;
}
.store-card h2 a { text-decoration: none; }
.store-card__summary { font-size: 0.95rem; margin: 0 0 1.25rem; }
.store-card__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  margin: auto 0 0;
}
.store-card__price { font-size: 1.35rem; font-weight: 800; }
.store-card__cur { font-size: 0.8rem; font-weight: 400; color: var(--pl-ink-soft); }

/* Product page: body and buy panel side by side, stacking on narrow screens.
   The panel is sticky on desktop so the price stays visible down a long page. */
.product {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 2.5rem;
  align-items: start;
  margin-top: 1.5rem;
}
.product__body > :first-child { margin-top: 0; }
.product__includes { margin: 0; }
.product__includes li { margin-bottom: 0.4rem; }
.product__buy {
  position: sticky;
  top: 1.5rem;
  padding: 1.5rem;
  background: var(--pl-card);
  border: 1px solid var(--pl-aqua);
  border-radius: var(--pl-radius-card);
}
.product__price { font-size: 2rem; font-weight: 800; margin: 0 0 1rem; line-height: 1; }
.product__cur { font-size: 0.85rem; font-weight: 400; color: var(--pl-ink-soft); }
.product__cta { width: 100%; }
.product__cta[disabled] { opacity: 0.45; cursor: not-allowed; }
.product__note {
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--pl-ink-soft);
  margin: 0.85rem 0 0;
}
.product__note--legal { padding-top: 0.85rem; border-top: 1px solid var(--pl-aqua); }

@media (max-width: 860px) {
  .product { grid-template-columns: 1fr; gap: 1.75rem; }
  .product__buy { position: static; }
}

.download-panel { margin: 1.5rem 0 2rem; max-width: 62ch; }
.download-panel__note { font-size: 0.85rem; color: var(--pl-ink-soft); margin-bottom: 0; }
.download-panel .pl-btn { margin-bottom: 1rem; }
.download-error { color: var(--pl-accent-text); font-weight: 700; }

/* A product whose document has not been uploaded yet. Normal when a new
   template is being added: the product has to exist before we know what to
   call the file. */
.store-card__soon {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 700;
  /* var(--pl-accent-text) (#C64438) on this peach only clears 3.7:1 - the
     same darker tone .pl-tag--peach already uses on the same background,
     which clears 4.5:1. */
  color: #8a4a35;
  background: var(--pl-peach);
  padding: 0.25rem 0.6rem;
  border-radius: 20px;
}


/* ---------------------------------------------------------------------------
   The centred homepage (2026-08-21)
   ---------------------------------------------------------------------------
   Elizabeth's one verdict on the design so far, by text: "I like the centered
   layout." /labs/hero-4b/ is promoted to the default here.

   Layout only. No colour and no decoration travels with it - the colour menu
   is still hers to order from, and the door cards stay in the video state.

   Practice pages are untouched: they carry .ask--work and never render
   .ask__grid, and the section rules below are gated on the homepage's own
   body class.

   Scoped one level deeper than the base hero rules on purpose. .ask h1 and
   .ask__lede sit earlier in this file at (0,1,1) and (0,1,0) and are shared
   with work.njk. Matching their specificity would leave the winner decided by
   source order, which is exactly how the peach band and the help-set both
   silently lost on 08-19. These are (0,2,x), so they win outright.
   --------------------------------------------------------------------------- */
/* An explicit measure, not fit-content (Chad, 2026-08-21: "lock it").
   margin-inline:auto on a grid item defeats justify-self:stretch, so this
   column used to size itself to the h1's max-content - it measured 944.328px
   at 1920, 1440 AND 1280 because that is simply how wide her headline renders.
   Editing that sentence in the CMS silently recomposed the hero. Capped here,
   a longer headline wraps to two balanced lines instead, which also brings
   text-wrap:balance on .ask h1 back to life. */
.ask__grid .ask__words { width: min(100%, 960px); margin-inline: auto; text-align: center; }
/* The sentence and the two ways to reach us, now under the film. */
.ask__tail { text-align: center; margin: 2.5rem auto 0; width: min(100%, 960px); }
.ask__tail .ask__lede { margin-top: 0; }
.ask__grid .ask__eyebrow { justify-content: center; }
/* The headline drops its 17ch measure and takes the whole wrap: one line at
   desktop width, a balanced pair below that. text-wrap: balance on the base
   rule still does the breaking. */
.ask__grid .ask__words h1 { max-width: none; margin-inline: auto; }
/* Instrument Serif, regular, its <em> italic - matching html[data-hero=
   "instrument"] in direction-2.njk (Direction 2 migration, stage 1,
   2026-09-20). .ask__grid only exists in index.njk, so this is the real
   homepage h1 and nothing else: work.njk's .ask--work hero (and every other
   page's h1) keeps Playfair from the base h1 rule, untouched. Georgia
   fallback rather than Playfair's - the two serifs don't share a fallback
   story. Font-size is left at the clamp set on the shared .ask h1 rule
   above; the spec calls out letter-spacing and line-height to match the
   lab, not size. */
.ask__grid .ask__words h1 {
  font-family: 'Instrument Serif', Georgia, serif;
  font-weight: 400;
  line-height: 1.04;
  letter-spacing: -0.01em;
}
.ask__grid .ask__words h1 em { font-style: italic; font-weight: 400; }
/* 42ch was a measure for a half-width column. Centred under a full-width
   headline it reads as a stub, so it relaxes. */
.ask__grid .ask__lede { max-width: 58ch; margin-inline: auto; }
.ask__grid .ask__actions { justify-content: center; }
/* Out of the old 560px column and into the page's centrepiece. 1132px is
   under twice the footage's native 640px, so the upscale stays soft. */
.ask__grid .ask__film { max-width: 1132px; width: 100%; margin: 3rem auto 0; }
/* The film had no elevation at all - no shadow, no border, nothing - which
   made the biggest object on the page the only one lying flat on the white
   while every card, chip and button around it sat above it.

   Deeper and wider than --pl-shadow on purpose: shadow has to scale with the
   thing casting it, and the card token was drawn for a 420px card, not for
   1132x637. Neutral rather than tinted, because this is photographic content -
   the coloured shadows on this page belong to coloured objects.

   The third layer is a hairline ring rather than a border: it defines the edge
   against white when a frame is bright, and costs no layout. */
.ask__grid .ask__film video {
  box-shadow:
    0 2px 6px rgba(26, 26, 26, 0.06),
    0 18px 50px rgba(26, 26, 26, 0.16),
    0 0 0 1px rgba(26, 26, 26, 0.06);
  transition: transform 420ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 420ms ease;
}

/* --- Theatre (2026-08-21) -------------------------------------------------
   Press play and the page dims while the film lifts out of it. Wired in
   main.js ("Theatre"). Exits on Escape, on a scrim click, and when the film
   ends; exiting pauses, the way closing a lightbox is expected to.

   80 and 90 sit above the sticky header (50) and the parked film bubble (70)
   but below the skip link (100), which must stay reachable, and the boot
   curtain (200), which owns page load. */
.theatre-scrim {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: rgba(8, 22, 28, 0.84);
  opacity: 0;
  pointer-events: none;
  transition: opacity 340ms ease;
  cursor: zoom-out;
}
html.is-theatre .theatre-scrim { opacity: 1; pointer-events: auto; }
html.is-theatre .ask__film { position: relative; z-index: 90; }
html.is-theatre .ask__grid .ask__film video {
  /* 1.04, not more. The source is 640x360 shown at 1132 - already a 1.77x
     upscale - and scaling further to sell the effect would spend real
     sharpness on it. The dim and the shadow do the work instead. */
  transform: scale(1.04);
  box-shadow:
    0 10px 30px rgba(0, 0, 0, 0.38),
    0 40px 90px rgba(0, 0, 0, 0.50),
    0 0 0 1px rgba(255, 255, 255, 0.10);
}

@media (prefers-reduced-motion: reduce) {
  /* The dim still happens - it is the point, and it is not motion. The lift
     and the fades do not. */
  .theatre-scrim { transition: none; }
  .ask__grid .ask__film video { transition: none; }
  html.is-theatre .ask__grid .ask__film video { transform: none; }
}
/* Below roughly 1324px the 1132 cap insets the film by less than the page's
   own 48px gutter - at 1280 it sat 19px off every other element's left edge,
   which reads as a mistake rather than as a narrower element. Past that point
   it takes the full wrap and shares the edge. */
@media (max-width: 1324px) {
  .ask__grid .ask__film { max-width: none; }
}

/* ===========================================================================
   Direction 2 migration, stage 2 (2026-09-20): the hero poster.
   Source of truth: MIGRATION-D2.md + scripts/make-polish-lab.mjs (search
   "hero experiments", "poster", "wash", "iris"). Lab picks, baked as real
   code with no lab switches: x=poster (headline on the film, no sheet of
   paper over it) + t=wash (a paper tint; the headline keeps the page's own
   navy/coral ink, not a brand hue) + o=iris (the wash opens from the play
   button on click) + a=still (no ambient loop - the poster frame sits under
   the wash until play).

   Homepage only. .ask__words/.ask__film/.ask__grid only exist on index.njk -
   work.njk's .ask--work hero never renders them - so this block does not
   touch the practice pages, which is also why it can reuse the plain
   .ask__grid selectors already used above rather than needing a .home hook.

   The play control: the old centred disc in .film__frame is gone. It moved
   onto the overlay as .hero-play (index.njk), which is now the ONE
   accessible play control - see the comment there for why a second, hidden
   control was rejected. .film__cta and its breathing-ring keyframe below are
   now unused; left in place since nothing else references them and this
   stage only adds, per the migration plan (see the stage log's dead-code
   note). */
@property --iris { syntax: '<length>'; inherits: true; initial-value: -100px; }
@property --pop { syntax: '<number>'; inherits: true; initial-value: 1; }

/* The overlap: words and film share one grid cell, so the headline sits ON
   the film rather than above it. */
.ask__grid .ask__words,
.ask__grid .ask__film {
  grid-area: 1 / 1;
  width: min(100%, 1100px);
  max-width: none;
  margin: 0 auto;
}
.ask__grid .ask__film { margin-top: 0; }
/* The frame also listens to the screen HEIGHT past 900px, so a short laptop
   window never pushes "Send Us a Note" below the fold: the width is capped
   by what a 16:9 crop can afford at (100svh - 345px) tall. Below 901 the
   frame goes portrait instead (see the phone/tablet aspect-ratio rules
   further down), so no height cap applies there. */
@media (min-width: 901px) {
  .ask__grid .ask__words,
  .ask__grid .ask__film {
    width: min(100%, 1100px, calc((100svh - 345px) * 1.7778));
  }
}

/* The wash: the overlay itself, stretched to the film's full height by grid
   stretch (the row's auto height comes from the taller item, the film). */
.ask__grid .ask__words {
  position: relative;
  z-index: 3;
  align-self: stretch;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0;
  border-radius: var(--pl-radius-card);
  background: linear-gradient(180deg, rgba(255, 250, 244, .86) 0%, rgba(253, 243, 233, .74) 100%);
  padding: 2.25rem 1.5rem;
  cursor: pointer;
  /* --pop scales the overlay in lockstep with the video's own 1.04 theatre
     lift (same duration and curve as .ask__grid .ask__film video below), so
     the wash's edge never shows past the film's during the lift. */
  transform: scale(var(--pop));
  /* The iris: a radial mask centred on the play cue, grown from JS via
     --cx/--cy (main.js, "Hero poster: the play cue"). 90px feather; 760px is
     the farthest corner of the 1100x619 frame from the button, plus the
     feather. */
  --cx: 50%;
  --cy: 64%;
  -webkit-mask-image: radial-gradient(circle at var(--cx) var(--cy), transparent var(--iris), #000 calc(var(--iris) + 90px));
  mask-image: radial-gradient(circle at var(--cx) var(--cy), transparent var(--iris), #000 calc(var(--iris) + 90px));
  transition: --iris 900ms cubic-bezier(0.55, 0, 0.3, 1), --pop 420ms cubic-bezier(0.22, 1, 0.36, 1);
}
.ask__grid .ask__eyebrow {
  position: absolute;
  top: 2.25rem;
  left: 0;
  right: 0;
  margin: 0;
  justify-content: center;
}
.ask__grid .ask__words h1 {
  max-width: 880px;
  font-size: clamp(3.2rem, 4.5vw, 5.4rem);
  color: #00324E;
  text-wrap: balance;
}
.ask__grid .ask__words h1 em { color: var(--pl-accent-text); }

/* The play cue: a brick disc with a white glyph, "Play the film" beside it -
   the .sheet__hint language from the lab, built as a real button here. */
.hero-play {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: .9rem;
  margin-top: 2.4rem;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  font: 800 .8125rem var(--pl-font-body);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #00324E;
  transition: opacity 220ms ease, transform 220ms cubic-bezier(0.34, 1.45, 0.64, 1);
}
.hero-play__disc {
  display: grid;
  place-items: center;
  flex: none;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--pl-accent-text);
  box-shadow: 0 10px 26px rgba(0, 50, 78, .28);
  transition: transform 200ms ease;
}
.hero-play__disc svg { width: 24px; height: 24px; color: #fff; margin-left: 3px; }
.ask__grid .ask__words:hover .hero-play__disc,
.hero-play:focus-visible .hero-play__disc { transform: scale(1.08); }
.hero-play:focus-visible { outline: 3px solid #0E6B80; outline-offset: 4px; border-radius: 999px; }
/* Pressed: collapse as the film takes over (main.js adds .is-going, the same
   class name .film__cta used for this). */
.hero-play.is-going { transform: scale(.4); opacity: 0; pointer-events: none; }

/* Hide the runtime badge and the wire while the overlay is still closed -
   they belong to the post-engage, native-controls state, and the wash
   already covers them, but a partial iris opening should never catch them
   mid-fade-in. */
html:not(.is-theatre) .ask__grid :is(.film__time, .film__wire) { opacity: 0; }

/* Theatre: the overlay opens instead of the old plain fade. Above the scrim
   (80) and the lifted film (90) so the iris can uncover it, and inert once
   open since the film itself is now the surface to click. */
html.is-theatre .ask__grid .ask__words {
  --iris: 760px;
  --pop: 1.04;
  z-index: 95;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  /* No growing circle: a plain fade, and no pop since there is no motion to
     match on the video's side either (its own reduced-motion rule above
     already drops the scale). */
  .ask__grid .ask__words {
    transition: opacity 200ms linear;
    -webkit-mask-image: none;
    mask-image: none;
  }
  html.is-theatre .ask__grid .ask__words { opacity: 0; }
  .hero-play, .hero-play__disc { transition: none; }
  .ask__grid .ask__words:hover .hero-play__disc,
  .hero-play:focus-visible .hero-play__disc { transform: none; }
}

/* Tablet, 701-900: the frame goes portrait-ish 3:2 rather than the 16:9 the
   desktop width formula assumes - at these widths 16:9 runs too short to
   hold the headline and the button both. */
@media (min-width: 701px) and (max-width: 900px) {
  .ask__grid .ask__film video { aspect-ratio: 3 / 2; object-fit: cover; }
  /* Film 1 is a type film: a 3:2 crop of its 16:9 frame clipped the widest
     line ("Sorting out your will and estate.") at both ends. Theatre shows
     the whole frame on tablets too, the way phones already do. */
  html.is-theatre .ask__grid .ask__film video { object-fit: contain; background: #08161c; }
}
/* Phone, <=700: 4:5, tall enough to hold the headline over one screen's
   width of film. Theatre keeps the same frame (nothing jumps) but switches
   to contain on a dark ground, since a 4:5 crop of 640x360 footage playing
   would otherwise crop the picture itself, not just the frame around it. */
@media (max-width: 700px) {
  .ask__grid .ask__film video { aspect-ratio: 4 / 5; object-fit: cover; }
  html.is-theatre .ask__grid .ask__film video { object-fit: contain; background: #08161c; }
  .ask__grid .ask__words h1 { font-size: clamp(2.1rem, 9.2vw, 3.4rem); }
}
/* Parity with the signed-off lab (2026-09-20): with the headline on the film the
   hero needs far less air above it, and a touch less under the frame. Missed in
   the first port: the button sat 48px lower than the lab at every width.
   .home scopes it to the homepage; the practice pages share .ask. */
.home .ask { padding-top: 2.25rem; }
.home .ask__tail { margin-top: 2rem; }
@media (max-width: 900px) {
  .home .ask { padding-top: 1rem; }
  .home .ask__tail { margin-top: 1.5rem; }
}
@media (min-width: 701px) and (max-width: 900px) {
  .ask__grid .ask__words h1 { font-size: clamp(2.6rem, 6.4vw, 3.6rem); }
}

/* ===========================================================================
   Direction 2 migration, stage 3 (2026-09-20): service wave cards.
   Source of truth: MIGRATION-D2.md + scripts/make-polish-lab.mjs (search
   "wave cards", "SOLID", "wavePath", "footPath", "card back: the same white
   card", "flat at rest"). Homepage only - .wcard/.wave-cards are new classes,
   not shared with work.njk's .area-cards, so nothing here needs a .home hook.

   2026-10-02, Elizabeth: "straight lines or a colour band". Chad picked the
   colour band for the cards: the wave SVGs and their gradients are gone, the
   front's foot (.wcard__fill) and the back's foot (.wcard__actions) are
   straight blocks in the card's fill colour with a lighter stripe on top.
   2026-10-02 later the same day: the lighter stripe is GONE everywhere (Chad: on a
   straight edge it read as a divider line, the kind Elizabeth asked to lose). Every
   "lighter stripe" mention below is history; the feet are one solid colour.
   The back is the same white card as the front, not a slab of the tone
   colour: title and service names in the card's TEXT ink (--w-text), a
   straight foot in the card's fill colour (--w-fill) holding two pills.
   Ink limits (MIGRATION-D2.md): teal card white on its front wave only,
   coral and butter cards navy. The butter card's front symbol and back text
   are butter-on-white (#FFD34D) - Chad's one sanctioned exception, 09-18.

   Two flip mechanisms, chosen once at load by main.js ("Wave cards") via
   matchMedia, partitioned below so neither needs !important to win: a wide,
   fine-pointer screen gets a true 3D flip that is FLAT AT REST (perspective
   and the rotateY transform exist only for the length of a flip - a
   permanent 3D layer rasterises visibly grainy even with vector paths).
   Everywhere else the html[data-flip="fade"] block crossfades instead: phone
   browsers proved unreliable at both backface-visibility and painting a
   hidden 3D layer in time, showing a mirrored title or a blank card. */
.home .areas__q {
  /* Finishes a stage 1 miss the parity check against the lab caught: every
     other homepage h2 got its polish margin-bottom, but .areas__q was left at
     the pre-polish clamp(1.5rem, 2.2vw, 2rem), making the whole .areas band
     12px shorter than /labs/polish/ at 1920 (4px at narrower widths). Scoped
     to .home: work.njk's practice-page "What We Help With" heading shares
     .areas__q and was never measured against this homepage-only lab, so it
     keeps its pre-existing spacing. */
  margin-bottom: clamp(1.75rem, 2.4vw, 2.75rem);
}
.wave-cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 3.5rem;
  align-items: stretch;
  padding: 1.5rem 0 2.5rem;
}
.wcard { --w-h: 500px; position: relative; height: var(--w-h); }
.wcard--teal   { --w-fill: #0E6B80; --w-light: #BFDDDE; --w-ink: #FFFFFF; --w-icon: #0E6B80; --w-text: #0E6B80; }
.wcard--coral  { --w-fill: #EE7A70; --w-light: #F6DBCA; --w-ink: #00324E; --w-icon: #C64438; --w-text: #C64438; }
.wcard--butter { --w-fill: #FFD34D; --w-light: color-mix(in srgb, #FFD34D 45%, #FFFFFF); --w-ink: #00324E; --w-icon: #FFD34D; --w-text: #FFD34D; }

.wcard__inner {
  position: relative; width: 100%; height: 100%;
  border-radius: 24px;
  box-shadow: 0 2px 6px rgba(26, 26, 26, .05), 0 18px 44px rgba(26, 26, 26, .10);
  transition: box-shadow 300ms ease, translate 300ms cubic-bezier(0.22, 1, 0.36, 1);
}
.wcard__front, .wcard__back {
  position: absolute; inset: 0; border-radius: 24px; overflow: hidden;
}
/* The front's colour band (.wcard__fill) is 12rem tall: tall enough for the
   estates card's tabs to wrap to two rows on a narrow card and still keep 14px+
   of solid colour above them. The symbol and title sit centred in the white above it. --wb-px is the back's side padding, kept
   in one place because the back's foot block bleeds out by exactly that much. */
.wcard__front { background: #fff; cursor: pointer; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 2.4rem 1.6rem 12rem; }
.wcard__back { --wb-px: 2rem; background: #fff; color: var(--pl-ink); padding: 2.1rem var(--wb-px) 0; display: flex; flex-direction: column; }
.wcard__back:focus { outline: none; }

/* Hover lift only where a pointer can actually hover; focus (keyboard) lifts
   everywhere. @media (hover: hover) means a phone tap never leaves a card
   stuck in its lifted state (there is no matching :hover to un-set it). */
@media (hover: hover) and (pointer: fine) {
  .wcard:hover .wcard__inner { translate: 0 -14px; box-shadow: 0 6px 14px rgba(26, 26, 26, .07), 0 30px 64px rgba(26, 26, 26, .16); }
}
.wcard:focus-within .wcard__inner { translate: 0 -14px; box-shadow: 0 6px 14px rgba(26, 26, 26, .07), 0 30px 64px rgba(26, 26, 26, .16); }

/* ---- front: symbol, title, colour band with tabs + arrow ---- */
.wcard__icon { display: block; width: 80px; height: 80px; color: var(--w-icon); margin-bottom: 1rem; }
.wcard__icon svg { width: 100%; height: 100%; }
.wcard__title { font-family: var(--pl-font-display); font-weight: 600; font-size: 1.45rem; line-height: 1.2; letter-spacing: -0.015em; color: var(--pl-logo); margin: 0; max-width: 16ch; }
.wcard__fill {
  position: absolute; left: 0; right: 0; bottom: 0; height: 12rem; color: var(--w-ink);
  background: var(--w-fill);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1.2rem;
  padding: 0 1.5rem;
}
.wcard__tabs { list-style: none; margin: 0; padding: 0; display: flex; gap: .6rem 2rem; justify-content: center; flex-wrap: wrap; color: inherit; }
.wcard__tabs li { margin: 0; font-family: var(--pl-font-body); font-weight: 800; font-size: .95rem; letter-spacing: .12em; text-transform: uppercase; padding-bottom: .35rem; border-bottom: 2px solid color-mix(in srgb, currentColor 55%, transparent); }
.wcard__go {
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; border-radius: 50%; border: 2px solid color-mix(in srgb, currentColor 70%, transparent);
  background: transparent; color: inherit; cursor: pointer; transition: background 200ms ease, transform 200ms ease;
}
.wcard__go svg { width: 24px; height: 24px; }
.wcard__go:hover, .wcard__go:focus-visible { background: color-mix(in srgb, currentColor 18%, transparent); transform: translateX(3px); }
.wcard__go:focus-visible { outline: 3px solid currentColor; outline-offset: 3px; }

/* ---- back: title, service rows with a hairline + chevron, colour band foot with two pills ---- */
.wcard__backtitle { font-family: var(--pl-font-display); font-weight: 600; font-size: 1.3rem; line-height: 1.2; letter-spacing: -0.015em; color: var(--w-text); margin: 0 0 .5rem; padding-bottom: 1rem; border-bottom: 2px solid var(--w-fill); }
.wcard__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0; flex: 1; color: inherit; }
.wcard__list li + li { border-top: 1px solid color-mix(in srgb, var(--w-fill) 30%, transparent); }
.wcard__list a { position: relative; display: block; color: inherit; text-decoration: none; border-radius: 12px; margin-inline: -.7rem; padding: 1.1rem 2.6rem 1.1rem .7rem; transition: background 180ms ease; }
.wcard__list a::after { content: ""; position: absolute; right: 1rem; top: 50%; width: 9px; height: 9px; margin-top: -5px; border-top: 2px solid var(--w-text); border-right: 2px solid var(--w-text); transform: rotate(45deg); transition: translate 180ms ease; }
.wcard__list a:hover, .wcard__list a:focus-visible { background: color-mix(in srgb, var(--w-light) 50%, #fff); }
.wcard__list a:hover::after, .wcard__list a:focus-visible::after { translate: 4px 0; }
.wcard__list a:focus-visible { outline: 3px solid var(--w-text); outline-offset: 3px; }
.wcard__list strong { display: block; color: var(--w-text); font-family: var(--pl-font-display); font-weight: 600; font-size: 1.2rem; line-height: 1.25; margin-bottom: .3rem; }
.wcard__list span { display: block; color: var(--pl-ink-soft); font-size: 1rem; line-height: 1.45; }
/* The estates card's "Start Now" row, above the service list (site.intakeLive only). */
.wcard__start {
  display: flex; align-items: center; gap: .65rem; margin: .1rem -.2rem .35rem; padding: .62rem .85rem .62rem .7rem;
  border-radius: 12px; text-decoration: none; background: color-mix(in srgb, var(--w-light) 62%, #FFFFFF); color: var(--w-text);
  font: 800 1rem var(--pl-font-body); transition: background 180ms ease;
}
.wcard__start:hover, .wcard__start:focus-visible { background: var(--w-light); }
.wcard__start:focus-visible { outline: 3px solid var(--w-text); outline-offset: 2px; }
.wcard__start-tag { flex: none; font: 800 .8125rem var(--pl-font-body); letter-spacing: .08em; text-transform: uppercase; background: var(--w-fill); color: var(--w-ink); padding: .22rem .55rem; border-radius: 999px; }
.wcard__start svg { width: 18px; height: 18px; margin-left: auto; flex: none; transition: transform 180ms ease; }
.wcard__start:hover svg { transform: translateX(3px); }

/* The foot: a straight block in the card's colour with a lighter stripe on
   top, bleeding out to the card's edges (negative margin = the back's side
   padding), holding the two pills - same shape, same ink, Back and Who
   Handles This belong together. The pills sit well inside the solid colour
   (15px below the stripe, 16px above the bottom edge). */
.wcard__actions { position: relative; display: flex; justify-content: center; align-items: center; gap: .6rem; margin: 0 calc(-1 * var(--wb-px)); padding: .95rem 1rem 1rem; background: var(--w-fill); color: var(--w-ink); flex: none; }
.wcard__return, .wcard__who {
  display: inline-flex; align-items: center; gap: .5rem; height: 44px; margin: 0; padding: 0 1.1rem .05rem 1.1rem;
  border-radius: 999px; border: 2px solid color-mix(in srgb, currentColor 70%, transparent); background: transparent;
  color: var(--w-ink); font: 800 .9rem var(--pl-font-body); text-decoration: none; cursor: pointer; transition: background 200ms ease;
}
.wcard__return svg, .wcard__who svg { width: 20px; height: 20px; }
.wcard__return:hover, .wcard__who:hover { background: color-mix(in srgb, currentColor 18%, transparent); }
.wcard__return:focus-visible, .wcard__who:focus-visible { outline: 3px solid var(--w-ink); outline-offset: 3px; }

/* ---- flip mechanism, mode one: flat at rest, 3D only while .is-animating ----
   (min-width: 1101px) and (hover: hover) and (pointer: fine) at load, see
   main.js. Partitioned under html:not([data-flip="fade"]) so this and the
   crossfade block below never fight the same property on the same element -
   they are mutually exclusive by construction, so neither needs !important. */
html:not([data-flip="fade"]) .wcard { perspective: none; }
html:not([data-flip="fade"]) .wcard.is-animating { perspective: 1800px; }
html:not([data-flip="fade"]) .wcard__inner { transform: none; transform-style: flat; }
html:not([data-flip="fade"]) .wcard.is-animating .wcard__inner {
  transform-style: preserve-3d;
  transition: transform 640ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 300ms ease, translate 300ms cubic-bezier(0.22, 1, 0.36, 1);
}
html:not([data-flip="fade"]) .wcard.is-animating.is-flipped .wcard__inner { transform: rotateY(180deg); }
html:not([data-flip="fade"]) .wcard__front, html:not([data-flip="fade"]) .wcard__back { transform: none; backface-visibility: visible; -webkit-backface-visibility: visible; }
html:not([data-flip="fade"]) .wcard.is-animating .wcard__front, html:not([data-flip="fade"]) .wcard.is-animating .wcard__back {
  backface-visibility: hidden; -webkit-backface-visibility: hidden; transition: visibility 0s linear 320ms;
}
html:not([data-flip="fade"]) .wcard.is-animating .wcard__back { transform: rotateY(180deg); }
/* Chad, 2026-09-20: the flipped card sat blank white before its content showed.
   Both faces were changing over at the midpoint, so the face coming IN stayed
   visibility: hidden for the first half of the turn and the browser did not
   paint it until it was already facing you. The face coming in is now visible
   from the first frame (backface-visibility keeps it unseen while it faces
   away, and desktop browsers honour that); only the face going OUT waits for
   the midpoint. Phones never reach this block, they crossfade. */
html:not([data-flip="fade"]) .wcard.is-animating.is-flipped .wcard__back,
html:not([data-flip="fade"]) .wcard.is-animating:not(.is-flipped) .wcard__front { transition-delay: 0s; }
html:not([data-flip="fade"]) .wcard:not(.is-flipped) .wcard__back { visibility: hidden; }
html:not([data-flip="fade"]) .wcard.is-flipped .wcard__front { visibility: hidden; }
html:not([data-flip="fade"]) .wcard.is-flipped .wcard__back { visibility: visible; }
/* .is-priming kills the transition for the single frame .is-animating turns
   3D on or off, so nothing jumps; it always comes with .is-animating (see
   main.js), so this rule only ever needs to beat the one above it. */
html:not([data-flip="fade"]) .wcard.is-priming .wcard__inner,
html:not([data-flip="fade"]) .wcard.is-priming .wcard__front,
html:not([data-flip="fade"]) .wcard.is-priming .wcard__back { transition: none; }

/* ---- flip mechanism, mode two: crossfade, everything else ----
   Both faces stay painted throughout (no visibility/backface-visibility
   trick), so nothing loads late and nothing can show mirrored on a phone
   that does not honour those properly. main.js also marks the hidden face
   inert. */
html[data-flip="fade"] .wcard, html[data-flip="fade"] .wave-cards { perspective: none; }
html[data-flip="fade"] .wcard__inner { transform: none; transform-style: flat; }
html[data-flip="fade"] .wcard__front, html[data-flip="fade"] .wcard__back {
  transform: none; backface-visibility: visible; -webkit-backface-visibility: visible; visibility: visible;
  transition: opacity 260ms ease, translate 320ms cubic-bezier(0.22, 1, 0.36, 1);
}
html[data-flip="fade"] .wcard__front { opacity: 1; }
html[data-flip="fade"] .wcard__back { opacity: 0; translate: 0 14px; pointer-events: none; }
html[data-flip="fade"] .wcard.is-flipped .wcard__front { opacity: 0; pointer-events: none; }
html[data-flip="fade"] .wcard.is-flipped .wcard__back { opacity: 1; translate: 0 0; pointer-events: auto; }

@media (prefers-reduced-motion: reduce) {
  .wcard__inner, .wcard__front, .wcard__back, .wcard__start svg { transition: none !important; }
}

/* ---- 701 to 1100px: two up, the third centred beneath, taller cards for the
   estates back (measured against the lab: needs 589px of the 604px card) ---- */
@media (min-width: 701px) and (max-width: 1100px) {
  .wave-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 780px; gap: 1.5rem; margin-inline: auto; }
  .wave-cards .wcard:nth-child(3) { grid-column: 1 / -1; justify-self: center; width: calc(50% - .75rem); }
  .wcard { --w-h: 604px; }
  .wcard__tabs { column-gap: 1.25rem; }
  .wcard__back { --wb-px: 1.4rem; padding-top: 1.7rem; }
  .wcard__backtitle { font-size: 1.15rem; padding-bottom: .8rem; }
  .wcard__list a { padding: .8rem 2.2rem .8rem .7rem; }
  .wcard__list strong { font-size: 1.08rem; }
  .wcard__list span { font-size: .95rem; line-height: 1.4; }
}

/* ---- <=700px: one column; the estates card runs taller for its Start Now
   row plus three services plus two pills (measured against the lab: 582px
   needed at 390px wide) ---- */
@media (max-width: 700px) {
  .wave-cards { grid-template-columns: 1fr; max-width: 520px; margin-inline: auto; gap: 1.25rem; padding-top: .5rem; }
  .wcard { --w-h: 440px; }
  .wcard--coral { --w-h: 610px; }
  .wcard__tabs { column-gap: 1.25rem; }
  .wcard__back { --wb-px: 1.35rem; padding-top: 1.6rem; }
  .wcard__backtitle { font-size: 1.15rem; padding-bottom: .8rem; }
  .wcard__list a { padding: .8rem 2.2rem .8rem .7rem; }
  .wcard__list strong { font-size: 1.08rem; }
  .wcard__list span { font-size: .95rem; line-height: 1.4; }
  .wcard__start { font-size: .95rem; }
}

/* ===========================================================================
   Direction 2 migration, stage 4 (2026-09-20): team block + Find Your People.
   Source of truth: MIGRATION-D2.md + scripts/make-polish-lab.mjs (search
   "team, third pass", "block", ".tcard", "Find Your People"). Markup in
   src/_includes/home/team-block.njk, homepage only (index.njk's #team
   section, in place of the old .people/.person cards - see that file's own
   header for what stayed and what moved). .home-scoped where a class name
   is shared with /team/'s .meet section (team-index.njk); .tcard/.tchips/
   .team-x are new classes, not shared, so most of this needs no .home hook.

   Card shape mirrors the service cards on purpose (same colour band, same
   panel-over-photo grammar, same ink-limit variables reused per tone under a
   different prefix so the two components never collide): --w-fill/--w-light/
   --w-ink/--w-soft here belong to .tcard, not .wcard. 2026-10-02: the wave
   above the panel is gone (Elizabeth: straight lines or a colour band; Chad
   picked the band), the panel's own top edge is the straight stripe now.

   Three rules ported from the lab's OWN CSS were never emitted by its markup
   either (.tcard__go, .tcard__role-detail, .tchips__help/__label) - dead
   inside the lab itself, so not carried over here.

   One correction: the lab lifts .tcard on plain :hover (unconditionally),
   then has to cancel it again under @media (hover: none) so a tap does not
   leave a card stuck lifted with no matching hover to release it - the exact
   bug already fixed once, for the wave cards, in stage 3. That fix is
   applied here too instead of being reintroduced: the lift and the photo's
   scale sit inside @media (hover: hover) and (pointer: fine); the
   :focus-visible half of the same rule stays unconditional, because a
   keyboard user on a touch device still needs it. No @media (hover: none)
   undo needed as a result.

   Second correction, a genuine stage 1 miss caught by measuring this block
   against the lab (the same kind stage 3 found for .areas__q): stage 1
   rescaled every homepage h2's font-size but never carried over the lab's
   matching .meet__intro width/margin polish (/labs/polish's own comment: "the
   width cap belongs on the paragraph: on the block it wrapped the bigger h2
   onto two lines"). Left at the old 52ch cap, the intro paragraph wrapped to
   three lines in the narrow left column instead of two across the full band,
   pushing the whole team block 58px lower at 1920 - the exact "does not fit
   on one screen" complaint the lab's own team-block rewrite was answering. */
.home .meet { padding-block: var(--pl-section-air); }
.home .meet__intro { max-width: none; margin-bottom: clamp(1.75rem, 2.4vw, 2.5rem); }
.home .meet__intro h2 { margin-bottom: .6rem; }
.home .meet__intro p { font-size: 1.125rem; line-height: 1.6; max-width: 56ch; }

.tcard--teal   { --w-fill: #0E6B80; --w-light: #BFDDDE; --w-ink: #FFFFFF; --w-soft: rgba(255, 255, 255, .82); }
.tcard--coral  { --w-fill: #EE7A70; --w-light: #F6DBCA; --w-ink: #00324E; --w-soft: rgba(0, 50, 78, .82); }
.tcard--butter { --w-fill: #FFD34D; --w-light: color-mix(in srgb, #FFD34D 45%, #FFFFFF); --w-ink: #00324E; --w-soft: rgba(0, 50, 78, .8); }

/* ---- rail: "Find Your People" + the four filters ---- */
.tchips { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem; margin: 0 0 clamp(2rem, 3vw, 3rem); }
.tchips__q { display: block; font-family: var(--pl-font-display); font-weight: 700; font-size: 1.3rem; line-height: 1.2; letter-spacing: -.02em; color: #00324E; margin: 0 0 .6rem; width: 100%; }
.tchip { display: flex; align-items: center; gap: .6rem; font: 700 1rem var(--pl-font-body); color: #00324E; background: #fff; border: 1.5px solid color-mix(in srgb, #0E6B80 28%, transparent); border-radius: 999px; padding: .55rem 1.15rem; cursor: pointer; transition: background 180ms ease, border-color 180ms ease, color 180ms ease, transform 180ms ease; }
.tchip:hover { transform: translateY(-1px); border-color: #0E6B80; }
.tchip:focus-visible { outline: 3px solid #0E6B80; outline-offset: 3px; }
.tchip[aria-pressed="true"] { background: var(--c, #00324E); border-color: var(--c, #00324E); color: var(--ci, #fff); }
.tchip svg { display: block; flex: none; width: 26px; height: 26px; color: var(--c, #00324E); transition: color 180ms ease; }
/* Ink limits (MIGRATION-D2.md): the property chip's house stays butter at
   rest (Chad's pick), and turns navy - not white - the moment it is pressed,
   because navy on butter is the sanctioned pair and white on butter is not. */
.tchip[data-k="business"] { --c: #0E6B80; --ci: #fff; }
.tchip[data-k="estates"]  { --c: #EE7A70; --ci: #00324E; }
.tchip[data-k="property"] { --c: #FFD34D; --ci: #00324E; }
.tchip[data-k="property"] svg { color: #FFD34D; }
.tchip[aria-pressed="true"] svg { color: var(--ci, #fff); }
.tchip[data-k=""] { --c: #00324E; --ci: #fff; }

/* ---- the cards themselves ---- */
.tcards { display: grid; gap: 1.75rem; }
.tcard {
  position: relative; display: block; overflow: hidden; border-radius: 24px; background: var(--w-light); color: var(--w-ink);
  box-shadow: 0 2px 6px rgba(26, 26, 26, .05), 0 18px 44px rgba(26, 26, 26, .10); cursor: default;
  transition: translate 300ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 300ms ease, opacity 320ms ease, filter 320ms ease, scale 320ms ease;
}
.tcard:focus-visible { translate: 0 -10px; box-shadow: 0 6px 14px rgba(26, 26, 26, .07), 0 30px 64px rgba(26, 26, 26, .16); outline: 3px solid #0E6B80; outline-offset: 4px; }
@media (hover: hover) and (pointer: fine) {
  .tcard:hover { translate: 0 -10px; box-shadow: 0 6px 14px rgba(26, 26, 26, .07), 0 30px 64px rgba(26, 26, 26, .16); }
  .tcard:hover .tcard__photo { scale: 1.04; }
}
.tcard.has-more { cursor: pointer; }
.tcard__photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 18%; transition: scale 600ms cubic-bezier(0.22, 1, 0.36, 1); }
.tcard__initials { position: absolute; inset: 0 0 30% 0; display: grid; place-items: center; font-family: var(--pl-font-display); font-weight: 700; font-size: clamp(3rem, 4.4vw, 5rem); letter-spacing: -.03em; color: color-mix(in srgb, var(--w-fill) 70%, #00324E); opacity: .55; }
/* 2026-10-02: the straight colour band. Solid fill with a 6px lighter stripe
   on the top edge; the text starts below the stripe with room to breathe. */
.tcard__panel { position: absolute; left: 0; right: 0; bottom: 0; background: var(--w-fill); padding: .9rem 1.6rem 1.5rem; }
.tcards--staff .tcard__panel { padding: .65rem 1.1rem 1.1rem; }
.tcard__name { display: block; font-family: var(--pl-font-display); font-weight: 700; font-size: 1.6rem; line-height: 1.15; letter-spacing: -.025em; color: var(--w-ink); }
.tcards--staff .tcard__name { font-size: 1.12rem; letter-spacing: -.015em; }
.tcard__role { display: block; margin-top: .4rem; font: 800 .8125rem var(--pl-font-body); letter-spacing: .1em; text-transform: uppercase; color: var(--w-soft); }
.tcards--staff .tcard__role { font: 600 .875rem/1.35 var(--pl-font-body); letter-spacing: 0; text-transform: none; margin-top: .3rem; }
/* one-line faces: the panel stays low, so the band never climbs over a face */
.tcards--staff .tcard__name, .tcards--staff .tcard__role { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tcards--staff .tcard--long .tcard__name { font-size: .92em; letter-spacing: -.025em; }
/* The rise: closed at rest (0fr), open on real hover, on focus, and whenever
   .is-open is set (main.js's click/tap toggle - see "Team block + Find Your
   People"). Hover only where a real hover exists, same reasoning as the
   photo scale above: a tap has no matching :hover to release it on a phone. */
.tcard__more { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 420ms cubic-bezier(0.22, 1, 0.36, 1); }
.tcard__more > span { overflow: hidden; min-height: 0; }
.tcard:focus-visible .tcard__more, .tcard.is-open .tcard__more { grid-template-rows: 1fr; }
@media (hover: hover) and (pointer: fine) { .tcard:hover .tcard__more { grid-template-rows: 1fr; } }
/* display: block (Chad, 2026-09-21: "the bios have heavy spacing"). The bio and the
   full title are <span>s, so they were INLINE: an inline box cannot shrink its
   line below the parent's strut, so the 13px staff bios were being set on the
   panel's own 16px x 1.6 line (21px apart instead of 18.5), and their
   margin-top never applied at all. As blocks they take their own line-height. */
.tcard__bio, .tcard__detail { display: block; }
.tcard__bio { margin: .9rem 0 0; font-size: 1rem; line-height: 1.5; color: var(--w-ink); }
.tcards--staff .tcard__bio { font-size: .9rem; line-height: 1.45; margin-top: .7rem; }
/* has-title: the staff FACE shows the short form (.tcard__role); opened, the
   full title (.tcard__detail) REPLACES it - never both at once. */
.tcard__detail { display: block; margin-top: .3rem; font: 600 .875rem/1.35 var(--pl-font-body); color: var(--w-soft); white-space: normal; }
.tcard.has-title:is(:focus-visible, .is-open) .tcard__role { display: none; }
@media (hover: hover) and (pointer: fine) { .tcard.has-title:hover .tcard__role { display: none; } }
/* who handles what: the rest step back, the matches keep their place */
.team-x[data-pick] .tcard:not(.is-match) { opacity: .34; filter: grayscale(.7); scale: .97; }
.team-x[data-pick] .tcard.is-match { box-shadow: 0 0 0 3px var(--pick, #0E6B80), 0 18px 44px rgba(26, 26, 26, .14); }
.team-x[data-pick="business"] { --pick: #0E6B80; }
.team-x[data-pick="estates"]  { --pick: #EE7A70; }
.team-x[data-pick="property"] { --pick: #FFD34D; }
@media (prefers-reduced-motion: reduce) { .tcard, .tcard__photo, .tcard__more { transition: none; } }

/* Team block breakpoints moved 1100/1101 -> 1535/1536 on 2026-10-05 (Chad):
   between 1101 and 1535 the desktop rail left the 3x2 staff grid 24-135px
   cards and every staff name ended in an ellipsis ("Anita Kovac...",
   "Stephanie Sear..."). Laptops get the tablet layout instead; the rail
   starts where the names fit (167px cards at 1536). The service cards keep
   their own 1100/1101 breakpoints. */
/* ---- <=1535px (phone, tablet, laptop): two lawyers, portrait; three staff up ---- */
@media (max-width: 1535px) {
  .tchips { display: grid; grid-template-columns: 1fr 1fr; gap: .55rem; margin-bottom: 1.5rem; }
  .tchips__q { grid-column: 1 / -1; font-size: 1.25rem; margin-bottom: .2rem; }
  .tchip { width: 100%; text-align: left; border-radius: 14px; padding: .7rem .8rem; font-size: .95rem; line-height: 1.2; min-height: 52px; }
  .tchip svg { width: 26px; height: 26px; }
  .tcards--lead { grid-template-columns: 1fr 1fr; gap: .75rem; max-width: none; margin-bottom: .75rem; }
  .tcards--lead .tcard { aspect-ratio: 10 / 14; border-radius: 20px; }
  .tcards--lead .tcard__photo { object-position: 50% 12%; }
  .tcards--lead .tcard__panel { padding: .7rem 1rem 1rem; }
  .tcards--lead .tcard__name { font-size: 1.15rem; }
  .tcards--lead .tcard__role { font-size: .8125rem; letter-spacing: .06em; margin-top: .25rem; }
  .tcards--lead .tcard__bio { font-size: .875rem; line-height: 1.4; margin-top: .55rem; }
  .tcards--staff { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1rem; }
  .tcards--staff .tcard { aspect-ratio: 10 / 12; border-radius: 18px; }
  .tcards--staff .tcard__name { white-space: normal; overflow: visible; font-size: 1rem; line-height: 1.15; }
  .tcards--staff .tcard--long .tcard__name { font-size: .95rem; }
  .tcards--staff .tcard__role, .tcards--staff .tcard__detail { font-size: .8125rem; }
  .tcards--staff .tcard__bio { font-size: .8125rem; line-height: 1.4; margin-top: .4rem; }
  .tcards--staff .tcard__panel { padding: .6rem .85rem .8rem; }
}
/* ---- <=700px (phone): staff drop to two up ---- */
@media (max-width: 700px) {
  .tcards--staff { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .75rem; }
}
/* Smallest phones (<=380px): staff cards are ~165px wide, and an opened card
   with a two-line title plus a one-line bio pushed the name off its top edge
   by 1-2px (found 2026-10-05 when the last three bios went in). One notch
   smaller text in the opened state only; the faces are unchanged. */
@media (max-width: 380px) {
  .tcards--staff .tcard__bio { font-size: .75rem; line-height: 1.35; margin-top: .3rem; }
  .tcards--staff .tcard__detail { font-size: .75rem; }
  .tcards--lead .tcard__bio { font-size: .8125rem; line-height: 1.35; margin-top: .4rem; }
}
/* Phones: "Founder and Principal Lawyer" (2026-10-05) in spaced capitals ran
   to three lines on a ~170px lead card, a band two lines taller than
   Darren's. Tighter tracking brings it back to two, as the old title was. */
@media (max-width: 700px) {
  .tcards--lead .tcard__role { letter-spacing: .03em; font-size: .75rem; }
}
/* ---- 701 to 1535px (tablet + laptop): rail as one row of four, lawyers a
   centred pair, staff three up ---- */
@media (min-width: 701px) and (max-width: 1535px) {
  .tchips { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .tcards--lead { grid-template-columns: repeat(2, minmax(0, 300px)); justify-content: center; gap: 1.25rem; margin-bottom: 1.25rem; }
  .tcards--lead .tcard { aspect-ratio: 10 / 12; }
  .tcards--lead .tcard__name { font-size: 1.3rem; }
  .tcards--lead .tcard__bio { font-size: .95rem; }
  .tcards--staff { max-width: 780px; margin-inline: auto; }
  .tcards--staff .tcard { aspect-ratio: 10 / 10.5; }
}
/* ---- >=1536px (desktop): the rail proper - one block, two lawyers side by
   side, six staff as a 3x2 grid at exactly half the lawyer card's height ---- */
@media (min-width: 1536px) {
  .team-x { --H: clamp(420px, 26vw, 500px); --g: 20px; display: grid; grid-template-columns: 250px auto minmax(0, 1fr); gap: 0 2.25rem; align-items: start; }
  .tchips { flex-direction: column; align-items: stretch; gap: .55rem; margin: 0; }
  .tchip { width: 100%; text-align: left; border-radius: 16px; padding: .8rem 1rem; font-size: 1rem; line-height: 1.25; }
  .tchip svg { width: 30px; height: 30px; }
  .tcards { gap: var(--g); margin: 0; }
  .tcards--lead { grid-template-columns: repeat(2, calc(var(--H) * .66)); justify-content: start; gap: 24px; }
  .tcards--lead .tcard { aspect-ratio: auto; height: var(--H); }
  .tcards--lead .tcard__name { font-size: 1.45rem; }
  .tcards--staff { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .tcards--staff .tcard { aspect-ratio: auto; height: calc((var(--H) - var(--g)) / 2); border-radius: 18px; }
  .tcards--staff .tcard__panel { padding: .6rem .9rem .8rem; }
  .tcards--staff .tcard__name { font-size: 1rem; }
  .tcards--staff .tcard--long .tcard__name { font-size: .8125rem; letter-spacing: -.03em; }
  .tcards--staff .tcard__role { font-size: .8125rem; margin-top: .15rem; }
  .tcards--staff .tcard__bio { font-size: .8125rem; line-height: 1.42; margin-top: .45rem; }
  .tcards--staff .tcard__detail { font-size: .8125rem; margin-top: .15rem; }
  .tcards--staff .tcard__initials { inset: 0 0 38% 0; font-size: 2.6rem; }
}

/* The section titles were centred with the hero on 2026-08-21 and put back on
   the left edge the same day, once a critique measured what it cost: 19 major
   elements resolving to 16 different ink left-edges, and four orphan tail
   lines that only exist when centred copy wraps. Elizabeth approved a centred
   HERO; the rest of the page keeps its left edge. Do not re-centre .areas__q,
   the process heading or .meet__intro without a fresh reason. */
/* The path keeps its left-to-right grammar - the numerals stay hard left in
   their columns so the connector can run between them - but the band stops
   sprawling to the full 1584px wrap and takes the film's measure instead.
   The film's 1132px was the first try and read too tight (Chad, on sight),
   so the band keeps a cap but takes most of the runway back. Homepage only:
   the practice pages keep a left-aligned heading, so a centred band there
   would sit under a heading that does not share its axis. */
/* Direction 2 migration, stage 5 (2026-09-20): the extra clearance below this
   heading (clamp(2.75rem, 4.5vw, 4.75rem)) was measured for the OLD .steps
   design - "the stamp hangs 1.7rem above the band and eats all but 13px of
   the heading's own 40px margin, so the gap is measured from the stamp
   rather than the band". The stamp is gone (replaced by .pj, which has its
   own padding-top and the track's own margin-top), so that extra clearance
   is stale and left the band sitting noticeably low against the lab.
   Removed rather than kept and overridden again: the generic .process >
   .pl-wrap > h2 margin-bottom (style.css, ~line 2022) already matches the
   lab's own clamp(1.75rem, 2.4vw, 2.75rem) figure, so the homepage now falls
   back to it like every other .process heading. */

/* Both bands go white on the homepage (Chad, 2026-08-21). The aqua wash under
   the doors and the blush under the path are gone; the hairlines stay, and
   they are now the only thing marking one room from the next.
   Worth knowing: a white .process was tried on 2026-08-04 and reverted then,
   because it merged with the white team section below it. What is different
   now is that the band kept its border-top and border-bottom, so the boundary
   survives without the tint. If it reads as one long white page, that comment
   is where the argument for a tint is written down.
   Homepage only - the practice pages share these components and their card
   band was signed off with the aqua wash on 2026-08-19. */
.home .areas { background: #fff; }
.home .process { background: #fff; }
/* REMOVED 2026-09-20 (Direction 2 migration cleanup): .home .steps__n,
   .home .steps__note, .home .steps li p and .home .steps h3 only ever matched
   the homepage's old .steps list, which src/_includes/home/steps-journey.njk
   (stage 5, below) replaced - confirmed dead by grepping the built homepage
   for .steps markup (none). work.njk's .steps is untouched and still needs
   the un-prefixed .steps/.steps__n/etc rules earlier in this file. */

/* -----------------------------------------------------------------------
   Direction 2 migration, stage 5 (2026-09-20): the journey tracker.
   Source of truth: src/labs/direction-2.njk (the base .pj/.pj__* markup,
   "journey" chip) patched by scripts/make-polish-lab.mjs (search "process
   journey timing" for the 2026-09-20 progress-timing fix, and
   ".pj__track { position: absolute" for the vertical-rail CSS this stage
   ports). Markup: src/_includes/home/steps-journey.njk, in place of the
   homepage's old .steps list. .pj/.pj__* are new classes, not shared with
   work.njk's .steps, so none of this needs a .home hook - only the shared
   .process wrapper gets one, for the --step-ink token.

   Progress (--p, set in main.js's "The journey") is keyed to the CARD ROW
   (the first .pj__step), not the .process section: 0 when its top is 78%
   down the viewport, 1 at 30% - Chad's 2026-09-18 fix for the old
   section-level timing, which played most of the sequence before the cards
   were even visible. Below 900px the steps stack into one column and the
   track becomes a vertical rail spanning from the first step's number to
   the last one's, with the envelope holding at 55% down the screen while
   the cards scroll past it - measured with offsetTop in main.js, not
   getBoundingClientRect, because the cards translate 14px as they light and
   measuring the moved box would make the rail's own length twitch on every
   step lit. --rail-top/--rail-len are written by that same script. */
.home .process, .work .process { --step-ink: #C64438; }
.pj { --p: 0; position: relative; padding-top: .5rem; }
.pj__track { position: relative; height: 8px; border-radius: 4px; margin: 1.2rem 16.66% 0; background: color-mix(in srgb, var(--step-ink) 16%, transparent); }
.pj__fill { position: absolute; top: 0; bottom: 0; left: 0; width: calc(var(--p) * 100%); border-radius: 4px; background: var(--step-ink); }
.pj__mail {
  position: absolute; top: 50%; left: calc(var(--p) * 100%); width: 72px; height: 72px; border-radius: 50%;
  translate: -50% -50%; rotate: calc(-10deg + var(--p) * 20deg);
  display: grid; place-items: center; background: #fff; color: var(--step-ink); border: 2.5px solid var(--step-ink);
  box-shadow: 0 6px 18px rgba(26, 26, 26, .14);
}
.pj__mail svg { width: 34px; height: 34px; }
.pj__steps { list-style: none; margin: 3.2rem 0 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 3rem; }
.pj__step {
  position: relative; margin: 0; text-align: center; padding: 2.4rem 1.8rem 2.2rem; border-radius: 22px; background: #fff;
  opacity: .42; translate: 0 22px; box-shadow: 0 0 0 1px rgba(26, 26, 26, .05);
  transition: opacity 480ms ease, translate 520ms cubic-bezier(.22, 1, .36, 1), box-shadow 520ms ease;
}
.pj__step.is-lit { opacity: 1; translate: 0 0; box-shadow: 0 2px 6px rgba(26, 26, 26, .05), 0 16px 40px rgba(26, 26, 26, .10); }
.pj__step h3 { font-size: 1.35rem; line-height: 1.22; margin: 0 0 .6rem; max-width: 20ch; margin-inline: auto; }
.pj__step p { margin: 0; font-size: 1.02rem; max-width: 32ch; margin-inline: auto; }
.pj__n {
  position: relative; display: inline-grid; place-items: center; width: 4.4rem; height: 4.4rem; margin-bottom: 1.2rem; border-radius: 50%;
  font-family: var(--pl-font-display); font-weight: 700; font-size: 1.9rem; color: var(--step-ink); border: 2.5px solid var(--step-ink); background: #fff;
  transition: background 360ms ease, color 360ms ease, transform 520ms cubic-bezier(.34, 1.56, .64, 1);
}
.pj__n b, .pj__n i { grid-area: 1 / 1; font-style: normal; font-weight: inherit; display: grid; place-items: center; }
.pj__n i { opacity: 0; transform: scale(.4); transition: opacity 300ms ease, transform 420ms cubic-bezier(.34, 1.56, .64, 1); }
.pj__n i svg { width: 2rem; height: 2rem; }
.pj__step.is-lit .pj__n { background: var(--step-ink); color: #fff; transform: scale(1.06); }
.pj__step:last-child.is-lit .pj__n b { opacity: 0; }
.pj__step:last-child.is-lit .pj__n i { opacity: 1; transform: scale(1); }
.pj__tag {
  position: absolute; top: -1.1rem; right: -.6rem; padding: .55rem .95rem; border-radius: 10px; rotate: 6deg;
  background: #FFD34D; color: #00324E; font: 800 .88rem/1 var(--pl-font-body); letter-spacing: .04em; text-transform: uppercase;
  box-shadow: 0 6px 16px rgba(26, 26, 26, .14); transform: scale(0); transform-origin: 80% 80%;
  transition: transform 520ms cubic-bezier(.34, 1.56, .64, 1) 120ms;
}
.pj__step.is-lit .pj__tag { transform: scale(1); }
@media (max-width: 900px) {
  .pj__steps { grid-template-columns: 1fr; }
  .pj { padding-left: 3.4rem; padding-top: 0; }
  .pj__track { position: absolute; left: 1.05rem; top: var(--rail-top, 3.5rem); width: 6px; height: var(--rail-len, 70%); margin: 0; border-radius: 3px; }
  .pj__fill { top: 0; left: 0; right: 0; bottom: auto; width: 100%; height: calc(var(--p) * 100%); border-radius: 3px; }
  .pj__mail { left: 50%; top: calc(var(--p) * 100%); width: 52px; height: 52px; rotate: calc(-8deg + var(--p) * 16deg); }
  .pj__mail svg { width: 26px; height: 26px; }
  .pj__steps { margin-top: .25rem; gap: 1.5rem; }
  .pj__step { padding: 1.9rem 1.4rem 1.8rem; translate: 0 14px; }
  .pj__step.is-lit { translate: 0 0; }
}
@media (prefers-reduced-motion: reduce) {
  .pj__step, .pj__n, .pj__tag { transition: none !important; }
}

/* -----------------------------------------------------------------------
   Direction 2 migration, stage 6 (2026-09-20): the close, ways cards + fast
   lane. Markup: src/_includes/home/close-ways.njk, in place of the
   homepage's old .close__actions/.close__note/.close__where. Source of
   truth: scripts/make-polish-lab.mjs (search "Close: three ways to start",
   ".way", "the smart intake, surfaced") - the lab calls this component
   .way/.way__*; renamed here to .ccard/.ccard__* and .close-ways because
   /contact/ already owns the bare .way__mark/__body/__value/__links/
   __label/__go prefix for its own three-ways-to-reach-us cards (style.css,
   search "6. The close" is the WRONG hit - see "Call or Fax" in
   src/pages/contact.md). Reusing the lab's names verbatim in this shared
   stylesheet would have bled the close band's card styling onto /contact/'s
   unrelated cards - the lab could never have caught this itself, since it
   renders in total isolation with its own inline <style>. --w-fill/
   --w-light/--w-ink are still reused unchanged: those are custom
   properties scoped per component container, the convention stage 4 already
   used for .tcard, and .ccard/.wcard/.tcard are the same card family (wave,
   team, close - next letter each time).

   The h2 loses its .glow-word highlight span entirely on the homepage
   (index.njk simply does not emit it, rather than emitting it and
   overriding it back off - the lab has to fight its own already-rendered
   markup with three !important rules; nothing here needs any, because the
   markup was never there to begin with). The close lede is dropped the same
   way - not hidden, not emitted.

   Call Us reads entity.openingHours (main.js, "The close ways" IIFE) - see
   that IIFE's own header for why this is stricter than the lab's hard-coded
   Mo-Fr/9-5 version. Write Us mirrors main.js's existing reply-clock
   sentence rather than recomputing it - .close__note[data-reply-clock] stays
   in the DOM (hidden) purely as that single source of truth. */
.home .close h2, .work .close h2 { margin-bottom: clamp(2rem, 2.8vw, 3rem); }
.home .close, .work .close { padding-block: var(--pl-section-air); }
.close-ways { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 3.5rem; text-align: center; }
.ccard {
  /* 392px, not the 372px the card first ships with in the generator: a
     later pass in the same file ("the wave is too low, it's not covering
     the full pill" - the pill's top edge sat above the wave's solid colour
     at the dips in the curve) raises both this and .ccard__foot's height
     below, and that later value is the one that ships. Reproduced directly
     as a single clean rule rather than as two rules where the second wins. */
  position: relative; display: flex; flex-direction: column; align-items: center; overflow: hidden; min-height: 392px; padding: 2.4rem 1.9rem 0;
  background: #fff; border-radius: 24px; box-shadow: 0 2px 6px rgba(26, 26, 26, .05), 0 18px 44px rgba(26, 26, 26, .10);
  transition: translate 300ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 300ms ease;
}
/* :hover gated to (hover: hover) and (pointer: fine), :focus-within left
   unconditional - the same fix stage 3 and 4 already made for .wcard/.tcard
   (a plain :hover lift gets "stuck" after a tap on a touchscreen, since a tap
   can leave :hover matching with no pointer move to clear it), ported here
   before the lab's own unconditional version could reintroduce the bug a
   third time. A keyboard user on a touch device still needs the
   :focus-within half. */
@media (hover: hover) and (pointer: fine) {
  .ccard:hover { translate: 0 -12px; box-shadow: 0 6px 14px rgba(26, 26, 26, .07), 0 30px 64px rgba(26, 26, 26, .16); }
}
.ccard:focus-within { translate: 0 -12px; box-shadow: 0 6px 14px rgba(26, 26, 26, .07), 0 30px 64px rgba(26, 26, 26, .16); }
.ccard--teal   { --w-fill: #0E6B80; --w-light: #BFDDDE; --w-ink: #FFFFFF; --w-icon: #0E6B80; --w-text: #0E6B80; }
.ccard--coral  { --w-fill: #EE7A70; --w-light: #F6DBCA; --w-ink: #00324E; --w-icon: #C64438; --w-text: #C64438; }
.ccard--butter { --w-fill: #FFD34D; --w-light: color-mix(in srgb, #FFD34D 45%, #FFFFFF); --w-ink: #00324E; --w-icon: #FFD34D; --w-text: #00324E; }
.ccard__icon { width: 72px; height: 72px; color: var(--w-icon); margin-bottom: .9rem; }
.ccard__icon svg { width: 100%; height: 100%; display: block; }
.ccard__title { font-family: 'Bricolage Grotesque', 'Montserrat', sans-serif; font-weight: 700; font-size: 1.45rem; line-height: 1.2; letter-spacing: -.02em; color: var(--pl-logo, #0E6B80); margin: 0 0 .7rem; }
.ccard__big { font-family: 'Bricolage Grotesque', 'Montserrat', sans-serif; font-weight: 700; font-size: 1.5rem; letter-spacing: -.02em; color: #00324E; margin: 0 0 .5rem; text-wrap: balance; }
.ccard__text { font-size: 1.0625rem; line-height: 1.5; color: var(--pl-ink-soft, #4a4a4a); margin: 0; max-width: 30ch; }
.ccard__text strong, .ccard__text b { color: #00324E; }
/* The Visit card's mailto link sits on top of a stretched card (the whole
   card is the "Get Directions" target via .ccard__go::after) - without its
   own stacking position above that overlay, a click here would land on the
   pill instead. The lab does this with an inline z-index; here it is a
   class, matching this file's usual "no inline styles" pattern. */
.ccard__inline-link { position: relative; z-index: 2; color: #0E6B80; }
.ccard__status { display: inline-flex; align-items: center; gap: .5rem; font: 800 .8125rem var(--pl-font-body); letter-spacing: .1em; text-transform: uppercase; color: #4a4a4a; margin: 0; }
.ccard__status i { width: 10px; height: 10px; border-radius: 50%; background: #9aa5a8; }
.ccard__status.is-open { color: #0E6B80; } .ccard__status.is-open i { background: #1FA971; box-shadow: 0 0 0 4px rgba(31, 169, 113, .18); }
.ccard__status.is-live { color: #0E6B80; } .ccard__status.is-live i { background: #0E6B80; box-shadow: 0 0 0 4px rgba(14, 107, 128, .16); }
.ccard__status[hidden] { display: none; }
/* 2026-10-02, Elizabeth: "straight lines or a colour band". Chad picked the
   band: the foot is a straight block in the card's colour with an 8px lighter
   stripe on top, the pill centred in the solid colour (about 20px above and
   below it). Replaces the wave SVG foot. */
.ccard__foot { position: absolute; left: 0; right: 0; bottom: 0; height: 5.9rem; display: flex; align-items: center; justify-content: center; background: var(--w-fill); color: var(--w-ink); }
.ccard__go {
  position: relative; display: inline-flex; align-items: center; gap: .55rem; height: 46px; padding: 0 1.15rem .05rem 1.3rem; border-radius: 999px; border: 2px solid color-mix(in srgb, currentColor 70%, transparent);
  color: var(--w-ink); font: 800 .95rem var(--pl-font-body); text-decoration: none; transition: background 200ms ease;
  /* Chad, 2026-09-20 (found on the wave cards' own pill, ported here before
     it could repeat): width:max-content/flex:none/white-space:nowrap, or the
     pill collapses to a circle as a flex item of .ccard__foot with its label
     stacked one word per line. */
  width: max-content; max-width: calc(100% - 2rem); flex: none; white-space: nowrap;
}
.ccard__go svg { width: 20px; height: 20px; transition: transform 200ms ease; }
.ccard__go:hover { background: color-mix(in srgb, currentColor 18%, transparent); } .ccard__go:hover svg { transform: translateX(3px); }
.ccard__go:focus-visible { outline: 3px solid currentColor; outline-offset: 3px; }
/* the whole card is the target: the pill's hit area stretches over it - one
   real link per card, no nested interactive elements underneath it */
.ccard__go::after { content: ""; position: absolute; left: -100vw; right: -100vw; top: -100vh; bottom: -100vh; }
.ccard { isolation: isolate; } .ccard__go { z-index: 1; }
/* Below 1101px the three tall centred cards become compact rows - symbol
   left, text right, the pill in a short foot - rather than shrunk copies of
   the desktop card (the generator's own comment: "the three ways as compact
   rows... instead of three tall centred cards"). This is the FINAL shape
   for every width this stage was asked to check at 1101px and below,
   including the 1024x768 and 768x1024 breakpoints - there is no separate,
   narrower "phone" layout for this component the way the wave and team
   cards have one; .fastlane is the only piece with its own sub-900px step,
   just below. */
@media (max-width: 1100px) {
  .close-ways { grid-template-columns: 1fr; gap: 1rem; max-width: 560px; margin-inline: auto; }
  .ccard {
    min-height: 0; display: grid; grid-template-columns: 52px minmax(0, 1fr); column-gap: 1rem;
    align-items: start; text-align: left; padding: 1.4rem 1.25rem 142px; border-radius: 22px;
  }
  .ccard__icon { grid-row: 1 / span 3; width: 52px; height: 52px; margin: 0; }
  .ccard__title { font-size: 1.2rem; margin: .1rem 0 .3rem; }
  .ccard__big { font-size: 1.25rem; margin: 0 0 .35rem; }
  .ccard__text { max-width: none; font-size: 1rem; }
  .ccard__status { letter-spacing: .06em; }
}
@media (prefers-reduced-motion: reduce) {
  .ccard, .ccard__go svg { transition: none; }
}

/* The smart intake, surfaced on the close band (Chad, 2026-09-20: "something
   about our smart intake, so people know if they are doing wills and
   estates they can get started now"). Fast lane under the three ways to
   /intake/wills/, gated on site.intakeLive like every other workbook
   entry point. Wording is the workbook page's own. */
.fastlane {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 1.75rem; margin-top: clamp(2rem, 2.8vw, 3rem); padding: 1.7rem 2.25rem;
  /* 2026-10-02, Chad: the homepage strip joins the workbook band on treatment B
     (white, 2px coral outline) instead of its peach fill, so the two read as one piece. */
  text-align: left; border-radius: 24px; background: #fff; border: 2px solid #EE7A70; box-shadow: 0 2px 6px rgba(26, 26, 26, .04), 0 12px 30px rgba(26, 26, 26, .06);
  transition: translate 300ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 300ms ease; position: relative; isolation: isolate; overflow: hidden;
}
/* Same :hover/(hover: hover) and (pointer: fine) split as .ccard above. */
@media (hover: hover) and (pointer: fine) {
  .fastlane:hover { translate: 0 -6px; box-shadow: 0 6px 14px rgba(26, 26, 26, .06), 0 24px 50px rgba(26, 26, 26, .12); }
}
.fastlane:focus-within { translate: 0 -6px; box-shadow: 0 6px 14px rgba(26, 26, 26, .06), 0 24px 50px rgba(26, 26, 26, .12); }
.fastlane__icon { width: 60px; height: 60px; color: #C64438; }
.fastlane__icon svg { width: 100%; height: 100%; display: block; }
.fastlane__tag { display: block; font: 800 .8125rem var(--pl-font-body); letter-spacing: .12em; text-transform: uppercase; color: #C64438; margin: 0 0 .3rem; }
.fastlane__title { font-family: 'Bricolage Grotesque', 'Montserrat', sans-serif; font-weight: 700; font-size: clamp(1.3rem, 1.55vw, 1.6rem); line-height: 1.2; letter-spacing: -.02em; color: #00324E; margin: 0 0 .35rem; }
.fastlane__line { font-size: 1.0625rem; line-height: 1.5; color: #4a4a4a; margin: 0; max-width: 78ch; }
.fastlane__go {
  position: relative; z-index: 1; display: inline-flex; align-items: center; gap: .6rem; width: max-content; white-space: nowrap; height: 52px; padding: 0 1.35rem .05rem 1.5rem; border-radius: 999px;
  background: #EE7A70; color: #00324E; font: 800 1rem var(--pl-font-body); text-decoration: none; transition: background 200ms ease;
}
.fastlane__go svg { width: 20px; height: 20px; transition: transform 200ms ease; }
.fastlane__go:hover { background: #F08E85; } .fastlane__go:hover svg { transform: translateX(3px); }
.fastlane__go:focus-visible { outline: 3px solid #00324E; outline-offset: 3px; }
.fastlane__go::after { content: ""; position: absolute; left: -100vw; right: -100vw; top: -100vh; bottom: -100vh; }
@media (max-width: 1100px) {
  .fastlane { gap: .9rem; padding: 1.35rem 1.25rem; margin-top: 1rem; }
  .fastlane__title { font-size: 1.25rem; }
  .fastlane__line { font-size: 1rem; }
  .fastlane__go { width: 100%; justify-content: center; }
}
@media (max-width: 900px) {
  .fastlane { grid-template-columns: 1fr; }
  .fastlane__icon { width: 48px; height: 48px; }
}
@media (prefers-reduced-motion: reduce) {
  .fastlane, .fastlane__go svg { transition: none; }
}
/* The workbook band on the estates practice pages (see src/_includes/work.njk
   for the story). It sits on the services band's aqua wash as that band's foot,
   no seam.
   2026-10-02, Elizabeth: "straight lines or a colour band ... an outlined and
   white box". Chad picked treatment B for this band: white, a 2px coral outline,
   no coloured foot at all. The tilted preview sheet stays, now rising from the
   bottom edge of the right column with a peach outline so it reads on white.
   The coral blocks, the navy wave foot and .wbk__wave are gone. Ink: navy text,
   navy outlined fact pills, coral Start pill with navy text, brick PDF link
   (brick is one of the two text colours allowed on white). */
.intake-band.intake-band--block { border-top: 0; padding: 0 0 clamp(3.5rem, 5vw, 5rem); background: rgba(191, 221, 222, 0.22); }
.areas.areas--work:has(+ .intake-band--block) { padding-bottom: clamp(2.5rem, 3vw, 3.5rem); }
.wbk {
  position: relative; display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr); column-gap: clamp(2rem, 3vw, 3rem);
  padding: clamp(2.2rem, 3.2vw, 3.6rem) clamp(1.6rem, 3.2vw, 3.6rem) 0; border-radius: 32px; overflow: hidden;
  background: #fff; border: 2px solid #EE7A70; color: #00324E; box-shadow: 0 6px 14px rgba(26, 26, 26, .05), 0 20px 48px rgba(26, 26, 26, .10);
}
.intake-band .wbk h2 { font-family: 'Instrument Serif', Georgia, serif; font-weight: 400; font-size: clamp(2.6rem, 4.4vw, 5rem); line-height: 1.04; letter-spacing: -.01em; color: #00324E; max-width: none; margin: 0; text-wrap: balance; }
.wbk h2 em { font-style: italic; }
.wbk__lede { font-size: clamp(1.05rem, 1.1vw, 1.2rem); line-height: 1.55; color: #00324E; margin: 1.1rem 0 1.6rem; max-width: 46ch; }
.wbk__facts { list-style: none; display: flex; flex-wrap: wrap; gap: .6rem; margin: 0 0 2rem; padding: 0; }
.wbk__facts li { font: 800 .95rem var(--pl-font-body); color: #00324E; border: 1.5px solid #00324E; border-radius: 999px; padding: .5rem 1.1rem; }
.wbk__sheet { grid-column: 2; grid-row: 1 / span 2; align-self: end; display: grid; gap: .9rem; background: #fff; border: 2px solid color-mix(in srgb, #EE7A70 40%, #FFFFFF); border-bottom: 0; border-radius: 22px 22px 0 0; padding: 1.7rem 1.8rem 2.8rem; rotate: 2deg; translate: 0 14px; box-shadow: 0 -4px 22px rgba(0, 50, 78, .10); }
.wbk__sheet b { font: 700 1.2rem var(--pl-font-display); color: #0E6B80; }
.wbk__sheet span { display: flex; align-items: center; gap: .8rem; font: 600 1rem var(--pl-font-body); color: var(--pl-ink); }
.wbk__sheet span::before { content: ""; flex: none; width: 22px; height: 22px; border-radius: 50%; border: 2px solid color-mix(in srgb, #0E6B80 40%, transparent); }
.wbk__sheet span.is-done::before { background: #0E6B80; border-color: #0E6B80; }
.wbk__foot { grid-column: 1; grid-row: 2; position: relative; display: flex; align-items: center; justify-content: space-between; gap: 1rem 2rem; flex-wrap: wrap; padding: 0 0 clamp(2.2rem, 3.2vw, 3.6rem); }
.wbk__go { position: relative; display: inline-flex; align-items: center; gap: .6rem; height: 54px; padding: 0 1.7rem; border-radius: 999px; background: #EE7A70; color: #00324E; font: 800 1.05rem var(--pl-font-body); text-decoration: none; white-space: nowrap; transition: transform 200ms ease, background 200ms ease; }
.wbk__go svg { width: 20px; height: 20px; transition: transform 200ms ease; }
.wbk__go:hover { background: #F08E85; transform: translateY(-2px); } .wbk__go:hover svg { transform: translateX(3px); }
.wbk__alt { position: relative; color: #C64438; font: 700 1rem var(--pl-font-body); text-underline-offset: 4px; }
.wbk__go:focus-visible, .wbk__alt:focus-visible { outline: 3px solid #00324E; outline-offset: 3px; border-radius: 999px; }
@media (max-width: 900px) {
  .wbk { grid-template-columns: minmax(0, 1fr); border-radius: 24px; }
  .wbk__sheet { display: none; }
  .wbk__foot { grid-column: 1; }
  .wbk__go { width: 100%; justify-content: center; }
}
@media (prefers-reduced-motion: reduce) { .wbk__go, .wbk__go svg { transition: none; } .wbk__go:hover { transform: none; } }

/* --- Colour-pass lab v3 (2026-08-11) -------------------------------------
   Chad killed the butter highlighter (v2's swipes are gone from the
   markup too). What remains under test: blush speech bubbles on every
   tier, and the hero's "English" + primary buttons warming from cool
   (petrol teal / navy) to coral. The aqua choices band stays - it is
   Elizabeth's own aqua; her note was about ratio, not the colour.
   Gated behind html[data-colorpass] - the live page ships unchanged.
   Open /?colors=a - main.js ("The colour pass") adds the switcher.
   When one wins: promote to base, delete this block and the switcher.

   every tier: blush speech bubbles (team hovers + service disclosures)
   a: "English" goes coral, buttons stay navy
   b: "English" goes coral, primary buttons go coral */

/* b only now: "English" in readable coral. a = pure blush bubbles, so the
   single-move proposal can be seen with nothing else changed. */
[data-colorpass="b"] .ask h1 em { color: var(--pl-accent-text); }

/* b: primary buttons in coral. --pl-accent-text, not the decorative coral:
   white on #EE7A70 is 2.74:1 and fails AA; on #C64438 it clears 4.9:1. */
[data-colorpass="b"] .pl-btn--primary {
  background: var(--pl-accent-text);
  color: #fff;
}
[data-colorpass="b"] .pl-btn--primary:hover { background: #B03A2F; }

/* c: the de-blue pass (2026-08-13). Different diagnosis after five rounds
   of adding warmth failed: the page reads "corporate blue" because its
   skeleton is blue - every heading navy, teal em, aqua hairlines. This
   tier subtracts instead: display headings go warm ink, the em goes
   readable coral, hairlines go sand. Aqua band and navy buttons stay -
   her aqua is brand, and one blue anchor is fine. Homepage scope only. */
[data-colorpass="c"] .ask h1,
[data-colorpass="c"] .areas__q,
[data-colorpass="c"] .meet__intro h2,
[data-colorpass="c"] .process > .pl-wrap > h2,
[data-colorpass="c"] .close > .pl-wrap > h2 { color: var(--pl-ink); }
[data-colorpass="c"] .ask h1 em { color: var(--pl-accent-text); }
[data-colorpass="c"] .areas,
[data-colorpass="c"] .process { border-color: #E7E1D6; }

/* d: the colour-blocked top (2026-08-13, from Chad's design-app mock,
   "Homepage C - Colour-Blocked Doors"). One butter highlight bar behind
   the hero em - a single solid block, not the sprayed swipes that got
   vetoed - and the three situation cards each take a pastel ground:
   cool aqua-grey, blush, pale butter. Navy titles and marks stay; the
   service names go readable coral. Band wash goes white so the cards
   carry all the colour. */
[data-colorpass="d"] .ask h1 em {
  color: var(--pl-logo);
  /* A real swipe, not a box: an inline SVG marker stroke - wobbly edges,
     angled ragged ends, lighter and darker streaks like felt-tip fibres -
     stretched across the lower ~58% of the line so it runs behind the
     letters' waists and never reaches the line above (line-height 1.08).
     Tune: background-size height = stroke thickness, position = how low. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 64' preserveAspectRatio='none'%3E%3Cpath fill='%23FFD34D' d='M9 16 C5 22 6 40 10 50 L18 54 C90 51 320 53 386 48 C393 44 394 24 389 14 L380 10 C300 14 90 8 16 12 Z'/%3E%3Cpath fill='%23FFD34D' opacity='0.65' d='M4 21 L10 17 L10 47 L5 41 Z'/%3E%3Cpath fill='%23FFD34D' opacity='0.6' d='M386 15 L394 19 L393 43 L385 47 Z'/%3E%3Cpath fill='%23F3BE3A' opacity='0.5' d='M12 44 C120 48 300 46 384 42 L384 47 C300 51 110 52 14 49 Z'/%3E%3Cpath fill='%23FFE38A' opacity='0.55' d='M14 18 C120 14 300 16 382 15 L382 19 C290 20 110 18 16 22 Z'/%3E%3Cpath fill='%23F3BE3A' opacity='0.3' d='M10 30 L388 27 L388 30 L10 33 Z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-size: 100% 58%;
  background-position: 0 80%;
  padding: 0 0.16em;
  margin: 0 -0.08em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}
[data-colorpass="d"] .areas {
  background: #fff;
  border-color: #EDE8DE;
}

/* Trial: the same marker stroke under every band title (Chad, 08-13,
   "just wanna see"). fit-content so the swipe hugs the words instead of
   painting the whole block. */
[data-colorpass="d"] .areas__q,
[data-colorpass="d"] .meet__intro h2,
[data-colorpass="d"] .process > .pl-wrap > h2,
[data-colorpass="d"] .close > .pl-wrap > h2 {
  width: fit-content;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 64' preserveAspectRatio='none'%3E%3Cpath fill='%23FFD34D' d='M9 16 C5 22 6 40 10 50 L18 54 C90 51 320 53 386 48 C393 44 394 24 389 14 L380 10 C300 14 90 8 16 12 Z'/%3E%3Cpath fill='%23FFD34D' opacity='0.65' d='M4 21 L10 17 L10 47 L5 41 Z'/%3E%3Cpath fill='%23FFD34D' opacity='0.6' d='M386 15 L394 19 L393 43 L385 47 Z'/%3E%3Cpath fill='%23F3BE3A' opacity='0.5' d='M12 44 C120 48 300 46 384 42 L384 47 C300 51 110 52 14 49 Z'/%3E%3Cpath fill='%23FFE38A' opacity='0.55' d='M14 18 C120 14 300 16 382 15 L382 19 C290 20 110 18 16 22 Z'/%3E%3Cpath fill='%23F3BE3A' opacity='0.3' d='M10 30 L388 27 L388 30 L10 33 Z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-size: 100% 58%;
  background-position: 0 80%;
  padding: 0 0.16em;
  margin-left: -0.16em;
}
/* d: every button and phone number goes peach. Fills take ink text;
   phone numbers become peach chips with the warm brown (#8a4a35) the
   mock used on its peach tags - raw peach text on white is 1.2:1 and
   unreadable. The footer tel sits on navy, where true peach is legible
   as plain text. */
[data-colorpass="d"] .pl-btn--primary,
[data-colorpass="d"] .site-header__cta {
  background: var(--pl-peach);
  border-color: var(--pl-peach);
  color: var(--pl-logo);
}
[data-colorpass="d"] .pl-btn--primary:hover,
[data-colorpass="d"] .site-header__cta:hover { background: #EFCBB4; border-color: #EFCBB4; }
[data-colorpass="d"] .pl-btn--outline {
  border-color: #E8BFA6;
  color: var(--pl-logo);
}
[data-colorpass="d"] .pl-btn--outline:hover { background: rgba(246, 219, 202, 0.35); }
/* Phone numbers stay stock navy (Chad's call after trying peach chips
   and warm brown) - the peach lives in the buttons, not the numbers. */
[data-colorpass="d"] .site-footer a[href^="tel:"] { color: var(--pl-peach); }


/* --- Deco lab v5: workbook page breaks (2026-08-13) -----------------------
   Chad's ask: the coloured section-divider pages from Elizabeth's
   workbooks, on the homepage. Each band title becomes a full-bleed
   colour strip - like turning to a section page in her printed
   workbook. Pastels follow the same progression as the D-tier cards
   (mint, peach, butter) with a deep teal close. Geometry lab is gone.
   Gated behind html[data-deco]; /?deco=a for the on/off switcher.
   View alone (?deco=a) or stacked with the colour lab (&colors=d). */

/* Two repairs, 2026-08-21, both present since this lab was written.

   1. The sections clip on the x axis. 100vw counts the scrollbar but the
      element's containing block does not, so every strip overhung the page by
      the scrollbar's width and the whole document scrolled 8px sideways.
      Clipping at the section is the fix that does not require measuring the
      scrollbar in JS. overflow-x, never overflow: the service sheets on the
      card band escape .areas vertically and have to keep doing so.

   2. .meet__intro is capped at 52ch, and calc(50% - 50vw) resolves that 50%
      against the PARENT, not the viewport - so the team strip was pulled 342px
      left of where it belonged and stopped 327px short of the right edge. The
      cap moves to the paragraph, which is what wanted a measure anyway. */
[data-deco] .areas,
[data-deco] .meet,
[data-deco] .process,
[data-deco] .close { overflow-x: clip; }
[data-deco] .meet__intro { max-width: none; }
[data-deco] .meet__intro p { max-width: 52ch; }

[data-deco] .areas__q,
[data-deco] .meet__intro h2,
[data-deco] .process > .pl-wrap > h2,
[data-deco] .close > .pl-wrap > h2 {
  width: 100vw;
  max-width: 100vw;
  margin-left: calc(50% - 50vw);
  padding-block: 1.15rem;
  padding-inline: max(var(--pl-gutter), calc((100vw - var(--pl-max-width)) / 2 + var(--pl-gutter)));
}
[data-deco] .areas__q { background: #DEECEA; }
[data-deco] .meet__intro h2 { background: #FAE4D6; }
[data-deco] .process > .pl-wrap > h2 { background: #FCEFC8; }
[data-deco] .close > .pl-wrap > h2 {
  background: var(--pl-primary);
  color: #fff;
}


/* --- Shapes lab (2026-08-17) ---------------------------------------------
   Chad asked for a direction other than glow. This is her workbook's own
   language: hard-edged colour blocks, no blur. Gated behind
   html[data-style="shapes"] (/?style=shapes, main.js "The style toggle").
   With it on, the glows switch off. Promote or delete when judged.

   - offset colour plates behind each card (paper on a coloured divider)
   - the open yellow frame from her estate workbook cover behind the film
   - a solid coral rule under "law-firm act" instead of the halo */



/* The film: a plain coral outline on the frame itself (Chad, replacing the
   offset butter frame). */
[data-style="shapes"] .film__frame video {
  border: 2px solid var(--pl-accent);
  box-sizing: border-box;
}

/* Shapes mode: the tucked peach glow (the law-firm-act treatment) behind
   each team member's name and the closing title. .glow-word is an inline
   span so the halo hugs the words themselves - centred titles and block-
   level names would otherwise glow across the whole row. Inert unless
   shapes mode is on. */
[data-style="shapes"] .glow-word {
  position: relative;
  isolation: isolate;
  display: inline-block;
}
[data-style="shapes"] .glow-word::before {
  content: '';
  position: absolute;
  inset: 42% -6% 4% -6%;
  border-radius: 999px;
  background: rgba(246, 219, 202, 0.95);
  filter: blur(10px);
  z-index: -1;
  pointer-events: none;
}
[data-style="shapes"] .close h2 .glow-word::before { filter: blur(14px); }

/* Team bubbles go peach (Chad, 2026-08-17): the hover speech bubbles on the
   team photos take the peach fill with the warm edge, in every mode -
   the same warmth as the play button's hover and the closing glow. */
[data-style="shapes"] .person__bubble {
  background: var(--pl-peach);
  border-color: #EBCFBC;
}
[data-style="shapes"] .person__bubble::after {
  background: var(--pl-peach);
  border-color: #EBCFBC;
}

/* Door-card colour accents (rim/chips/coral plus circles) were added and
   then reverted 2026-08-19 same evening (Chad: too much has changed) - the
   recipe lives in git history at commit 7b360df if it is ever wanted. */

/* The contact page layout (2026-08-19, replacing the migrated WP structure:
   a floating Hello over three orphan cards and a form squeezed beside a
   giant map). Form is the main event; everything else is a rail. */
/* --- Layout, rebuilt 2026-08-21 -------------------------------------------
   Was a 1.5fr form beside a 1fr rail. Measured, the form ran 1145px and the
   rail 533px, so 668px of column 516px wide sat empty - 53% of the section was
   white space on the right, which is exactly the split that made the page feel
   wrong. A row of three across the top cannot leave a void, and it puts the
   quick paths first, which is what most people open a contact page for. */
.contact-ways {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
  align-items: start;
}
.contact-layout { display: block; }
.contact-form h2 { margin-bottom: 1.5rem; }
/* The form fills the band now that nothing sits beside it, and the short
   fields pair up - eight stacked single-column fields is what made it 1145px
   long in the first place. */
/* .elementor-form is capped at 480px sitewide, which is right for the single
   column forms elsewhere and is why this one looked ragged inside its own card
   long before today. Released here, then the CARD is capped and centred
   instead - so the leftover space sits evenly either side as composition
   rather than dumped against the right edge as a void.
   900px gives two columns near 420px each, which is a comfortable field; a
   full-band 1329px form would have put 650px-wide inputs on a name. */
.contact-form { max-width: 900px; margin-inline: auto; }
.contact-form form {
  max-width: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(1rem, 2vw, 1.5rem);
}
.contact-form form > * { grid-column: 1 / -1; }
.contact-form form > .field--half { grid-column: span 1; }
@media (max-width: 620px) {
  .contact-form form > .field--half { grid-column: 1 / -1; }
}
/* --- The rail (rebuilt 2026-08-21) ---------------------------------------
   The page had no images and no icons at all, and its type went 41.6px to
   12.48px with nothing between - so the form shouted while the phone number,
   which is the whole reason anyone opens a contact page, whispered under it.

   Each way is an icon chip plus a body now, borrowing the chip straight from
   the practice cards: tinted rounded square, coloured stroke, colour in the
   fill rather than the mark. Same device, so the page stops being the one
   that speaks a different language. */
.contact-way {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 1rem;
  align-items: start;
}
.way__mark {
  width: 44px;
  height: 44px;
  padding: 10px;
  box-sizing: content-box;
  border-radius: 14px;
  background: var(--way-tint);
  border: 1px solid var(--way-edge);
  color: var(--way-ink);
  display: block;
}
.way__mark svg { display: block; width: 100%; height: 100%; }
.contact-way--call   { --way-tint: rgba(191, 221, 222, 0.38); --way-edge: #BFDDDE; --way-ink: #0C5F72; }
.contact-way--mail   { --way-tint: rgba(238, 122, 112, 0.10); --way-edge: rgba(238, 122, 112, 0.55); --way-ink: #C64438; }
.contact-way--social { --way-tint: rgba(255, 211, 77, 0.28); --way-edge: rgba(255, 211, 77, 0.90); --way-ink: #0C5F72; }

.contact-way h3 {
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--pl-accent-text);
  margin-bottom: 0.35rem;
}
.contact-way p { margin: 0; font-size: 0.98rem; line-height: 1.7; }
/* The value is the point of the card. It was set at body size under a label
   that was nearly as loud as it was.
   Scoped .contact-way .way__value (0,2,0) and not .way__value (0,1,0): the
   rule right above is .contact-way p, which at (0,1,1) beats a bare class and
   silently kept these at 15.68px on the first pass. */
.contact-way .way__value { font-size: 1.22rem; line-height: 1.4; }
.contact-way .way__value a { color: var(--pl-logo); font-weight: 700; text-decoration: none; border-bottom: 2px solid var(--pl-aqua); }
.contact-way .way__value a:hover { border-bottom-color: var(--pl-accent-text); }
.contact-way a { color: var(--pl-primary); font-weight: 700; }
/* Social links were stacked one per line by <br>, which made three short words
   occupy three rows. */
.way__links { display: flex; flex-wrap: wrap; gap: 0.25rem 1rem; }
.contact-muted { color: var(--pl-ink-soft); font-size: 0.9rem; }

/* --- Come by (2026-08-21) -------------------------------------------------
   Replaces the Google Maps iframe that used to sit in the rail. The firm has
   its own photography of the Shipyards; a page that says "come by" should show
   the place rather than a grey map tile. The address stays as text and the
   directions link still goes to Maps - a picture is an invitation, not
   directions. */
.contact-visit {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: clamp(1.75rem, 4vw, 3.5rem);
  /* start, not center: the photo is 453px and the words 275px, so centring
     pushed the heading 89px below the top of the picture and read as two
     things that failed to line up rather than as a deliberate composition. */
  align-items: start;
  padding-top: clamp(2.5rem, 5vw, 4rem);
}
.contact-visit__address { font-size: 1.22rem; line-height: 1.5; margin: 0 0 0.75rem; }
.contact-visit__note { color: var(--pl-ink-soft); max-width: 38ch; margin: 0 0 1.5rem; }
.contact-visit__photo { margin: 0; }
.contact-visit__photo img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--pl-radius-card);
  /* Same elevation grammar as the hero film: a large photograph on white needs
     a shadow that scales with it, plus a hairline for bright frames. */
  box-shadow:
    0 2px 6px rgba(26, 26, 26, 0.06),
    0 16px 40px rgba(26, 26, 26, 0.14),
    0 0 0 1px rgba(26, 26, 26, 0.06);
}
@media (max-width: 860px) {
  .contact-layout { grid-template-columns: 1fr; }
  .contact-visit { grid-template-columns: 1fr; }
  /* Photo first on a phone: the invitation lands before the logistics. */
  .contact-visit__photo { order: -1; }
}

/* The workbook nudge (2026-08-19, dormant behind intakeLive): appears under
   the service dropdown the moment a wills-family option is chosen. An inline
   card, never a popup - the enquiry in hand is worth more than any nudge,
   so the copy always offers the send-this-note-instead escape hatch. */
.workbook-nudge {
  background: #FBEFE7;
  border: 1px solid #EBCFBC;
  border-radius: 10px;
  padding: 0.9rem 1.1rem;
  margin: 0 0 1.25rem;
}
.workbook-nudge p { margin: 0; font-size: 0.9rem; line-height: 1.6; max-width: none; }
.workbook-nudge p + p { margin-top: 0.4rem; }
.workbook-nudge:not([hidden]) { animation: nudge-in 240ms ease; }
@keyframes nudge-in {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .workbook-nudge:not([hidden]) { animation: none; }
}

/* --- Blob lab (2026-08-21) ------------------------------------------------
   Three far-apart answers to an outside note that the page reads "too blue
   and corporate law", which measured true: navy is 54.3% of text ink and warm
   colour is 1.6% of background fill. Not one finished pass - three, so there
   is something to point at rather than a fait accompli to react to.

     ?style=blob1  Wash       huge, blurred, low-opacity. Atmosphere only.
     ?style=blob2  Paint      the literal ask. Gouache shapes, multiplied
                              where they overlap. Rounding bumped a step.
     ?style=blob3  Cut paper  flat, opaque, hard-edged, layered. Graphic and
                              committed. Rounding bumped hard.

   A switcher appears bottom-right on any of them (main.js, "The style
   toggle") so all three compare on the real page. The default is untouched:
   nothing here runs without the query param. Delete this block, the JS
   whitelist entries and the switcher when it is decided either way.

   Shared scaffolding. overflow-x: clip, never overflow: clip - the service
   sheets on the card band escape .areas vertically and must keep doing so,
   and overflow-x: hidden would force the y axis to auto and start scrolling
   the section. Blobs are decoration: no pointer events, behind the content,
   and nothing here animates, so the reduced-motion path is unaffected. */
[data-style^="blob"] .ask,
[data-style^="blob"] .areas,
[data-style^="blob"] .process,
[data-style^="blob"] .meet,
[data-style^="blob"] .close {
  position: relative;
  overflow-x: clip;
  isolation: isolate;
}
[data-style^="blob"] .ask > .pl-wrap,
[data-style^="blob"] .areas > .pl-wrap,
[data-style^="blob"] .process > .pl-wrap,
[data-style^="blob"] .meet > .pl-wrap,
[data-style^="blob"] .close > .pl-wrap { position: relative; z-index: 1; }

[data-style^="blob"] .ask::before,     [data-style^="blob"] .ask::after,
[data-style^="blob"] .areas::before,   [data-style^="blob"] .areas::after,
[data-style^="blob"] .process::before, [data-style^="blob"] .process::after,
[data-style^="blob"] .meet::before,    [data-style^="blob"] .meet::after,
[data-style^="blob"] .close::before {
  content: "";
  position: absolute;
  pointer-events: none;
  z-index: 0;
}

/* --- 1. Wash -------------------------------------------------------------
   Very large, very soft, very faint. The page still reads white and the
   colour arrives as light rather than as shape. The safest of the three for a
   firm whose estate pages are read at a bad moment. */
[data-style="blob1"] .ask::before {
  width: 720px; height: 640px; top: -220px; left: -180px;
  background: var(--pl-peach); opacity: 0.5; filter: blur(100px);
  border-radius: 52% 48% 61% 39% / 44% 57% 43% 56%;
}
[data-style="blob1"] .ask::after {
  width: 560px; height: 520px; bottom: -200px; right: -160px;
  background: var(--pl-butter); opacity: 0.24; filter: blur(110px);
  border-radius: 43% 57% 38% 62% / 55% 41% 59% 45%;
}
[data-style="blob1"] .areas::before {
  width: 680px; height: 600px; top: -160px; right: -220px;
  background: var(--pl-aqua); opacity: 0.55; filter: blur(100px);
  border-radius: 58% 42% 47% 53% / 39% 62% 38% 61%;
}
[data-style="blob1"] .areas::after {
  width: 520px; height: 480px; bottom: -180px; left: -140px;
  background: var(--pl-peach); opacity: 0.45; filter: blur(95px);
  border-radius: 46% 54% 55% 45% / 58% 43% 57% 42%;
}
[data-style="blob1"] .process::before {
  width: 760px; height: 560px; top: -180px; left: 50%; translate: -50% 0;
  background: var(--pl-peach); opacity: 0.4; filter: blur(110px);
  border-radius: 50% 50% 44% 56% / 47% 53% 47% 53%;
}
[data-style="blob1"] .meet::before {
  width: 600px; height: 540px; top: -140px; left: -200px;
  background: var(--pl-butter); opacity: 0.2; filter: blur(105px);
  border-radius: 55% 45% 40% 60% / 52% 48% 52% 48%;
}
[data-style="blob1"] .close::before {
  width: 640px; height: 520px; bottom: -220px; right: -180px;
  background: var(--pl-aqua); opacity: 0.5; filter: blur(100px);
  border-radius: 48% 52% 58% 42% / 43% 56% 44% 57%;
}

/* --- 2. Paint ------------------------------------------------------------
   The literal reading of the note. Mid-size gouache shapes at real opacity,
   only lightly softened, multiplying where they overlap so the seams carry a
   third colour the palette never declared. Rounding goes up one step. */
/* Cards only. --pl-radius-btn is deliberately NOT touched: the note at
   .pl-btn says that token is used by things that are not buttons and
   should stay at 8px, and the buttons already carry their own pill. */
[data-style="blob2"] { --pl-radius-card: 20px; }
[data-style="blob2"] .ask::before,     [data-style="blob2"] .ask::after,
[data-style="blob2"] .areas::before,   [data-style="blob2"] .areas::after,
[data-style="blob2"] .process::before, [data-style="blob2"] .process::after,
[data-style="blob2"] .meet::before,    [data-style="blob2"] .meet::after,
[data-style="blob2"] .close::before { mix-blend-mode: multiply; filter: blur(6px); }

[data-style="blob2"] .ask::before {
  width: 460px; height: 420px; top: -150px; left: -120px;
  background: var(--pl-peach); opacity: 0.85;
  border-radius: 61% 39% 44% 56% / 38% 63% 37% 62%; rotate: -8deg;
}
[data-style="blob2"] .ask::after {
  width: 300px; height: 280px; top: 30px; right: -90px;
  background: var(--pl-butter); opacity: 0.5;
  border-radius: 44% 56% 63% 37% / 57% 42% 58% 43%; rotate: 12deg;
}
[data-style="blob2"] .areas::before {
  width: 420px; height: 380px; top: -120px; right: -110px;
  background: var(--pl-aqua); opacity: 0.75;
  border-radius: 39% 61% 52% 48% / 62% 37% 63% 38%; rotate: 6deg;
}
[data-style="blob2"] .areas::after {
  width: 340px; height: 320px; bottom: -130px; left: -90px;
  background: var(--pl-peach); opacity: 0.8;
  border-radius: 57% 43% 38% 62% / 41% 59% 42% 58%; rotate: -14deg;
}
[data-style="blob2"] .process::before {
  width: 520px; height: 360px; top: -110px; left: -140px;
  background: var(--pl-butter); opacity: 0.42;
  border-radius: 48% 52% 60% 40% / 55% 45% 56% 44%; rotate: 4deg;
}
[data-style="blob2"] .process::after {
  width: 380px; height: 340px; bottom: -140px; right: -110px;
  background: var(--pl-peach); opacity: 0.7;
  border-radius: 63% 37% 45% 55% / 40% 61% 39% 60%; rotate: -6deg;
}
[data-style="blob2"] .meet::before {
  width: 400px; height: 360px; top: -120px; left: -130px;
  background: var(--pl-aqua); opacity: 0.6;
  border-radius: 52% 48% 39% 61% / 60% 41% 59% 40%; rotate: 9deg;
}
[data-style="blob2"] .meet::after {
  width: 300px; height: 300px; bottom: -110px; right: -80px;
  background: var(--pl-butter); opacity: 0.4;
  border-radius: 45% 55% 57% 43% / 44% 58% 42% 56%; rotate: -10deg;
}
[data-style="blob2"] .close::before {
  width: 480px; height: 400px; bottom: -160px; right: -120px;
  background: var(--pl-peach); opacity: 0.75;
  border-radius: 40% 60% 55% 45% / 58% 39% 61% 42%; rotate: 7deg;
}

/* --- 3. Cut paper --------------------------------------------------------
   No blur, no blending, no transparency games: flat opaque shapes with hard
   edges, layered and cropped by the section like torn paper. The most
   committed of the three, and the one that will read least like a law firm.
   Rounding goes up hard to match. */
/* Cards only. --pl-radius-btn is deliberately NOT touched: the note at
   .pl-btn says that token is used by things that are not buttons and
   should stay at 8px, and the buttons already carry their own pill. */
[data-style="blob3"] { --pl-radius-card: 28px; }
[data-style="blob3"] .ask::before {
  width: 520px; height: 470px; top: -190px; left: -150px;
  background: #FDEBE0;
  border-radius: 58% 42% 47% 53% / 40% 61% 39% 60%; rotate: -6deg;
}
[data-style="blob3"] .ask::after {
  width: 260px; height: 240px; top: 60px; right: -70px;
  background: #FFF0C2;
  border-radius: 47% 53% 61% 39% / 56% 43% 57% 44%; rotate: 14deg;
}
[data-style="blob3"] .areas::before {
  width: 470px; height: 430px; top: -150px; right: -130px;
  background: #E4F1F1;
  border-radius: 42% 58% 53% 47% / 61% 38% 62% 39%; rotate: 8deg;
}
[data-style="blob3"] .areas::after {
  width: 330px; height: 310px; bottom: -120px; left: -80px;
  background: #FDEBE0;
  border-radius: 59% 41% 40% 60% / 43% 58% 42% 57%; rotate: -12deg;
}
[data-style="blob3"] .process::before {
  width: 560px; height: 400px; top: -140px; left: -160px;
  background: #FFF0C2;
  border-radius: 50% 50% 58% 42% / 54% 46% 55% 45%; rotate: 5deg;
}
[data-style="blob3"] .process::after {
  width: 360px; height: 330px; bottom: -130px; right: -100px;
  background: #FDEBE0;
  border-radius: 62% 38% 46% 54% / 41% 60% 40% 59%; rotate: -8deg;
}
[data-style="blob3"] .meet::before {
  width: 430px; height: 390px; top: -130px; left: -140px;
  background: #E4F1F1;
  border-radius: 53% 47% 41% 59% / 59% 42% 58% 41%; rotate: 10deg;
}
[data-style="blob3"] .close::before {
  width: 500px; height: 420px; bottom: -170px; right: -130px;
  background: #FDEBE0;
  border-radius: 41% 59% 56% 44% / 57% 40% 60% 43%; rotate: 6deg;
}

/* --- Kit 1 components pass (2026-08-21) -----------------------------------
   /?kit=on. Chad went back to the brandkit and found components we never
   built. This is those components, nothing invented.

   Source: Desktop\Paperclip Law\paperclip-law-brandkits\breakdown.html, the
   "Components" section. Its palette block is Kit 1 and matches this site's
   tokens exactly - petrol teal #0E6B80, coral #EE7A70, butter #FFD34D, aqua
   #BFDDDE, peach #F6DBCA, paper #FDFBF7 - so nothing here is a new colour.

   What the kit drew and the site never used: a set of category chips, one per
   practice area, each a filled pill with its own readable text colour.

       Wills          #BFDDDE fill / #0E6B80 text
       Incorporation  #F6DBCA fill / #8a4a35 text
       Real Estate    #FFD34D fill / #5c430a text

   Measured on the real render, the peach and butter pairings clear AA at
   5.11 and 6.49. The aqua one does not: the kit's #0E6B80 on #BFDDDE is
   4.26:1, under the 4.5 floor. That is the kit's own pairing failing, not a
   transcription error, so the teal is taken one step down to #0C5F72 - the
   nearest value that clears, at 5.05. The fill stays exactly as drawn.

   Also from the kit: its headings are petrol teal #0E6B80. The site sets
   --pl-logo #00324E, a navy that appears nowhere in the brandkit, and that
   token paints every heading and the footer - 54.3% of all text ink on the
   homepage. It is the single largest block of colour on the site and it is
   off-kit. Switched here so the difference can be seen rather than argued.

   html[data-kit] rather than [data-kit]: the .home rules sit at (0,2,0) and
   would otherwise tie and be settled by source order. */
html[data-kit] {
  --pl-logo: #0E6B80;
}

/* The two words doing the differentiating go coral. Butter and peach were both
   tried on 2026-08-21 and neither can carry type: measured on white, the whole
   Kit 1 palette reads
     petrol teal #0E6B80  6.12  passes
     coral       #C64438  4.90  passes
     coral       #EE7A70  2.74  fails
     aqua        #BFDDDE  1.44  fails
     butter      #FFD34D  1.43  fails
     peach       #F6DBCA  1.32  fails
     paper       #FDFBF7  1.03  fails
   Two of seven can be ink on white. The warm half is a surface family. */
/* The headline itself takes the site's darker blue (Chad, 2026-08-21), not the
   petrol teal the rest of the kit pass puts on headings. #00324E is the navy
   --pl-logo carries by default - the one the site already has - so this is the
   hero opting out of the kit's heading colour rather than a new value. 13.41:1
   on white. The em below stays coral and still wins on specificity. */
html[data-kit] .ask h1 { color: #00324E; }
/* Chad: "why does it look orange instead of coral?" - because it was the wrong
   coral for the job. Both corals sit at hue 5; what differs is everything else:

     --pl-accent      #EE7A70   S 79  L 69   2.74:1
     --pl-accent-text #C64438   S 56  L 50   4.90:1

   Coral's identity lives in being light. Dropping it 19 points of lightness and
   23 of saturation stops it reading as coral and starts it reading as brick.

   The mistake was mine and it was a floor mistake: --pl-accent-text is the
   colour for things that are READ, rated to 4.5:1 for body copy. This headline
   is 56.8px, which is large text, so it only owes 3:1 - and I put a body-copy
   colour on it, overshooting by nearly two points of contrast and paying for it
   in hue.

   #EC6B5F is the lightest value on coral's own hue-and-saturation ramp that
   still clears 3:1. Four lightness points off the true brand coral, full 79%
   saturation kept.

   IT IS ONLY LEGAL AT THIS SIZE. 3.07:1 has no room in it. Never reuse this
   value on anything smaller than 24px, or bold under 18.66px - that is what
   --pl-accent-text exists for. */
html[data-kit] .ask h1 em { color: #EC6B5F; }

/* And the eyebrow comes off coral, because with the em coral the hero opened
   on the same colour twice in a row (Chad: "coral then coral"). It takes the
   headline's own teal instead, so the hero reads locator, headline, then one
   accent - rather than two accents and a headline between them. 6.12:1 at
   11.5px, past the 4.5 small text owes. */
html[data-kit] .ask__eyebrow span { color: var(--pl-logo); }

/* NOW DEAD, removed 2026-09-20 (Direction 2 migration cleanup): the Kit 1
   chip/pill styling for .area-cardset/.area-card__mark/.svc__name, the "Card
   top lab" (?cardtop=1|2|3), and their reduced-motion rules - all of it only
   ever targeted the pre-migration .area-cards homepage markup, which
   src/_includes/home/wave-cards.njk (stage 3) replaced. Nothing on the site
   renders .area-cardset/.area-card any more (see MIGRATION-D2.md, stage 3's
   dead-code note); the wave cards have their own CSS block below, stage 3. */

/* --- The film's wire and its runtime (2026-08-21) -------------------------
   Two additions to the hero film, both progressive: the markup is inert until
   main.js runs, so no-JS still gets exactly a poster and a play button.

   THE RUNTIME. The firm's promise is a real answer and a price before you
   commit to anything. Telling the visitor how long the film is before they
   press play is that promise applied to the player. It is read from the
   file's own metadata rather than typed, so it stays true when Elizabeth's
   hello replaces this 15 second reel. It hides on engage, because from that
   point the native controls carry a real timeline and two are worse than one.

   THE WIRE. A hairline that fills as the film runs with the firm's own clip
   riding the leading edge - the same "an object travels the line" grammar the
   process band already uses for the envelope, which is why it reads as part
   of this site rather than as a media player dropped into it.

   Inset from the edges rather than flush: the video carries the card radius,
   and a full-bleed bar would cut across its rounded corners. */

.film__time {
  position: absolute;
  left: 50%;
  /* Directly under the 66px disc, which is where the eye already is when it
     is deciding whether to press. */
  top: calc(50% + 45px);
  translate: -50% 0;
  z-index: 3;
  font-family: var(--pl-font-body);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: #8a4a35;
  background: #FBEFE7;
  padding: 0.22rem 0.5rem;
  border-radius: 999px;
  pointer-events: none;
  /* Its own ground, not the video's: over a frame of unknown content nothing
     else can be relied on to keep it readable. 5.98:1 on this blush. */
  opacity: 0;
  transition: opacity 200ms ease;
}
.film__time.is-shown { opacity: 1; }

.film__wire {
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 12px;
  height: 2px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.34);
  /* The track sits on video, so it carries its own separation rather than
     trusting whatever frame is underneath. */
  box-shadow: 0 1px 3px rgba(26, 26, 26, 0.35);
  z-index: 3;
  opacity: 0;
  transition: opacity 240ms ease;
  pointer-events: none;
}
/* Only while it is actually running. At rest the film is a poster and a play
   button, and a dead scrubber on it would be furniture. */
.film__wire.is-live { opacity: 1; }

.wire__fill {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--pl-accent-text);
  transform-origin: left center;
  /* scaleX rather than width: it stays on the compositor, so a timeupdate
     landing every frame costs no layout. */
  transform: scaleX(var(--film-progress, 0));
}

.wire__clip {
  position: absolute;
  top: 50%;
  left: calc(var(--film-progress, 0) * 100%);
  translate: -50% -50%;
  width: 20px;
  height: 20px;
  color: var(--pl-accent-text);
  filter: drop-shadow(0 1px 3px rgba(26, 26, 26, 0.4));
}

@media (prefers-reduced-motion: reduce) {
  /* The progress itself stays - it is information, not decoration - but it
     arrives without a fade. */
  .film__time, .film__wire { transition: none; }
}

/* --- The hero wave (2026-08-21) -------------------------------------------
   /?wave=on. Chad's reference was a stock "abstract wave gradient line"
   vector; this is the same construction done in maths - 34 sampled paths
   phase-shifted against one shared envelope, which is what the Illustrator
   blend tool produces - in her own colours rather than the reference's
   pink-to-orange.

   WHERE IT SITS IS THE WHOLE DESIGN. The coral on "law-firm act" clears its
   floor by two per cent (3.07:1 against 3:1). Anything coloured passing behind
   that word takes it under. So the ribbon's envelope peaks across the middle
   of the section - behind the film - and tapers to nothing at both ends, and
   the type sits above it in the stacking order on plain white.

   Hidden by default. Nothing renders without the query param. */
.ask__wave { display: none; }
html[data-wave="hero"] .ask { position: relative; overflow-x: clip; isolation: isolate; }
html[data-wave="hero"] .ask__wave {
  display: block;
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  /* Wider than the section so the tapered ends fall outside the viewport
     rather than stopping visibly inside it. */
  width: 128%;
  height: 100%;
  z-index: 0;
  opacity: 0.55;
  pointer-events: none;
}
/* Everything in the hero rides above it. .pl-wrap already carries z-index 1
   from the centred-homepage block; this is the film's own stacking, which sits
   inside that. */
html[data-wave="hero"] .ask > .pl-wrap { position: relative; z-index: 1; }

/* --- The wave as a page break (2026-08-21) --------------------------------
   /?wave=divider (or bare ?wave=on). Chad's call, and a better home for it
   than the hero: nothing sits behind type, so the coral em keeps its plain
   white and its 3.07:1, and a wave used as a rule reads far less like the
   stock vector it came from than a wave used as a backdrop. It is also
   already item 12 on Elizabeth's colour menu - "a bent-wire divider between
   sections" - so it is a thing she has been asked about rather than a new
   idea landing on her.

   A background-image rather than markup: one cached file serves every break,
   there is nothing to inject, and no element to keep out of the accessibility
   tree. preserveAspectRatio="none" in the file lets it stretch to any width
   without the bundle thinning out at the ends.

   The aqua hairline it replaces is switched off where the wave lands, or the
   two read as two dividers stacked. */
html[data-wave="divider"] .areas,
html[data-wave="divider"] .process { position: relative; border-top-color: transparent; }
html[data-wave="divider"] .areas::before,
html[data-wave="divider"] .process::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  /* Crosses the seam rather than sitting under it, but biased upward: dead
     centre left only 11px between the bundle and the heading below, and the
     section above has far more room to give than the one below. */
  top: 0;
  translate: 0 -62%;
  height: 84px;
  background: url("/assets/img/divider-wave.svg") center / 100% 100% no-repeat;
  pointer-events: none;
  z-index: 1;
}
/* Below about 960px, stretching a 1440-wide viewBox into the viewport squeezes
   the wave's cycles into a quarter of their drawn length - measured 3.8x at
   375, which turns a languid ribbon into a steep scribble. Past that point it
   keeps its own proportions and the viewport crops it instead. */
@media (max-width: 960px) {
  html[data-wave="divider"] .areas::before,
  html[data-wave="divider"] .process::before {
    background-size: auto 100%;
  }
}
/* The bands' own content has to clear it. */
html[data-wave="divider"] .areas > .pl-wrap,
html[data-wave="divider"] .process > .pl-wrap { position: relative; z-index: 2; }

/* --- Butter finally gets a job, and the page arrives somewhere (2026-08-21) --

   THE STAMP GOES BUTTER. Across the process and close bands, teal appears 24
   times and coral 22; peach appears once, as this pill; butter appears zero
   times. The token's own note says butter is for "section bars, highlights",
   and "A real answer, and a price" is the page's one genuine highlight - the
   claim no competitor can copy. It was sitting on #FBEFE7, four per cent off
   white, so the boldest statement on the page was rendered in the faintest
   way available.

   The ink has to move with it. Coral on butter measures 3.43:1, worse than the
   4.34 it was already holding knowingly. Teal clears at 5.07, so this swap
   buys the bolder colour AND settles the one contrast debt on this element
   rather than trading one for the other. */
html[data-kit] .steps__stamp {
  background: var(--pl-butter);
  border-color: #EFC53A;
  color: #0C5F72;
}


/* --- The reply clock becomes the feature (2026-08-21) ---------------------
   The close band was ending on a generic CTA block. The one thing in it that
   no other firm has is the live sentence - "It is Sunday 2:47pm in North
   Vancouver, so a note sent today gets an answer on Monday" - which rewrites
   itself every minute and openly admits the firm is shut at weekends.

   It was set at 14.72px: the same size as the address line, under a 30.4px
   heading and a 16.3px lede. The most distinctive sentence on the page was
   the smallest thing in its own band.

   No fill, no ornament, no new device. The words and their order are exactly
   as they were - this is hierarchy applied to content that already existed and
   already worked. */
html[data-kit] .close__note {
  font-size: 1.18rem;
  line-height: 1.6;
  max-width: 34ch;
  margin-left: auto;
  margin-right: auto;
  color: var(--pl-ink-soft);
}
/* The live half carries the weight, so the eye lands on the part that is
   actually true right now rather than on the boilerplate in front of it. */
html[data-kit] .clock__now {
  color: var(--pl-logo);
  font-weight: 700;
}
/* And the policy line steps back. It is a real promise and it stays, but it is
   the least surprising thing in the sentence. */
html[data-kit] .clock__policy {
  display: block;
  /* Direction 2 migration, stage 1 (2026-09-20): raised to the 13px floor. */
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--pl-ink-soft);
  margin-bottom: 0.55rem;
}

/* --- /inquire/ (2026-08-21) -----------------------------------------------
   The destination of every CTA on the site, and it was a 1210px single-column
   form in a 334px well with one heading, no phone number, no email address and
   no statement of what happens next.

   It reuses /contact/'s classes rather than growing a second implementation:
   .contact-ways, .contact-way and .contact-form are all shared. */
/* NEVER put a max-width on .inquire-head itself: it also carries .pl-wrap,
   which is max-width 1680 with margin:0 auto, so capping it at 46ch collapsed
   the whole section to 442px and centred it - the heading ended up floating in
   the middle-right of the page with the ways row still running full width
   underneath. The measure belongs on the children. */
/* The head shares the column too. It was landing at the wrap's gutter (48)
   while the ways and the form sat at 263, so the eye had two left edges to
   track down one page. A form page reads as a single centred column - the
   whitespace is symmetric, so there is no void of the kind the contact rail
   produced. */
.inquire-head__inner { max-width: 900px; margin-inline: auto; }
.inquire-head h1 { margin-bottom: 0.5rem; max-width: 18ch; }
.inquire-head .ask__lede { max-width: 52ch; }

/* Narrowing this to 900 for TWO cards is fine and lines them up with the form.
   For THREE it is not: card padding is 48px a side, the icon chip is 66, and a
   900px row split three ways left each body 72px wide - the phone number
   wrapped onto three lines and the email ran outside its own card. So the
   narrow column is opt-in, and /contact/ keeps the full band its three ways
   need. */
.contact-ways--narrow { max-width: 900px; margin-inline: auto; }
/* In the narrow column the icon stacks above the body rather than sitting
   beside it. Beside it, a 390px card minus 96px of padding and a 66px chip
   left 210px for the value, and hello@papercliplaw.com needs about 215 - so
   the address ran outside its own card by a few pixels. Stacked, the value
   gets the card's full 294px and stays on one line. */
.contact-ways--narrow .contact-way { grid-template-columns: minmax(0, 1fr); gap: 0.85rem; }
/* A long value must never escape its card, whatever anyone types into the CMS
   later. This is the belt to the stacking's braces. */
.way__value { overflow-wrap: anywhere; }

/* Same pairing as the contact form. Nine fields stacked one per row is what
   made this 1210px tall. */
/* The grid for this form is declared once, at the /contact/ block above,
   and specialised to six columns below. Do not redeclare it here. */

/* Only the message spans. A single-line input at 802px is a long way for the
   eye to travel for a company name, and three of them stretched full width
   between 389px pairs put two different scales in one form. Everything on one
   line is now a pair; the textarea is the only thing that earns the width. */
.contact-form form textarea {
  /* And it earns some height too. It was 120px - the same visual weight as a
     name field - for the one question the whole site drives toward. */
  min-height: 190px;
}

/* The clock sits under the send button rather than in a footer: it is the last
   thing read before committing, which is the whole point of moving it here. */
.inquire-clock {
  margin-top: 1.25rem;
  max-width: 46ch;
}

/* --- /inquire/ fits one screen (2026-08-21) -------------------------------
   Chad's constraint: the whole page, heading to send button, visible without
   scrolling. At 1080p that is about 862px under the sticky header, and the
   page needed roughly 1560. Every number below is spent against that budget.

   What went, and why it was affordable: Company and How-did-you-find-us are
   marketing data rather than qualifying data, and the Worker collects fields
   generically and only requires email plus a message - it renders whatever
   arrives and skips what does not. The two contact cards cost ~200px of height
   to say two lines' worth; they are one line now.

   This is a deliberate trade. A form this compressed is less comfortable than
   one that breathes, and it only holds on a desktop screen - narrow viewports
   fall back to stacked and scroll, which is correct. */
.inquire-reach {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.75rem;
  margin: 0.9rem 0 0;
  font-size: 1rem;
}
.reach__item { display: inline-flex; align-items: center; gap: 0.45rem; }
.reach__item svg { width: 18px; height: 18px; color: var(--pl-accent-text); flex: none; }
.reach__item a { color: var(--pl-logo); font-weight: 700; text-decoration: none; border-bottom: 2px solid var(--pl-aqua); }
.reach__item a:hover { border-bottom-color: var(--pl-accent-text); }

/* Three across for the short fields, and a tighter rhythm throughout. 93px a
   row was comfortable; it is 20px of that in margin alone. */
.contact-form form { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.contact-form form > * { grid-column: 1 / -1; }
.contact-form form > .field--half { grid-column: span 3; }
.contact-form form > .field--third { grid-column: span 2; }
.inquire-head + * .elementor-field-group,
.contact-form form .elementor-field-group { margin-bottom: 0.9rem; }
.contact-form form .elementor-field-label { margin-bottom: 0.25rem; }
/* Three fields share row two and their labels are not the same length: "What
   services are you interested in? *" wraps to two lines at this width while
   "Email *" does not, which left that select sitting 20px below its
   neighbours. Grid already stretches every cell to the row height, so making
   the cell a column and pushing the control to its foot lines the inputs up
   whatever the labels above them do. */
.contact-form form .elementor-field-group { display: flex; flex-direction: column; }
.contact-form form .elementor-field-group > .elementor-field { margin-top: auto; }
/* The bottom-align rule above turns every field cell into a column, which is
   right for a label over a control and wrong for a checkbox group: it stacked
   the buying/selling pair that is meant to read as one either-or question.
   This group opts back out so its options stay on a row that wraps. */
.contact-form form .elementor-field-group.form-choice { display: block; }
/* 108px, not 132. Sixteen pixels of headroom against a 940px viewport is not
   headroom - a bookmarks bar or a slightly taller browser chrome eats it and
   the constraint silently fails. This buys the margin back from the one place
   that can afford it without losing a field. */
.contact-form form textarea { min-height: 108px; }
/* The consent line is legal boilerplate, not copy anyone reads by choice. */
.contact-form .form-consent { font-size: 0.82rem; line-height: 1.45; margin-bottom: 0.9rem; }
/* The card's own 48px of padding is 96px of the budget. */
.contact-form .pl-card { padding: 2rem; }
/* The clock rides beside the button instead of under it - same information,
   one row instead of two. */
.inquire-clock { margin-top: 0.85rem; font-size: 1rem; max-width: 62ch; }

/* Checkbox groups inside an enquiry form. The buying/selling pair on the real
   estate landing page was the only one on the site and it shipped completely
   unstyled - two bare browser checkboxes with the label text hard against
   them. Rows are 44px so the tap target clears the minimum the 08-21 critique
   set, and the options sit in a row that wraps rather than stacking, because
   two short choices stacked read as a list of two unrelated questions. */
.form-choice__opt {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 44px;
  margin-right: 1.25rem;
  cursor: pointer;
}
.form-choice__opt input { width: 20px; height: 20px; accent-color: var(--pl-accent-text); flex: none; }

/* The head sits BESIDE the form, not above it. Stacked, the heading, lede and
   contact line cost 339px of the 940px budget before the form even started -
   side by side the band is only as tall as the form itself, which is the
   single biggest saving available and the one that does not come out of the
   form's comfort. */
.inquire-split {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: start;
  /* 56px top and bottom was 112 of the budget on this section alone. */
  padding-top: 1.5rem;
  padding-bottom: 1.5rem;
}
.inquire-split .inquire-head__inner { max-width: none; margin-inline: 0; }
.inquire-split .contact-form { max-width: none; margin-inline: 0; }
/* 2026-09-20: stepped up from clamp(2.1rem, 3.4vw, 2.9rem) when the sitewide h1 moved from
   Playfair to Instrument Serif, which runs narrower and lighter at the same size. */
.inquire-split h1 { font-size: clamp(2.5rem, 3.9vw, 3.6rem); max-width: 14ch; }
.inquire-split .ask__lede { max-width: 38ch; }

@media (max-width: 900px) {
  /* Below this the two columns would each be too narrow to be worth having.
     It stacks and scrolls, which is the honest behaviour on a small screen -
     one-screen was never reachable there. */
  .inquire-split { grid-template-columns: 1fr; padding-top: 2.5rem; }
}

@media (max-width: 720px) {
  /* Below this the one-screen goal is not reachable or desirable; everything
     stacks and the page scrolls like any other form. */
  .contact-form form > .field--third,
  .contact-form form > .field--half { grid-column: 1 / -1; }
}

/* --- The ways as linked cards (2026-08-21) --------------------------------
   From the reference Chad sent: the contact routes stack down the column
   beside the form, each one a card with an icon, a label, a value and an
   affordance on the right. Taken as structure only - the reference is a dark
   neon theme and this is a law firm on white.

   The whole card is the link, not a link inside a card. A 300px target beats
   a 200px string, and it means the arrow needs no separate tab stop. */
.inquire-ways { display: grid; gap: 0.75rem; margin-top: 1.5rem; }
.contact-way--link {
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.9rem;
  padding: 0.9rem 1rem;
  text-decoration: none;
  color: inherit;
  transition: border-color 180ms ease, box-shadow 180ms ease, transform 180ms ease;
}
.contact-way--link .way__mark { width: 22px; height: 22px; padding: 9px; }
.contact-way--link .way__body { display: block; min-width: 0; }
.way__label {
  display: block;
  font-family: var(--pl-font-body);
  font-weight: 800;
  font-size: 0.7rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--pl-accent-text);
  margin-bottom: 0.1rem;
}
.contact-way--link .way__value {
  display: block;
  font-size: 1rem;
  font-weight: 700;
  color: var(--pl-logo);
  /* No underline here: the card is the affordance, and a border under a value
     inside a card that is already a link reads as two controls. */
  border-bottom: 0;
  overflow-wrap: anywhere;
}
.way__go {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--pl-aqua);
  color: var(--pl-logo);
  transition: background 180ms ease, color 180ms ease, border-color 180ms ease;
}
.way__go svg { width: 15px; height: 15px; }
.contact-way--link:hover { transform: translateY(-1px); }
.contact-way--link:hover .way__go,
.contact-way--link:focus-visible .way__go {
  background: var(--pl-logo);
  border-color: var(--pl-logo);
  color: #fff;
}
/* Butter, not aqua (Chad, 2026-08-25). Two reasons it is the right chip to
   move: "Call us" was already aqua, so the come-by pin was the second aqua
   chip in a column of three, and the butter recipe is not a new colour - it is
   the one .contact-way--social already carries, so both contact pages now run
   one aqua, one coral, one butter. Ink stays #0C5F72: butter is 1.43:1 on
   white and can never be the stroke itself, only what sits behind it. */
.contact-way--visit { --way-tint: rgba(255, 211, 77, 0.28); --way-edge: rgba(255, 211, 77, 0.90); --way-ink: #0C5F72; }

/* Full-width submit, as in the reference: on a card this wide a 164px button
   floating at the left reads as unfinished. */
.contact-form form .elementor-button { width: 100%; }

@media (prefers-reduced-motion: reduce) {
  .contact-way--link { transition: none; }
  .contact-way--link:hover { transform: none; }
}

/* --- Peach sweep lab (2026-08-25) ----------------------------------------
   Chad's reference tile: "Right sweep - text-left heroes, peach".

   NO LONGER LAB ONLY as of 2026-08-25: variant a is the real style on
   /contact/ and /inquire/, set by `sweep: a` in each page's front matter,
   which base.njk turns into data-sweep on <html>. Every other page renders
   nothing, so what Elizabeth holds is unchanged outside those two. b and c
   stay reachable with /?sweep=b|c for comparison, switcher bottom-right.

   Page level rather than hero level on purpose: the two contact pages do not
   share a hero. /inquire/ runs a text-left column, which is what the tile is
   drawn for; /contact/'s .ask--work centres its words (margin-inline auto),
   so a right-hand sweep sits behind centred text there rather than beside it.
   Worth seeing both before deciding whether /contact/ goes text-left.

   This is colour-on-areas, which is the family that has failed twice on this
   palette (full peach "way too loud", the golden-hour gradient "cool but not
   professional"). Kept light and kept behind the type for that reason. */
/* Anchored to the document, not the viewport (Chad, 2026-08-25). It was fixed,
   which meant the curve stayed glued to the screen: scroll down and the same
   bend is still sitting in the same place, so the shape reads as following you
   down the page rather than being part of it. Absolute against body with top
   and bottom both pinned makes it exactly one shape as tall as the whole
   document, which is the point - it runs through the entire page and you
   scroll past it. preserveAspectRatio="none" on the SVG is what lets the one
   curve stretch the full height instead of tiling. */
html[data-sweep] body { position: relative; }
html[data-sweep] body::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(62%, 900px);
  z-index: 0;
  pointer-events: none;
}
/* Content rides above the sweep.

   .site-header is deliberately NOT in this list, and putting it there was a
   real bug (2026-08-25). At (0,2,1) this selector beats .site-header's own
   (0,1,0), so on the two pages carrying data-sweep it replaced
   position:sticky with relative and dropped z-index 50 to 1. The header
   stopped sticking, and the mobile drawer - which is absolutely positioned
   inside the header - was left in a z-index 1 stacking context with page
   content able to paint over it. The header never needed the help: sticky
   already positions it, and 50 is already above the sweep's 0. */
html[data-sweep] main,
html[data-sweep] footer { position: relative; z-index: 1; }

/* a - the tile: a single curved edge, peach, full height. */
html[data-sweep="a"] body::before {
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cpath fill='%23F6DBCA' d='M58,0 C58,25 30,40 32,62 C34,84 48,100 62,100 L100,100 L100,0 Z'/%3E%3C/svg%3E") no-repeat right center / 100% 100%;
}
/* b - blush instead of peach, rising from the bottom right. Lighter and lower,
   so the top of every page stays white and the colour arrives as you scroll. */
html[data-sweep="b"] body::before {
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cpath fill='%23FBEFE7' d='M100,30 C76,32 52,52 40,76 C34,87 31,95 29,100 L100,100 Z'/%3E%3C/svg%3E") no-repeat right center / 100% 100%;
}
/* d - the sweep along the bottom instead of down the right (Chad, 2026-08-25).
   Every rule in the base block above is written for a right-hand column, so
   this one has to unset all four of them: top goes auto, left comes in, width
   goes auto and height takes over. Anchored to the foot of the DOCUMENT, not
   the viewport, for the same reason a is - it stays where it is on the page
   and you scroll down onto it.

   The consequence to look at: a right sweep carries colour past every screen
   of the page, and a bottom one does not. The hero arrives on plain white and
   the peach only appears as you reach the end. On /contact/ that puts it
   under "Come by the Shipyards", which is the warmest thing on the page
   anyway, so it may be the better home for it. */
html[data-sweep="d"] body::before {
  top: auto;
  left: 0;
  right: 0;
  bottom: 0;
  width: auto;
  height: min(55%, 900px);
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cpath fill='%23F6DBCA' d='M0,68 C30,66 52,30 100,22 L100,100 L0,100 Z'/%3E%3C/svg%3E") no-repeat center bottom / 100% 100%;
}
/* e - both sweeps at once, down the right AND along the foot. Built and
   REJECTED on sight, 2026-08-25 ("both doesn't work"). Do not rebuild it.
   Two overlapping areas of #F6DBCA came to roughly 40% of the page, and this
   palette's design law has held every time it has been tested: colour on
   objects wins, colour on areas loses. Full peach was "way too loud" on 08-19
   and this was further in the same direction, not less. The right shape also
   ran 538px into the content column at 1905, so it sat behind the rail and a
   third of the form rather than beside them. /contact/ is back on d. */
/* w - the four-band wave ribbons from Chad's reference image. Built
   2026-08-25 and dropped the same day; /contact/ went back to d. Not a
   failure of the build - the structure, colour order and band rhythm all
   matched - it just was not wanted on the page. The recipe, if it is ever
   asked for again: one curve per corner drawn four times, each copy
   translated ~68px further into its corner and painted innermost first, so
   the opaque fills leave slivers that become the bands. Top-right aqua,
   peach, butter, coral inward to out; bottom-left coral, peach, butter,
   coral. Full paths are in commit 74c7548. Do not re-pitch it unprompted. */
/* c - no edge at all: peach as light falling into the corner. The soft option,
   for whether it is the colour or the hard curve that reads as loud. */
html[data-sweep="c"] body::before {
  background: radial-gradient(120% 90% at 100% 0%, #F6DBCA 0%, rgba(246, 219, 202, 0.55) 38%, rgba(246, 219, 202, 0) 72%);
}

/* --- /contact/ split top (2026-08-25) -------------------------------------
   The page was measured at eight distinct left edges, the ink stepping
   336 - 413 - 48 - 232 - 48 - 619 down it. Three sections, three measures,
   none of them related: a centred hero, a full-band row of ways, and a 900px
   card centred inside it. The widest element on the page sat directly above
   the narrowest with nothing holding them together.

   One spine fixes it. The words and the ways share the hero band, the form
   sits under the words rather than under the whole page, and every block
   starts at the wrap's gutter. */
/* Capped at 1180, and this is the fix for the thing that looked wrong on a
   1920 screen. .pl-wrap runs to --pl-max-width 1680, so the words column was
   1252px wide while the words themselves stopped at a 46ch measure of 440.
   Measured on Chad's screen: 765px of nothing between the end of the lede and
   the start of the rail, and 684px of nothing to the right of the form. The
   page read as two things pinned to opposite edges of the monitor.

   A cap is the structural fix rather than a wider measure: the column stops
   growing, so the rail sits beside the words instead of against the far edge,
   and the whole page centres on a wide monitor instead of spreading. */
.contact-top__inner,
.contact-write,
.contact-visit { max-width: 1180px; margin-inline: auto; }
/* The hero is words only now. The rail beside it was pulled 2026-08-25 ("not
   feeling it") - the ways moved to a row across the top of the form, where
   they share its column and line up on both edges instead of hanging off the
   corner. Do not put the grid back here. */
/* No measure on the words now that the column itself is capped - the headline
   uses the column it is given, which puts "Tell us what is going on." back on
   one line. Only the lede keeps a measure, because a lede is read as prose. */
.contact-top__words { max-width: none; }
.contact-top__words .ask__lede { max-width: 50ch; }
/* One card per row in a 380px column. .contact-ways is auto-fit, so it would
   land on one column here by itself - this states it rather than relying on
   the arithmetic holding if the column ever widens. */
/* Three across the form's column, explicit rather than auto-fit: auto-fit at
   this width lands on two and orphans the third, the same left-aligned
   remainder the staff row had. */
.contact-ways--row { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* stretch, overriding the base row's align-items:start. Their contents are
   not the same shape - two cards carry a single value line and the third
   carries three inline links - so left to size themselves they came out 87,
   87 and 84. Three pixels is exactly the kind of difference that reads as
   sloppy without being obvious enough to diagnose. */
.contact-ways--row { align-items: stretch; }
/* Compact in the rail, and this is the correction to a mistake worth keeping
   a record of. Stacking the icon above the body fixed the email breaking
   mid-word, but it made each card 230px tall, so three of them ran 750px
   beside 250px of words - 500px of dead column. That is precisely the void
   that got the 08-21 rail pulled, rebuilt on the other side of the page.

   A rail beside a short hero wants a list, not three full cards. The chip
   drops 62px to 40px and the padding 48px to 18/20, which puts the icon back
   BESIDE the body without crowding the value: 380 less 40 of padding, 40 of
   chip and 14 of gap still leaves 286px, and hello@papercliplaw.com needs
   about 223. One line, and the column comes down to roughly a third. */
.contact-ways--row { gap: 1rem; margin-bottom: clamp(1.25rem, 2.5vw, 2rem); }
.contact-ways--row .contact-way {
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.9rem;
  padding: 1.15rem 1.25rem;
  align-items: start;
}
.contact-ways--row .way__mark { width: 20px; height: 20px; padding: 10px; }
/* The form keeps its 900 cap and loses the auto centring. The cap is what
   stops a name field being 650px wide; the centring is what put its left edge
   at 183 while everything above it started at 48. */
/* The card fills the capped column instead of sitting at 900 inside it. At
   900 it ended 684px short of the rail above it, which is the void again. The
   900 cap existed to stop a name field being 650px wide - the fields go three
   across below instead, which holds them near 330 and shortens the form. */
.contact-write .contact-form { max-width: none; margin-inline: 0; }

/* Below the split the two halves stack, and the ways go back to a row while
   there is still width for one - three cards need about 780px to sit side by
   side without the phone number wrapping to three lines. */
/* One per row below 1100, and the first guess at 1000 was measured wrong.
   Three across needs about 985 of COLUMN: a card must clear 40 of padding, a
   40 chip, a 14 gap and 223 for the value, so 317 each plus two 16 gaps.
   The column is the viewport less two gutters, and the gutter is 4vw here, so
   1000 of viewport is only 920 of column - cards land at 291, the value gets
   193, and hello@papercliplaw.com wraps. Verified at 985: two lines.
   1100 of viewport gives 1012 of column and 326 per card, which clears it. */
@media (max-width: 1099.98px) {
  .contact-ways--row { grid-template-columns: minmax(0, 1fr); }
}
/* No row restored on tablet. Letting auto-fit back in put two cards up and
   the third alone on a left-aligned second row, the same orphan the staff row
   had; and three across cannot work here either - at 692 each card is 214px,
   which leaves 120px for a value that needs 223. The cards are compact now,
   so one column is only about 318px tall and costs nothing. */

/* NOW DEAD, removed 2026-09-20 (Direction 2 migration cleanup): the
   "Ready When You Are." highlighter, .home .close h2 .glow-word and its
   ::after (2026-08-25) - src/index.njk (stage 6) no longer wraps the close
   h2's text in a .glow-word span at all, so this .home-scoped pair can never
   match again. /work/*'s own close h2 still emits .glow-word and keeps the
   un-prefixed rule (search ".glow-word is an inline span" above); confirmed
   dead by grepping the built homepage for "glow-word" (zero hits). */

/* ---- The enquiry forms: FORM A, the colour block (2026-09-20) ----
   Chad picked this from three bold roughs after the first pass that evening
   (a white card with a wave foot) "still had too much of the old styling": it
   reskinned the old layout instead of changing it. One rounded block on
   /inquire/ and /contact/: a solid teal panel (headline in Instrument Serif,
   white with the italic in butter; the ways as plain rows; a navy wave foot
   holding the live reply clock) beside the form on white, send button a coral
   pill. The home-buying page keeps a plain white card with the same fields and
   pill. No field, name, endpoint or script changed. Ink: white and butter on
   teal/navy, navy on coral, teal labels on white. 2026-10-02, Elizabeth:
   "straight lines or a colour band"; Chad picked the band, so the navy foot is
   a straight block with a thin lighter stripe and the wave SVG is gone.
   Tripled selectors where the older .inquire-split / .contact-write / .pl-card
   rules sit at equal weight. */
.formblock.formblock.formblock {
  display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: 0; align-items: stretch;
  width: min(100% - 2 * var(--pl-gutter), var(--pl-max-width) - 2 * var(--pl-gutter)); max-width: none; padding: 0; margin-block: clamp(1.25rem, 2vw, 2.5rem) clamp(2.5rem, 4vw, 4.5rem);
  border-radius: 32px; overflow: hidden; background: #fff;
  box-shadow: 0 6px 14px rgba(26, 26, 26, .06), 0 24px 56px rgba(26, 26, 26, .13);
}
.formblock .formblock__side {
  position: relative; display: flex; flex-direction: column; max-width: none; margin: 0;
  background: #0E6B80; color: #fff; padding: clamp(2rem, 3vw, 3.5rem) clamp(1.6rem, 2.8vw, 3.2rem) 0;
}
.formblock .formblock__side h1 { font-size: clamp(2.8rem, 4.4vw, 5.2rem); line-height: 1.04; color: #fff; max-width: none; margin: 0; }
.formblock .formblock__side h1 em { font-style: italic; color: #FFD34D; }
.formblock .formblock__side h1 { text-wrap: balance; }
.formblock .formblock__side h1 em { white-space: nowrap; }
.formblock .formblock__side .ask__lede { color: #fff; font-size: clamp(1.02rem, 1.05vw, 1.15rem); line-height: 1.55; max-width: 36ch; margin: 1rem 0 1.4rem; }
.formblock .formblock__side .ask__eyebrow { color: #fff; justify-content: flex-start; margin-bottom: 1rem; }
.formblock .formblock__side .ask__eyebrow i { background: #FFD34D; }
/* the ways: rows on the teal, not cards */
.formblock .inquire-ways, .formblock .contact-ways { display: block; margin: 0; }
.formblock .contact-way.contact-way {
  display: flex; align-items: center; gap: 1rem; padding: .95rem 0; margin: 0;
  background: none; border: 0; border-top: 1px solid rgba(255, 255, 255, .28); border-radius: 0; box-shadow: none;
  color: #fff; text-decoration: none; transform: none;
}
.formblock .contact-way .way__mark { flex: none; width: 34px; height: 34px; display: grid; place-items: center; background: none; border: 0; color: #FFD34D; }
.formblock .contact-way .way__mark svg { width: 28px; height: 28px; }
.formblock .contact-way :is(.way__label, h3) { display: block; margin: 0; font: 800 .75rem var(--pl-font-body); letter-spacing: .12em; text-transform: uppercase; color: rgba(255, 255, 255, .82); }
.formblock .contact-way :is(.way__value, .way__value a, .way__links a) { margin: 0; font: 700 clamp(1rem, 1.05vw, 1.15rem) var(--pl-font-body); color: #fff; text-decoration: none; border: 0; }
.formblock .contact-way .way__links { display: flex; flex-wrap: wrap; gap: .2rem 1.1rem; margin: 0; }
.formblock .contact-way :is(.way__value a, .way__links a):hover, .formblock a.contact-way:hover .way__value { text-decoration: underline; text-underline-offset: 4px; }
.formblock .contact-way .way__go { margin-left: auto; color: #fff; background: none; border: 1.5px solid rgba(255, 255, 255, .55); }
.formblock .contact-way:focus-visible, .formblock .contact-way a:focus-visible { outline: 3px solid #FFD34D; outline-offset: 3px; }
/* the navy foot with the live clock. 2026-10-02, Elizabeth: "straight lines or a
   colour band"; Chad picked the band: a straight navy block with a 6px lighter
   stripe (#2A8AA0 at 90% over the teal = #27879D), the clock centred in it. The
   padding is sized so the foot is exactly as tall as the wave foot was (the
   stripe plus 2.76rem each side), so the block keeps its old height. */
.formblock__foot { position: relative; margin: auto calc(-1 * clamp(1.6rem, 2.8vw, 3.2rem)) 0; padding: 2.76rem clamp(1.6rem, 2.8vw, 3.2rem); min-height: 150px; display: flex; align-items: center; background: #00324E; }
.formblock .formblock__foot .close__note { position: relative; margin: 0; max-width: 46ch; text-align: left; font-size: 1rem; line-height: 1.45; color: #fff; }
.formblock .formblock__foot .close__note :is(.clock__policy, .clock__now) { color: #fff; }
html[data-kit] .formblock .formblock__foot .clock__now { font-weight: 800; color: #FFD34D; }
html[data-kit] .formblock .formblock__foot .clock__policy { color: #fff; }
/* the form side */
.formblock .formblock__form.formblock__form { max-width: none; margin: 0; background: #fff; border: 0; border-radius: 0; box-shadow: none; padding: clamp(1.8rem, 2.8vw, 3.2rem); align-self: center; }
.formblock .formblock__form > .pl-card { background: none; border: 0; border-radius: 0; box-shadow: none; padding: 0; }
.formblock .contact-form h2 { display: none; }
.contact-form > .pl-card { background: #fff; border: 0; border-radius: 24px; box-shadow: 0 2px 6px rgba(26, 26, 26, .05), 0 18px 44px rgba(26, 26, 26, .10); }
.contact-form .elementor-field-label { color: #0E6B80; font-weight: 800; letter-spacing: .08em; }
.contact-form :is(.elementor-field, .elementor-field-textual) {
  border: 1.5px solid color-mix(in srgb, #0E6B80 28%, transparent); border-radius: 14px; padding: .8rem 1rem;
  transition: border-color 160ms ease, box-shadow 160ms ease;
}
.contact-form :is(.elementor-field, .elementor-field-textual):hover { border-color: color-mix(in srgb, #0E6B80 55%, transparent); }
.contact-form :is(.elementor-field, .elementor-field-textual):focus { outline: none; border-color: #0E6B80; box-shadow: 0 0 0 4px color-mix(in srgb, #0E6B80 18%, transparent); }
.contact-form form .elementor-button {
  justify-self: start; width: max-content; height: 54px; padding: 0 1.9rem; border-radius: 999px;
  background: #EE7A70; color: #00324E; font: 800 1.05rem var(--pl-font-body); transition: background 200ms ease, transform 200ms ease;
}
.contact-form form .elementor-button:hover { opacity: 1; background: #F08E85; transform: translateY(-2px); }
.contact-form form .elementor-button:focus-visible { outline: 3px solid #00324E; outline-offset: 3px; }
@media (max-width: 900px) {
  .formblock.formblock.formblock { grid-template-columns: minmax(0, 1fr); border-radius: 24px; }
  .formblock__foot { min-height: 130px; padding-block: 2.46rem; }
  .contact-form form .elementor-button { width: 100%; justify-self: stretch; }
}
@media (prefers-reduced-motion: reduce) {
  .contact-form :is(.elementor-field, .elementor-field-textual), .contact-form form .elementor-button { transition: none; }
  .contact-form form .elementor-button:hover { transform: none; }
}

/* The workbook aside inside the enquiry form, as a small peach lane (2026-09-20).
   The whole row is one link. Navy words on peach, brick symbol, coral arrow disc. */
.form-aside.form-aside--lane {
  display: flex; align-items: center; gap: 1rem; margin: .2rem 0 .4rem; padding: .85rem 1rem .85rem 1.1rem;
  background: color-mix(in srgb, #F6DBCA 52%, #FFFFFF); border: 0; border-radius: 18px; max-width: none;
  color: #00324E; text-decoration: none; font-size: .98rem; line-height: 1.4; transition: background 200ms ease, translate 200ms ease;
}
.form-aside--lane:hover { background: color-mix(in srgb, #F6DBCA 78%, #FFFFFF); translate: 0 -2px; }
.form-aside--lane:focus-visible { outline: 3px solid #0E6B80; outline-offset: 3px; }
.form-aside__icon { flex: none; width: 36px; height: 36px; color: #C64438; }
.form-aside__icon svg { width: 100%; height: 100%; display: block; }
.form-aside__words { flex: 1; color: #00324E; }
.form-aside__words b { display: block; font: 700 1.05rem/1.25 var(--pl-font-display); color: #00324E; }
.form-aside__go { flex: none; width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center; background: #EE7A70; color: #00324E; transition: transform 200ms ease; }
.form-aside__go svg { width: 20px; height: 20px; }
.form-aside--lane:hover .form-aside__go { transform: translateX(3px); }
/* the "you could start tonight" nudge that appears when a wills service is picked: same lane */
.contact-form .workbook-nudge { background: color-mix(in srgb, #F6DBCA 52%, #FFFFFF); border: 0; border-radius: 18px; padding: 1rem 1.2rem; color: #00324E; }
.contact-form .workbook-nudge p { color: #00324E; font-size: .98rem; }
.contact-form .workbook-nudge b { font-family: var(--pl-font-display); }
@media (prefers-reduced-motion: reduce) { .form-aside--lane, .form-aside__go { transition: none; } .form-aside--lane:hover { translate: none; } .form-aside--lane:hover .form-aside__go { transform: none; } }
