/* HKQ site stylesheet.
 *
 * Ordered as the page is built: tokens, then the shared shell, then page types,
 * then the two big listing pages, then the homepage, then the animation layer.
 * Section banners below match this list -- search for the name in capitals.
 *
 *   DESIGN TOKENS          colors, type scale, spacing
 *   BASE                   layout primitives
 *   HEADER AND NAVIGATION  including the dropdown and the mobile drawer
 *   PREVIEW BANNER
 *   PAGE TYPES             practice areas, hubs, FAQs, attorneys, results,
 *                          insights, news, intake form
 *   FOOTER
 *   TEAM
 *   STAFF
 *   HOMEPAGE
 *   ENTRANCE MOTION        the data-reveal effects
 *
 * Two conventions worth knowing before editing:
 *
 * - Numbers here are measured off the live site, not chosen. Where a value
 *   looks arbitrary the comment says what it was measured from; change it and
 *   `manage.py check_geometry` will tell you.
 * - Colors come from the token block. Four navies differ by three points each
 *   and cannot be told apart by eye, which is why picking one by hand has
 *   already shipped a bug.
 */

/* HKQ site styles.
 *
 * Every value here traces to a measurement in docs/DESIGN-SYSTEM.md, taken by
 * `manage.py audit_computed_styles` off the rendered Wix pages. Where a number
 * looks arbitrary, it is not — it is what the source site computes.
 *
 *   type      Libre Baskerville 700 for display (85/36px), Montserrat 400 for
 *             body (18/16/14px). Measured by visible area, not element count.
 *   spacing   4px base; 8/12/16/24/28/40/44/56 are the observed steps
 *   container 980px, which the computed audit and Wix's own CSS agree on
 *   color     navy family #324158 / #232C53 / #04133A carrying the dark bands
 *
 * Raw extracted tokens with usage counts live in tokens.css, generated by
 * `manage.py extract_theme --write`.
 */

:root {
  /* Stand-in for Wix's helvetica-w01 family (Monotype, licensed to Wix, not
     to us). Weight 300 is how helvetica-w01-light is reproduced -- Arial has no
     light cut, so Windows falls back to regular, the worst case being 2%.

     "Metrically compatible" is not the same as identical, and the 0.4% this
     comment used to claim was optimistic. Measured across five strings from the
     homepage at 16px, Helvetica runs 0.07% to 1.0% WIDER than
     helvetica-w01-roman, and the difference is per-glyph rather than a constant
     -- 0.005 to 0.078px per character -- so no tracking value corrects it.
     Where a source line fills its measure to within ~2px, ours wraps a word
     early. It does on the first homepage practice paragraph. There is no fix
     short of the licensed face; see docs/PARITY-AUDIT.md. */
  --helv: Helvetica, Arial, sans-serif;
  /* Navy family. Four of them, close enough that they cannot be told apart by
     eye -- which is exactly why they are tokens. Each is listed with the
     surfaces it belongs to, because picking the wrong one has already shipped
     once: the homepage bands were built with --navy before measurement showed
     they are --navy-band, three points lighter.

       --navy-mid    footer story band
       --navy        page heads (team, staff, practice, hubs) and the legal strip
       --navy-band   homepage bands: motto, call, billions, form heading, buttons
       --navy-deep   cards (team, staff)
       --navy-button the /faqs category buttons and their card border */
  --navy-mid: #324158;   /* rgb(50, 65, 88)  — 13,852k px² */
  --navy: #232C53;       /* rgb(35, 44, 83)  —  9,887k px² */
  --navy-band: #263059;  /* rgb(38, 48, 89)  — the homepage's dominant band */
  --navy-deep: #04133A;  /* rgb(4, 19, 58)   —  7,354k px² */
  /* A fifth navy, and a real theme color rather than a one-off: the Wix theme
     declares it as --color_44 and the captured pages reference it 4,909 times,
     second only to the plain whites. It is 7 points off --navy-deep, which is
     the nearest, and the two are not interchangeable by eye. */
  --navy-button: #0B2F5B; /* rgb(11, 47, 91) — tokens.css --color_44 */

  /* Button blues. Shared across the hero button, the "Get help now" button and
     the three practice buttons: all of them settle on the same hover color even
     though two different colors rest underneath it. */
  --btn-blue: #86AFCC;        /* var(--btn-blue) */
  --btn-blue-hover: #417586;  /* var(--btn-blue-hover)  */

  --gold: #D5B77E;
  --rust: #C45308;
  --steel: #82A0BA;

  --ink: #000000;
  --paper: #FFFFFF;
  --shell: #E8E6E6;
  --mist: #FAFAFA;

  /* Type. Sizes are the measured steps; the ratio between them is the site's,
     not a scale I chose. */
  --display: 'Libre Baskerville', Georgia, 'Times New Roman', serif;
  --body: Montserrat, Helvetica, Arial, sans-serif;

  --size-hero: 85px;
  --size-h2: 36px;
  --size-h3: 24px;
  --size-lead: 18px;
  --size-body: 16px;
  --size-small: 14px;

  --line-hero: 1.4;
  --line-body: 1.8;   /* 28.8px at 16px, the commonest body pairing */

  /* Spacing, observed */
  --s-1: 8px;
  --s-2: 12px;
  --s-3: 16px;
  --s-4: 24px;
  --s-5: 28px;
  --s-6: 40px;
  --s-7: 44px;
  --s-8: 56px;

  --container: 980px;
}

*, *::before, *::after { box-sizing: border-box; }

/* The entrance animations start their elements outside the page box -- the
 * motto band begins at scale 1.2, which on a full-width band reaches 32px past
 * each edge, and the story heading begins translated right. Un-clipped, that
 * counts as scrollable overflow, and on a canvas that declares its own width
 * the browser answers by widening the layout viewport to contain it: an iPhone
 * SE laid the homepage out at 352 instead of 320 and shrank the whole document
 * to fit, until the reveals fired and it snapped back.
 *
 * `clip`, not `hidden`: hidden would make this a scroll container, which
 * changes how anything positioned inside it resolves. The source clips these
 * the same way -- Wix wraps every animated section in an overflow-hidden box. */
html { overflow-x: clip; }

/* The source never reflows the desktop layout below a 980 canvas: at an 800 or
   900px window hkqlaw.com keeps a 980px scrollWidth and scrolls sideways, and
   core/device.py already serves a tablet this same build at a fixed 980. Ours
   squeezed to the viewport instead, which ran "Let's Talk." and the footer's
   framed motto flush to both edges where the source holds a 16px inset.
   overflow-x has to leave `clip` for the scroll to be reachable, so it is
   restored below 980 only. */
html:not([data-device="phone"]) body { min-width: 980px; }
@media (max-width: 979px) {
  html:not([data-device="phone"]),
  html:not([data-device="phone"]) body { overflow-x: auto; }
}

body {
  margin: 0;
  overflow-x: clip;
  font-family: var(--body);
  font-size: var(--size-body);
  line-height: var(--line-body);
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: var(--display);
  font-weight: 700;
  line-height: var(--line-hero);
  margin: 0 0 var(--s-4);
}
/* 6.5vw, not 6: `vw` excludes the scrollbar, so a 1440 window measures 1390 and
   6vw tops out at 83.4px -- the clamp never reached its own 85px maximum at any
   real desktop width. The cap is what desktop should render; the middle term
   only decides where the shrink starts. */
h1 { font-size: clamp(40px, 6.5vw, var(--size-hero)); }
h2 { font-size: clamp(28px, 4vw, var(--size-h2)); }
h3 { font-size: var(--size-h3); }

p { margin: 0 0 var(--s-3); }
a { color: inherit; }
img { max-width: 100%; height: auto; display: block; }

/* ==========================================================================
   BASE — layout primitives shared by every page
   ========================================================================== */

.container {
  /* --container is the *content* width, measured at 980px on the captures:
   * body text runs x=230 to x=1204 at a 1440px viewport. Adding the padding
   * to max-width keeps that true instead of leaving 932px of content. */
  max-width: calc(var(--container) + var(--s-4) * 2);
  margin: 0 auto;
  padding-inline: var(--s-4);
}

/* Below 1028px the padding has no room left to sit in, and keeping it starts
 * eating the 980px of content instead of the margin. The source has no such
 * inset: its canvas IS 980 wide, so at a 980 viewport the text runs edge to
 * edge. Shedding the padding here rather than narrowing the content keeps the
 * two identical -- it is what makes the 980 tablet canvas line up, and it is
 * continuous with the wider case, where the content is also 980. */
/* Bounded below at 980 as well as above at 1028: this is the tablet canvas
 * rule specifically. Left open-ended it also stripped the inset off the 320
 * phone canvas, where the source insets its body copy by 20px. */
@media (min-width: 980px) and (max-width: 1028px) {
  .container {
    max-width: var(--container);
    padding-inline: 0;
  }
}

/* ==========================================================================
   HEADER AND NAVIGATION
   ========================================================================== */

.skip-link {
  position: absolute;
  left: -9999px;
}
.skip-link:focus {
  left: var(--s-3);
  top: var(--s-3);
  z-index: 200;
  background: var(--paper);
  padding: var(--s-2) var(--s-3);
}

/* --- Header ----------------------------------------------------------- */

.site-header {
  /* Not sticky, and no bottom border. Both were mine rather than the site's:
   * the source header scrolls away with the page, and the homepage runs pure
   * white straight through y=228 with no divider at the join.
   *
   * position/z-index stay only so the nav dropdowns paint over the content
   * below them; they do not affect scrolling. */
  position: relative;
  z-index: 60;
  background: var(--paper);
}

/* Measured from captures/screenshots/results.png at 1440px, because the
 * header is the one block every page's vertical position depends on:
 *
 *   total height  228px      logo   x 67-338, baseline y 97
 *   nav items     y 70-81, last one ending x 966
 *   search box    x 1100-1337, y 56-98
 *
 * The row sits at the top and the remaining ~130px is empty space below it —
 * that space is part of the design, not padding to be trimmed. The margins
 * are asymmetric (67 left, 103 right) because Wix positioned absolutely, so
 * they are stated rather than centered. */
.header-inner {
  max-width: none;
  margin: 0;
  /* The source's item boxes start at y=52 in a 221px band; 52 of padding puts
     ours there too. 103 on the right and 67 on the left are measured from the
     search box's right edge and the wordmark's left. */
  padding: 52px 103px 127px 67px;
  min-height: 228px;
  display: flex;
  align-items: center;
  gap: var(--s-5);
}

/* The wordmark is an SVG, so the only job here is placement. The source puts
   it at x=66, y=78 in a 221px-tall header band -- it does not share a baseline
   with the nav row, which sits higher. */
.logo {
  display: block;
  position: relative;
  top: 11px;
  flex: none;
  text-decoration: none;
}
.logo img { display: block; width: 274px; height: 20px; }

/* --- Search ------------------------------------------------------------ */

.header-search {
  display: flex;
  align-items: center;
  /* icon ends at 1164 and the field starts at 1176 on the source */
  gap: 12px;
  /* 203x43 at x=1135 on the source, with a 4px radius. The earlier 237x42
     came from a screenshot rather than the live box. */
  width: 203px;
  height: 43px;
  /* The header row is right-anchored -- .primary-nav takes the free space as a
     left margin -- so an item removed from between the nav and this field
     drags the nav right by its whole footprint. The source's Log In control is
     not reproduced (see templates/partials/_header.html), and it measured 90px
     wide with a 21px lead-in to this field, so 111 holds every other item at
     the position it was measured at. */
  margin-left: 111px;
  padding: 0 14px;
  border: 1px solid rgb(11, 47, 91);
  border-radius: 4px;
  flex: none;
}
/* Measured on the live field with the pointer over it: the box's fill goes a
   light grey, applied with no transition (the source's own
   `transition-property` reads `all` at `0s`). The source's own `<input>`
   border-color changes too, on hover and focus alike, but the input paints
   its border at 0 width there -- same as here -- so it stays invisible and
   this box's own 1px navy border is left alone. */
.header-search:hover {
  background: rgb(232, 230, 230);
}
.header-search-icon { width: 14px; height: 14px; color: rgb(11, 47, 91); flex: none; }

/* The header row was measured at 1440 and needs every pixel of it: 67 + 274
   logo + 28 + 535 nav + 8 + 111 + 203 search + 103 is 1329. Below that the flex
   line has to give somewhere, and the space comes out of the outer padding
   rather than off any item. The source overlaps at this width -- its nav runs
   over its own wordmark at 1280 -- and reproducing a collision is not fidelity
   (rule 11). 1440 is untouched. */
@media (min-width: 801px) and (max-width: 1400px) {
  .header-inner { padding-inline: 32px; }
}
.header-search input {
  /* 119x41 at x=1176 on the source -- the field does not stretch to fill the
     box, it sits 12px after the icon and leaves the tail empty. */
  width: 119px;
  height: 41px;
  border: 0;
  appearance: none;
  font-family: var(--display);
  font-size: 14px;
  color: rgb(11, 47, 91);
  background: none;
}
/* Full-strength navy, not the browser's grey. The source's placeholder is the
   same color as typed text, which is why ours read as washed out beside it. */
.header-search input::placeholder {
  color: rgb(11, 47, 91);
  opacity: 1;
}
/* No focus ring, matching the source, which sets none.

   This is a deliberate accessibility departure and worth knowing about: the
   browser default was drawing a blue-violet ring 2px outside the field, which
   landed inside the bordered box and read as a second, wrong-colored box. The
   source shows nothing at all on focus.

   `:focus-visible` is not a way out here -- it matches on a text field however
   it was focused, because typing is expected -- so removing the ring removes it
   for keyboard users too. If that trade is not wanted, the on-brand
   alternative is to thicken .header-search's own border on :focus-within
   rather than to restore the default ring. */
.header-search input:focus { outline: none; }
/* The clear control the source paints once the header field holds a term. */
.header-search-clear {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  color: rgb(4 19 58 / .6);
  text-decoration: none;
}
.header-search-clear:hover { color: rgb(4 19 58); }

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --- Navigation ------------------------------------------------------- */

/* The negative right margin cancels the last trigger's padding, which
 * would otherwise shift every menu item 14px left of where the capture
 * has it, since the group is pushed right by margin-left: auto. */
/* margin-right sets the gap before Log In, and because the nav is
   right-aligned it is also what fixes where the row starts. */
.primary-nav { margin-left: auto; margin-right: 8px; }

.nav-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  /* No gap. The item boxes are flush on the source: 452+140=592, which is
   * exactly where the next one starts. The earlier 39px "gap" was the space
   * between text edges, read off a screenshot — it is the triggers' own
   * padding, not a gap. */
  gap: 0;
}

.nav-list > li { position: relative; }

.nav-top {
  /* Nunito Sans Light, not Helvetica. The source sets avenir-lt-w01_35-light,
     a genuinely LIGHT cut that we cannot license. Helvetica has no 300 weight,
     so it silently fell back to Regular and rendered 19% more ink than the
     source at the same 16px -- which reads as bigger and bolder even though
     the size matched.

     Measured against the source's own rendering of "Practice Areas": Nunito
     Sans 300 matches its cap height exactly, its width to 1%, and its ink to
     5%. Helvetica 300 was +19% ink and +4.9% wide; Montserrat 400 was +27% and
     +13.7%. This is the closest of the faces we ship. */
  font-family: 'Nunito Sans', Helvetica, Arial, sans-serif;
  font-weight: 300;
  font-size: 16px;
  letter-spacing: .02em;
  color: var(--ink);
  background: none;
  border: 0;
  padding: var(--s-1) 0;
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
  white-space: nowrap;
}

/* Trigger boxes measured off the element, not off paint: 140x49 for
 * "Practice Areas" (text 105 wide), 87x49 for "Results" (text 52). That is
 * 17.5px of padding each side and 15px above and below a 19px line. */
/* The 5px white border is not decoration -- it is what makes the pill look
   right. The source's item box is 49px tall but its painted background is only
   39px, because a 5px border in the header's own white insets the fill on every
   side. The 7px radius is on the border box, so the visible gold corner ends up
   at roughly 2px: tighter and squarer than a 7px pill drawn edge to edge.

   Without it ours painted the full 49px at a true 7px radius, which read as a
   noticeably bigger, rounder box.

   Vertically: 5 border + 12 + 19 line + 8 + 5 border = the source's 49. The
   source splits its padding 10/10; ours is 12/8 because Nunito Sans sits its
   glyphs 2px higher in the line than the source's Avenir.
   Horizontally: 5 + 12.3 each side puts the label 17.3px in, matching the
   source's 34.6px of total chrome around the text. */
/* The source carries the radius with the fill, not on the resting item: its
   nav link computes 0px at rest and 7px while hovered. Both look the same on
   a white header, which is why this read as settled -- confirmed by hovering
   the live nav, per rule 11. */
.nav-list > li > .nav-top {
  border: 5px solid var(--paper);
  border-radius: 0;
  background: var(--paper);
  padding: 12px 12.3px 8px;
  line-height: 19px;
  transition: background-color .08s linear, color .08s linear;
}
.nav-list > li:hover > .nav-top,
.nav-list > li.is-open > .nav-top {
  background: var(--steel);
  border-radius: 7px;
  color: var(--paper);
}
/* The current section, in gold — and it STAYS gold on hover. An earlier rule
 * turned it navy on hover, from the same bad reading that gave the nav a navy
 * hover at all. */
.nav-list > li.is-current > .nav-top,
.nav-list > li.is-current:hover > .nav-top,
.nav-list > li.is-current.is-open > .nav-top {
  background: var(--gold);
  /* The radius travels with the fill, as on hover above: the live current item
     computes 7px. Ours painted the gold pill with square corners on every page
     but the homepage, which has no current item. */
  border-radius: 7px;
  color: var(--paper);
}

.dropdown {
  list-style: none;
  margin: 0;
  position: absolute;
  top: 100%;
  /* The panel hangs 4px left of its trigger on the live menu. */
  left: -4px;
  /* Sizes to its contents: 232 wide under Practice Areas, 113 under About Us.
   * A fixed width made every dropdown as wide as the widest. Items are inset
   * 11px each side, 6px top and bottom. */
  width: max-content;
  min-width: 0;
  padding: 6px 11px;
  background: var(--paper);
  border: 1px solid var(--gold);
  /* Flush with the trigger: the live panel's top is 101 and the trigger's
   * bottom is 101. The 6px this used to carry opened a gap the source does
   * not have. The ::before bridge below is kept anyway -- it costs nothing and
   * survives the panel being nudged again. */
  margin-top: 0;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity .16s ease, transform .16s ease, visibility .16s;
}

/* Bridges the 6px gap so moving the pointer from trigger to panel does not
 * leave the item and close the menu. */
.dropdown::before {
  content: '';
  position: absolute;
  top: -7px;
  left: 0;
  right: 0;
  height: 7px;
}

.has-children.is-open > .dropdown {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

/* The 5px above and below each row is the LI's padding, not the A's margin.
 * As a margin the two adjacent 5s collapse into one, which put the rows on a
 * 44px pitch against the source's 49 and left the panel 28px short. */
.dropdown li { padding: 5px 0; }
.dropdown a {
  display: block;
  /* Rows are 49 tall, but the highlight block inside them is only 39 —
   * inset 5px top and bottom by the LI above. */
  padding: 10px 12px;
  margin: 0;
  font-size: var(--size-small);
  line-height: 19px;
  color: var(--navy-deep);
  text-decoration: none;
  white-space: nowrap;
}
/* Gold at 60% with a 2px radius — measured off a live dropdown item. */
.dropdown a { border-radius: 2px; transition: background-color .08s linear; }
/* The current page inside a dropdown, in brown. */
.dropdown li.is-current > a { background: rgb(174, 99, 63); color: var(--paper); }
.dropdown a:hover,
.dropdown a:focus-visible { background: rgba(213, 183, 126, .6); color: var(--navy-deep); }

/* Bridges the 6px gap so moving the pointer from trigger to panel does not
 * leave the item and close the menu. This lived inside the mobile media query
 * by accident, which meant it did nothing on desktop — the only place a
 * hover gap exists. */
.dropdown::before {
  content: '';
  position: absolute;
  top: -7px;
  left: 0;
  right: 0;
  height: 7px;
}

.dropdown .has-children { position: relative; }
.dropdown-sub { top: 0; left: 100%; }

.nav-toggle { display: none; }

/* --- Footer ----------------------------------------------------------- */


/* Footer colors are per band, not per footer: the motto and legal bands are
 * navy and the card and "Let's Talk" bands are white. A blanket
 * `.site-footer h2 { color: paper }` survived from when the whole footer was
 * dark and made both white-background headings invisible. */

/* --- Mobile ----------------------------------------------------------- */

@media (max-width: 899px) {
  .nav-toggle {
    display: grid;
    gap: 5px;
    margin-left: auto;
    background: none;
    border: 0;
    padding: var(--s-1);
    cursor: pointer;
  }
  .nav-toggle span { width: 26px; height: 2px; background: var(--ink); display: block; }

  .primary-nav {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--paper);
    border-bottom: 1px solid var(--shell);
    display: none;
    margin-left: 0;
  }
  .primary-nav.is-open { display: block; }

  .nav-list { flex-direction: column; gap: 0; padding: var(--s-1) var(--s-4) var(--s-3); }
  .nav-list > li { border-bottom: 1px solid var(--shell); }
  .nav-top { display: block; width: 100%; text-align: left; padding: var(--s-2) 0; }

  .dropdown {
    position: static;
    opacity: 1;
    visibility: visible;
    transform: none;
    border: 0;
    box-shadow: none;
    padding: 0 0 var(--s-1) var(--s-2);
    display: none;
  }


.has-children.is-open > .dropdown { display: block; }
  .dropdown-sub { padding-left: var(--s-2); }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}

/* ==========================================================================
   PREVIEW BANNER — staff-only, never reaches production
   ========================================================================== */

/* --- Rebuilt page: practice area ------------------------------------- */

.preview-banner {
  background: var(--gold);
  color: var(--navy-deep);
  padding: var(--s-3) var(--s-4);
  font-size: var(--size-small);
}
.preview-banner a { color: var(--navy-deep); }

/* ==========================================================================
   PAGE TYPES — practice areas, hubs, FAQs, attorneys, results, insights, news
   ========================================================================== */

/* The page banner. Measured from the captured screenshots at 1440px: the
 * band runs y=228 to y=574, the title is centered, and the photograph sits
 * under a navy wash heavy enough that white type holds over any image. */
/* Asymmetric padding: the content is centered in the 346px band, and the extra
   18px on top pushes it down the 9px that puts the title on the source's
   baseline without changing the band's height. Re-derived after the title lost
   its margin -- the pair only holds for one content height, so changing either
   the type size or the gap below the title means solving PT - PB again. */
.practice-head {
  position: relative;
  background: var(--navy);
  color: var(--paper);
  /* Top-aligned with an explicit inset, not centered. The source hand-positions
     this content per page -- the title starts at y=351 on
     /workers-compensation and 348 on /corporate-law -- and centering meant
     solving for a padding pair every time the type size or the gap under the
     title changed. Pages carry their own value in banner_style.padding_top;
     123px is the common one. */
  padding: var(--banner-pad-top, 123px) 0 0;
  min-height: var(--banner-height, 346px);
  display: flex;
  align-items: flex-start;
  text-align: center;
}
.practice-head.has-photo { overflow: hidden; }
/* The photograph is not this band's background. On the source it is a separate
   490px-tall image that starts at y=83 -- 145px above this band, behind the
   header -- and is cropped to cover *that* box, so the band shows its bottom
   345px. Painting it as the band's own background cropped a 346px box instead,
   which is a visibly different part of the picture: the same photograph, framed
   wider and shifted down.

   It has to stay a real 490px layer rather than a background-position offset,
   because the correct offset depends on the image's aspect ratio and so differs
   per page; this way the browser does the cover arithmetic. */
.practice-head-photo {
  position: absolute;
  left: 0;
  right: 0;
  top: var(--banner-photo-top, -145px);
  height: var(--banner-photo-height, 490px);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
/* The wash paints over the photograph, and the title over both. Without these
   the ::before generates ahead of the photo layer and loses to it. */
.practice-head.has-photo::before { z-index: 1; }
.practice-head > .container { z-index: 2; }
/* 60%, not 78%. The source paints the photograph at 0.4 opacity over navy,
   which composites to photo*0.4 + navy*0.6 -- so a 60% navy wash over the
   photograph is the same result. At 78% the picture was almost gone. */
.practice-head.has-photo::before {
  content: '';
  position: absolute;
  inset: 0;
  /* Strength is per page (banner_style.wash), not a site constant: the source
     fades these banners by different amounts -- 60% on /workers-compensation,
     69% on /telecommunications-law, 74% on /corporate-law. */
  background: rgb(35 44 83 / var(--banner-wash, 60%));
}
/* The insights banner sits over a bright skyline with NO scrim at all: the
 * source's hero section computes `rgba(0, 0, 0, 0)` with no background image,
 * and an 18% black overlay here read 19% darker than the live band across
 * every channel (mean 79,88,93 against 97,109,117).
 *
 * That leaves white type over a bright sky at the source's own contrast, which
 * is a WCAG 1.4.3 question rather than a parity one -- the same call already
 * recorded for the search field's focus ring in docs/PARITY-AUDIT.md. */
.practice-head.wash-light::before { background: transparent; }
.practice-head > .container { position: relative; width: 100%; }
.hero-sub { color: var(--paper); margin: 0; font-size: var(--size-small); }
/* No gap under the title. The trail's own 28.8px line box supplies the whole
   separation on the source -- adding a margin here pushed the trail 14px low. */
/* Libre Baskerville bold at 66px, which is the site default and not what the
   source's h1 element says. Do not read that element: Wix wraps the title in
   nine nested spans and the innermost one -- font-weight:bold, 66px,
   "libre baskerville" -- is what actually paints. The outer h1 claims
   Montserrat 400 at 64px and is entirely overridden.

   6.9vw, not 4.6 and not 5. `vw` excludes the scrollbar, so at a 1440 window
   the viewport is 1390 and 4.6vw resolved to 63.936px -- the clamp never
   reached its own maximum, and the title came out 26px narrow at every desktop
   width. 5vw fixed that but only from 1320 up, which left the title at 49px on
   the 980 tablet canvas where the source still paints it at 66. 6.9vw reaches
   the maximum at 980 and holds it everywhere above, which is what the source
   does -- it has no width response at all, so the title never shrinks. */
/* 89.6px is a length on purpose and is NOT 1.4 of the font-size above it. The
 * practice banner's h1 block computes 64px on the source while the span that
 * paints inside it is 66, so the line box is 1.4 of 64 and the type is 66 --
 * see the rule about measuring type on the span and geometry on the block in
 * .claude/rules/parity-measurement.md. Every variant that raises the
 * font-size has to restate line-height, because this length does not scale
 * with it: .hero-faq, .hero-faq-index, .hero-contact, .hero-insights and
 * .hero-referrals all set their own. */
.practice-head h1 {
  color: var(--paper);
  margin-bottom: 0;
  font-size: clamp(32px, 6.9vw, 66px);
  line-height: 89.6px;
}


/* 16px, not the small step: the trail matches body size on the source, and it
   is tracked out 0.04em -- without that the whole trail measures 56px narrow
   and, being centered, starts 28px too far right. */
.crumb {
  font-size: 16px;
  line-height: 28.8px;
  letter-spacing: 0.04em;
  color: var(--paper);
  margin: 0;
}
/* Not underlined. The source's trail links carry no rule at all. */
.crumb a { color: var(--paper); text-decoration: none; }
/* White, not gold. The whole trail is one color on the source -- the label is
   distinguished by weight alone. */
.crumb-label { color: var(--paper); font-weight: 700; }

/* Measured, not scale steps, and not equal to each other: 87/89 is what puts
   the lead-in at y=660 and the types band at y=1177 on /workers-compensation. */
/* Every var() below is a per-page measurement carried on .practice by
   PracticeArea.style_vars, with the fallback being the value most of the
   family shares. Nothing here is set inline on the elements themselves, so
   the phone build can override any of it by ordinary cascade. */
.practice-body {
  padding-top: var(--hook-gap-above, 87px);
  padding-bottom: var(--types-gap-above, var(--intro-gap-below, 89px));
}
/* No measure limit: the source runs body copy the full 980px -- and no margin
   between paragraphs either. The rhythm comes entirely from the empty
   zero-width-space paragraphs Wix's editor leaves between them, so a margin
   here is added on top of a gap that already exists and drifts the whole
   column low. */
/* No margin, for the same reason .practice-body p has none: the source's
   rhythm comes from the empty spacer paragraphs Wix leaves between blocks, so
   the browser's default heading margin is added on top of a gap that already
   exists -- 25px after every intro heading. */
/* Not .block-heading. This rule is for headings inside the intro copy, and at
   (0,1,1) it outranks .block-heading at (0,1,0) -- so a block's own recorded
   size and face never applied and every one of them fell back to the intro
   heading's, which is how "NHTSA Findings*" painted 16px display where the
   source sets 18px montserrat. */
.practice-body h3:not(.block-heading) {
  font-family: var(--h-family, var(--display));
  font-weight: var(--h-weight, 700);
  font-size: var(--h-size, inherit);
  line-height: var(--h-lh, inherit);
  margin: 0;
}
.practice-body p {
  max-width: none;
  margin: 0;
  /* The paragraph's own recorded values arrive as custom properties rather
     than as inline font-size/line-height. Written directly they were inline
     styles inside the stored HTML, which no stylesheet can override -- the
     phone canvas could not change body copy at all. */
  font-size: var(--p-size, 18px);
  line-height: var(--p-lh, var(--body-leading, 27px));
  letter-spacing: var(--p-track, normal);
}

/* The lead-in is a 45px display line, not a section heading at the body
   size -- it was rendering at 24px, roughly half. */
/* Other families reuse .practice-body and open with a plain heading --
   /faqs does. They keep the fixed display size; only a practice area's
   lead-in carries recorded values. */
.practice-body > h2:first-child:not(.practice-hook):not(.practice-secondary-heading) {
  font-family: var(--display);
  font-size: 45px;
  line-height: 54px;
  font-weight: 700;
  margin: 0 0 23px;
}
.practice-hook {
  font-family: var(--hook-family, var(--display));
  font-weight: var(--hook-weight, 700);
  font-size: var(--hook-size, 45px);
  line-height: var(--hook-lh, 54px);
  margin: 0 0 var(--hook-gap-below, 23px);
  max-width: var(--hook-width, none);
  min-height: var(--hook-height, 0);
}
/* The closing block's heading is larger again. */
/* The closing block does not share the intro block's rhythm -- it starts 8px
   lower under its band and closes 20px tighter, so it overrides both paddings
   rather than inheriting .practice-body's. */
.practice-secondary {
  padding-top: var(--sec-gap-above, 95px);
  padding-bottom: var(--sec-gap-below, 69px);
}
/* Runs straight into the closing row, so it closes nothing of its own. */
.practice-secondary-open { padding-bottom: 0; }
.practice-secondary-heading {
  font-family: var(--sec-family, var(--display));
  font-weight: var(--sec-weight, 700);
  font-size: var(--sec-size, 48px);
  line-height: var(--sec-lh, 57.6px);
  margin-bottom: var(--sec-gap-below-heading, 16px);
}
/* 0.8px of tracking, which is load-bearing rather than cosmetic: without it
   this paragraph fits on two lines where the source takes three, and the
   button below lands a line high. */
/* Size, leading and tracking all come from the page where it recorded them
   (secondary_style.body_*): 16px/28.8px/0.8px on /workers-compensation and
   18px/25.2px/normal on /telecommunications-law. The values below are the
   fallback for pages that have not been recorded. */
/* The paragraph's own recorded values first, then the band's -- the order the
   phone rule already uses. A band is not one size: /real-estate-law records
   27.2px leading on this paragraph and 30.6 on the one above it, and the
   band-level value overrode both because this rule sits later in the file than
   the .practice-body p rule of equal weight. */
.practice-secondary p {
  font-size: var(--p-size, var(--closing-size, 16px));
  line-height: var(--p-lh, var(--closing-leading, 28.8px));
  letter-spacing: var(--p-track, var(--closing-tracking, 0.8px));
}
/* The closing button is a third shape again -- 28px sides, no minimum width.
   Three bands, three buttons, none of them the same; this is the source's
   doing, not ours. */
.practice-secondary .hub-btn { min-width: 0; padding: 0 28px; gap: 3px; margin-top: 23px; }
/* The source sets this button's width per instance rather than letting its
   padding size it -- 203px around a 128px label on one page, 282 around 216 on
   another. Everything is border-box, so the 28px inset above still holds. */
.practice-secondary-cta {
  margin-top: var(--sec-cta-gap, 23px);
}
/* Two classes throughout, because both `.hub-btn { background: none }` and
   `.practice-secondary .hub-btn { min-width: 0 }` outrank a single class here.
   The width is a floor rather than a fixed size, for the reason the panel
   button carries the same note: our substituted face is wider than the
   source's, and pinning its number wraps the label. */
.hub-btn.practice-secondary-cta {
  min-width: var(--sec-cta-width, auto);
  background: var(--paper);
}
/* Excludes the headings that carry recorded per-page values: this rule is
   (0,1,1) and .practice-hook is (0,1,0), so it was overriding a recorded
   43px lead-in with the 24px scale step. */
.practice-body h2:not(.practice-hook):not(.practice-secondary-heading):not(.block-heading) { font-size: var(--size-h3); margin-top: var(--s-6); }
.practice-body h2:first-child { margin-top: 0; }

.types { background: var(--shell); padding-block: var(--s-8); }
.types h2 { font-size: var(--size-h3); }

/* The split band: photograph on the left half, navy panel on the right.
 * Full-bleed by design — the source runs it edge to edge, so it has no
 * .container and the panel carries its own padding. */
/* Photograph left, navy panel right, both 604 tall. The panel is --navy-deep,
   a darker navy than the hero's wash. */
/* The recorded height is a FLOOR, not a size. Set as `height` it clipped
   /tax-assessment's panel copy mid-line when that page's paragraph was
   replaced, and every later copy edit would have meant re-measuring the band.
   The panel's own padding sizes it past the floor when the copy is longer than
   the source's; the phone build at the foot of this file has always worked
   this way. */
.types-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: var(--types-height, 604px);
  background: var(--navy-deep);
  padding-block: 0;
}
/* The photograph is washed the same way the page banner is, and for the same
   reason: the source paints it at 0.5 opacity over --navy, so half the navy
   shows through. Without this the picture reads bright and warm against the
   panel beside it instead of sharing its color. */
.types-photo {
  position: relative;
  background-size: cover;
  background-position: center;
  background-color: var(--navy);
  /* Fills the grid row, so it follows the panel beside it when the copy makes
     the band taller than `--types-height`. `height: 100%` resolved against a
     band that no longer has a definite height. */
  align-self: stretch;
}
.types-photo::after {
  content: '';
  position: absolute;
  inset: 0;
  /* Strength comes from the page (types_style.wash): the source fades these
     photographs by different amounts, 0.5 on one band and 0.65 on another. */
  background: rgb(35 44 83 / var(--photo-wash, 50%));
}
/* A 490px column centered in the panel half, not a fixed inset from the split.
   Both descriptions give 115px at 1440, which is why the fixed inset survived
   -- but the panel content sits 218px past the split at 1850, and only the
   centered column predicts that. Same shape as .hub-results-panel. */
/* Padded top and bottom rather than sized: with the band's recorded height as a
   floor, the bottom padding is what holds the copy off the foot on a page whose
   copy outgrows it. `--types-panel-pad-bottom` is the source's own slack below
   the copy, recorded per page.

   It defaults to 0, not to the top padding: the padding counts toward the
   panel's border box, so a default would push 31 of the 64 pages with this band
   past their recorded floor and silently change a height every parity gate
   grades. A page whose copy is replaced wants its slack recorded with it. */
.types-panel {
  color: var(--paper);
  padding-top: var(--types-panel-pad-top, 90px);
  padding-bottom: var(--types-panel-pad-bottom, 0);
  box-sizing: border-box;
}
.types-panel-inner { width: 490px; margin: 0 auto; }
.types-panel h2 {
  color: var(--paper);
  font-family: var(--types-heading-family, var(--display));
  font-size: var(--types-heading-size, 33px);
  line-height: var(--types-heading-lh, 39.6px);
  font-weight: var(--types-heading-weight, 700);
  margin: 0 0 21px;
}
/* Heading-plus-list blocks. Used beside the intro copy, inside the navy panel
   and in the closing row -- one shape, three placements. Sizes and the bullet
   indent ride on the elements themselves, because the source sets them per
   block. See PracticeArea.blocks. */
.practice-block { margin-top: var(--b-gap-above, 0); }
.block-heading {
  font-family: var(--b-heading-family, var(--display));
  font-weight: var(--b-heading-weight, 700);
  font-size: var(--b-heading-size, inherit);
  line-height: var(--b-heading-lh, inherit);
  margin: 0 0 var(--b-gap-below-heading, 12px);
}
.block-prose { font-size: var(--b-body-size, inherit); line-height: var(--b-body-lh, inherit); }
.block-list {
  list-style: disc;
  margin: 0;
  padding: 0;
  font-size: var(--b-item-size, inherit);
  line-height: var(--b-item-lh, inherit);
}
.block-list li { padding: 0; margin-left: var(--b-item-indent, 0); min-height: var(--b-item-pitch, 0); }

/* The closing band's verdict lines. Bulleted and bold, indented 14px from the
   copy above them; the gap over the list is recorded per page and set inline. */
.practice-results {
  list-style: var(--results-marker, disc);
  margin: var(--sec-results-gap, 0) 0 0;
  padding-left: 29px;
  font-size: var(--results-size, inherit);
  line-height: var(--results-lh, inherit);
  font-weight: var(--results-weight, 700);
  /* The source tracks these lines out: 0.8px on /truck-accidents, which is
     26px on its shortest verdict line and 49 on its longest. */
  letter-spacing: var(--results-track, normal);
}
.practice-results li { padding: 0; }
.practice-results a { color: inherit; text-decoration: underline; }

/* Copy in a narrow left column with the lists beside it: the source runs the
   copy 519px wide and starts the sidebar at x=811, a 62px gutter. */
.practice-intro-row { display: flex; gap: 62px; align-items: flex-start; }
/* The copy column is as wide as the lead-in above it -- 697px on
   /corporate-law against the 980 the page runs at. */
.practice-intro-copy { flex: none; width: var(--hook-width, auto); }
.practice-intro-copy p { max-width: var(--intro-measure, none); }
.practice-intro-side { flex: 1; }
/* Gaps between stacked blocks ride on the blocks themselves (gap_above). */

/* The closing row: two equal columns in the 980px container, the second
   starting at x=764. */
/* Columns sized to their own recorded widths rather than split evenly: the
   source runs 497 beside 428 on /commercial-litigation, and two equal tracks
   put the right-hand one 33px off. */
.practice-closing-cols {
  display: grid;
  grid-template-columns: auto auto;
  justify-content: start;
  column-gap: var(--closing-col-gap, 88px);
  row-gap: 88px;
  padding-top: var(--closing-gap-above, 0);
  padding-bottom: var(--closing-gap-below, 69px);
}
.practice-closing-col { width: var(--col-width, auto); }
/* The source lays these on a mesh, so the next block's top -- not this one's
   content height -- decides where it sits. */
.practice-closing-slot { min-height: var(--slot-pitch, 0); }
/* A single closing block is one column, not half a two-column grid. */
.practice-closing-cols:has(> div:only-child) { grid-template-columns: 1fr; }
.practice-closing-cols .block-heading { color: var(--ink); }

@media (max-width: 800px) {
  .practice-intro-row { display: block; }
  .practice-intro-copy { width: auto !important; }
  .practice-closing-cols { grid-template-columns: 1fr; gap: var(--s-6); }
}

/* One item per line, not a grid. */
.types-list { list-style: none; margin: 0; padding: 0; }
.types-list li {
  padding: 0;
  font-size: var(--types-size, 18px);
  line-height: var(--types-lh, 27px);
  list-style-type: var(--types-marker, inherit);
  margin-left: var(--types-item-indent, 0);
}
/* A panel the source sets as prose rather than a list. */
.types-prose { font-size: var(--types-size, 18px); line-height: var(--types-lh, 27px); margin: 0; }
/* Where the source runs the list as prose it bullets it and sets it smaller.
   The 8px and 20.8px are the source's own indents: they put the text at x=864
   in a panel column starting at 835. */
.types-list-bulleted { list-style: disc; margin-left: 8px; }
.types-list-bulleted li { margin-left: 20.8px; }

/* The .hub-btn-onnavy variant lives with .hub-btn further down the file. It has
   to: both are single-class selectors, so whichever is written last wins, and
   up here every one of its overrides lost silently -- the panel button was
   rendering with the steel border and the base button's 35px gap even though
   this block said otherwise. */

@media (max-width: 700px) {
  .types-split { grid-template-columns: 1fr; }
  .types-photo { min-height: 240px; }
}
.types-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--s-2) var(--s-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
}
.types-grid li {
  padding: var(--s-2) 0;
  border-bottom: 1px solid rgb(4 19 58 / 12%);
  font-size: var(--size-small);
}

.results-cta {
  background: var(--navy-deep);
  color: var(--paper);
  padding-block: var(--s-8);
  text-align: center;
}
.results-cta h2 { color: var(--paper); }
.results-cta .disclaimer {
  font-size: var(--size-small);
  color: var(--steel);
  max-width: 70ch;
  margin-inline: auto;
}

.btn {
  display: inline-block;
  padding: var(--s-2) var(--s-4);
  margin: var(--s-2) var(--s-1) 0;
  background: var(--gold);
  color: var(--navy-deep);
  font-size: var(--size-small);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  text-decoration: none;
}
.btn:hover { background: #c9a86b; }
.btn-quiet { background: transparent; color: var(--paper); border: 1px solid currentColor; }
.btn-quiet:hover { background: rgb(255 255 255 / 10%); }

/* --- Rebuilt page: FAQ index ------------------------------------------
 *
 * /faqs and /commercial-faqs. Measured on the live site at 1440: the card is
 * 1px-bordered with a 16px radius, and holds one column of 619x43 buttons.
 * This replaced a `types-grid` list of plain links, which is a different
 * component and is still used elsewhere — docs/PARITY-AUDIT.md item 9. */

/* 261px of painted band, sampled down the live page: navy runs y=227 to 487.
 * The same height /contact uses, and not the 408 the source's own box reports
 * — Wix starts that box at y=80 and a 227px header covers its first 147.
 * Hero height varies by page type — docs/PARITY-AUDIT.md 1b, where assuming
 * one height everywhere shipped a defect.
 *
 * `faq-index`, not `faq`: the FAQ DETAIL pages are 400px and were briefly on
 * this same selector, so the later rule won and made every index 139px too
 * tall. Two page types, two names. */
/* 72px in, the same inset /contact needs: the source starts both index titles
 * at y=299, 72 below the band's visible top at 227. */
.practice-head.hero-faq-index { min-height: 261px; padding-block: 72px 0; }

/* 85px, the page default, rather than the 66px the practice banners drop to —
 * the same call /contact needed, for the same reason. */
/* line-height set, not inherited: the shared rule pins 89.6px, which is 1.4 of
 * the 64px the practice banners use, and left this title in a 90px box. */
/* 8.68vw is 85 at 980, the tablet canvas. At 6vw the middle term resolved to
 * 58.8 there, so --size-hero was unreachable on any width the tablet build
 * ships and this title rendered 26px small in a 82px box against the source's
 * 120. The band's pinned min-height absorbed the difference, so no page-height
 * gate could see it. */
.practice-head.hero-faq-index h1 {
  /* Flat, not a clamp. 8.68vw reaches 85 exactly AT the 980 tablet canvas and
   * undershoots below it -- 67.7px at a 780 window against the source's
   * constant 85 -- because the desktop build holds a 980 canvas there (the
   * min-width on body) while vw keeps tracking the smaller window. Measured
   * live at 780, 980 and 1440: 85/119 at all three. */
  font-size: var(--size-hero);
  line-height: 1.4;
}

/* The card's block is a fixed 986px, from the hero band's foot at 487 to the
 * motto strip at 1473. The source pins that strip at the same y on both
 * indexes, so /faqs — five buttons shorter than /commercial-faqs — carries the
 * difference as white space beneath its card rather than pulling the strip up.
 * Letting it flow instead left /faqs 357px short, which is exactly the five
 * missing buttons at their 71px pitch. */
/* The 92px above the card is padding here, not a margin on the card: as a
 * margin it collapsed through the container's top edge and pushed the whole
 * block down instead of sitting inside the 986. */
.faqs > .container { min-height: 986px; padding-top: 61px; }

.faq-picker {
  /* The card and its buttons are the same navy. Wix declares both from one
   * theme slot -- the card as `--brd: var(--color_44)`, which resolves to
   * 11,47,91 -- so they are one value here too and cannot drift apart.
   * It is lighter than --navy-deep and darker than --navy: neither token. */
  --faq-navy: #0B2F5B;

  max-width: 691px;         /* 619 button + 36 padding each side */
  /* No bottom margin: the container's min-height carries the space under the
   * card, so a shorter card (/faqs) does not pull the motto strip up. */
  margin: 0 auto;
  /* 690x889 on the live card, 549 to 1438: 72 above the heading and 39 under
   * the last button. Not symmetric, and not the --s-6/--s-3 pair guessed at
   * first, which put the card 32px low and 55px short. */
  padding: 72px var(--s-5) 39px;
  border: 1px solid var(--faq-navy);
  border-radius: 16px;
  background: var(--paper);
}

/* 24px on the source, and an h3 rather than an h2 — the hero holds the h1. */
.faq-picker-heading {
  font-size: 24px;
  font-weight: 400;
  text-align: center;
  /* 60px: the heading ends at 655 and the first button starts at 715. */
  margin: 0 0 60px;
}

/* 43px buttons on a 71px pitch, so 28px between them. No `justify-items:
 * center` here: that shrinks each row to its content, and the buttons then
 * take their width from their label instead of the 619px the source gives
 * every one of them. The anchor centers itself instead. */
.faq-picker-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 28px;
}

/* Measured on the live button: 619x43, background rgb(11, 47, 91), a 4px
 * double white border, and the label in Playfair Display 17px/400 at 2.55px of
 * tracking. Playfair is the only place on the site that face is used; it is
 * self-hosted for this, see static/css/fonts.css. */
.faq-picker-button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  max-width: 619px;
  margin-inline: auto;
  height: 43px;
  padding: var(--s-1) var(--s-3);
  border: 4px double var(--paper);
  background: var(--faq-navy);
  color: var(--paper);
  font-family: 'Playfair Display', var(--display);
  font-size: 17px;
  letter-spacing: 2.55px;
  /* `normal`, as the source leaves it, not a ratio. Setting 1.2 shortened the
   * line box and sat every label 1px high inside its button — visible only to
   * a component-relative measurement, which is what found it. */
  line-height: normal;
  text-align: center;
  text-decoration: none;
  /* The source eases the whole inversion over 0.2s -- its computed transition
   * is `all 0.2s ease`. Ours changed four properties on hover with no
   * transition at all, so the button snapped where the source fades. */
  transition: all .2s ease;
}
/* The source INVERTS on hover rather than darkening: the fill goes white, the
 * border goes navy and narrows from 4px to 3, and the label goes black.
 * Measured on /commercial-faqs with the pointer over the button. A hover state
 * appears in no screenshot and no capture, so nothing here had ever compared
 * one -- it took driving the page (rule 10). */
.faq-picker-button:hover {
  background: var(--paper);
  border-width: 3px;
  border-color: var(--faq-navy);
  color: var(--ink);
}
.faq-picker-button:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

@media (max-width: 800px) {
  .faq-picker { margin-inline: 0; padding: var(--s-4) var(--s-3); }
  .faq-picker-list { gap: var(--s-3); }
  /* The longest label is 39 characters and does not hold one line on a phone,
   * so the fixed height is released here and the tracking eased. */
  .faq-picker-button {
    height: auto;
    min-height: 43px;
    padding-block: var(--s-2);
    font-size: 15px;
    letter-spacing: 1px;
  }
}


/* --- Rebuilt page: FAQ ------------------------------------------------ */
/* --- Rebuilt page: FAQ detail ----------------------------------------
 *
 * Measured off the live /workers-comp-faqs at 1440px; the full table is in
 * notes/wip/faq-detail-migration.md. The band boundaries are 228 / 628 / 692 /
 * 1590 / 2000 and every number below is a difference between two of them.
 * /es-us/workers-comp-faqs measures identically, so nothing here branches on
 * locale.
 */

/* 400px, against the 346 the practice banners use and the 261 /contact and
 * /faqs use. Hero height varies by page type on the source -- docs/PARITY-AUDIT.md
 * 1b, where assuming one height shipped a defect. No photograph: the rows carry
 * a hero_image but the source paints the band as flat --navy. */
/* 140px above the title, which is where the source puts it and is a CONSTANT
 * rather than a function of the title: measured at band top + 140 on
 * /workers-comp-faqs, /personal-injury-faqs AND /es-us/workers-comp-faqs,
 * whose title runs three lines and 360px tall. The band is 408 on all three.
 *
 * The 20px this used to carry was chosen so a 360px Spanish title still fitted
 * a 400px band -- which it does, at the cost of putting EVERY title 120px above
 * the source's. The source does not solve that problem: on the Spanish pages it
 * holds the band at 408 and lets the title overflow it by 92px. We keep the
 * title where the source puts it and let the band grow instead, so those pages
 * run ~92px tall rather than overlapping the copy beneath. See
 * docs/PARITY-AUDIT.md.
 *
 * No photograph: the rows carry a hero_image and the source paints flat --navy.
 * Hero height varies by page type -- PARITY-AUDIT 1b, where assuming one height
 * shipped a defect. */
.practice-head.hero-faq {
  min-height: 408px;
  /* CENTERED in the band, which is the one rule that fits both languages.
   *
   * The inset is not a constant: measured across thirteen FAQ pages the source
   * sets it to 140 for a one-line title, 84 for two lines and 24 for three --
   * 120, 240 and 360px of title. Those are (408 - title) / 2 to the pixel on
   * the two- and three-line pages and within 4px on the one-line ones, so the
   * source is centering and the three "different" numbers are one rule seen
   * three times.
   *
   * A constant 140 was tried first and fits the English one-line pages and
   * several Spanish ones, but drops a three-line English title to 140-500 in a
   * 408 band -- overflowing, where the source has it at 24-384 and inside. The
   * 20px this carried before that put EVERY title about 120px above the
   * source's.
   *
   * Four Spanish pages sit at 84 in a 454 band, which centering does not
   * explain; those are the source's own per-page edits, and .practice-head's
   * comment already records that Wix hand-positions this content. */
  align-items: center;
  padding-block: 0;
  /* The navy is a fixed 408px LAYER rather than the section's own fill, which
   * is the single rule that fits English and Spanish at once.
   *
   * The source paints the band 220-628 on every one of these pages and starts
   * the title at 140 regardless of its length. Where a three-line Spanish
   * title runs past 628 it simply overflows the navy onto white -- but the
   * copy beneath still starts below the TITLE, not below the band
   * (/es-us/workers-comp-faqs: title ends 720, back link 730; the English one:
   * title ends 480, band ends 628, back link 652).
   *
   * So the section flows and grows with its title, and the fill does not. One
   * rule, no branch on locale. */
  background: none;
}
.practice-head.hero-faq::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 408px;
  background: var(--navy);
  z-index: 0;
}
.practice-head.hero-faq > * { position: relative; z-index: 1; }
/* 85px, the page default, not the 66px the practice banners drop to: the title
 * measures 120px tall on the live page, which is 85px at the 1.4 line-height. */
.practice-head.hero-faq h1 {
  /* Flat, not a clamp. The source sets 85px at every width measured -- 780,
     980 and 1440 all read 85/119 -- while `clamp(40px, 6vw, 85px)` resolved to
     46.8 at 780 and 58.8 at 980, reaching 85 only at 1440. The vw term cannot
     be repaired by raising it either: the desktop build holds a 980 canvas
     below 980 while `vw` keeps tracking the smaller window, so any vw undershoots
     there. */
  font-size: var(--size-hero);
  /* Set, not inherited: the shared rule pins 89.6px, which is 1.4 of the 64px
   * the practice banners use, and left this title in a 90px box. */
  line-height: 1.4;
  margin: 0;
}

/* The accordion widget is inset 32px inside the 980 container, putting its
 * content at x=262 and 916 wide. */
.faq-main {
  padding-inline: 32px;
  /* The back link sits 24px under the banner; 32px closes the widget. */
  padding-top: 24px;
  padding-bottom: 32px;
}

/* The source pins this block and lets the space after the last card flex,
   rather than leaving a fixed gap: main runs 227 to 2000 on both locales even
   though the Spanish page's taller title and wrapped questions push its
   content 102px further down. Fixing the trailing gap instead would leave the
   Spanish page 61px taller than the source. Same call as .contact-main. */
.faq { min-height: 1773px; }

/* Box runs y=652 to 692, with the label on the 16px baseline at 663. */
.faq-back {
  margin: 0 0 32px;
  min-height: 40px;
  font-family: 'Nunito Sans', Helvetica, Arial, sans-serif;
  font-size: var(--size-body);
}
.faq-back a { color: var(--navy-button); text-decoration: underline; }
.faq-back a:hover, .faq-back a:focus-visible { color: var(--rust); }

/* Heading left, search right, both on the same 724 line. */
.faq-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  margin-bottom: 24px;
}
/* 32px/400 -- lighter than the 700 the base h2 rule sets. */
.faq-heading {
  margin: 0;
  font-family: var(--body);
  font-size: 32px;
  font-weight: 400;
  line-height: 1.2;
  color: var(--ink);
}

/* 280 wide with a single hairline under it, and the magnifier inside the
   field's right edge. Revealed by static/js/faq.js. */
.faq-search {
  position: relative;
  flex: 0 0 280px;
  max-width: 280px;
  border-bottom: 1px solid rgb(0 0 0 / 60%);
}
.faq-search input {
  /* The source's field stops short of the magnifier rather than padding itself
     out behind it: its input measures 256 inside the same 280 rail, with
     `padding: 8px 0`. Ours ran the input the full 280 and reserved 26px of
     right padding, which put the caret and the placeholder 26px left of the
     source's. */
  width: calc(100% - 24px);
  padding: 8px 0;
  border: 0;
  background: none;
  font-family: var(--body);
  font-size: var(--size-body);
  line-height: 1.5;
  color: var(--ink);
}
/* The source paints the placeholder in full black, not a muted grey. Chrome's
   default is 117,117,117 and no gate here reads a pseudo-element, so this was
   invisible to the whole stack. */
.faq-search input::placeholder { color: rgb(0 0 0); opacity: 1; }
.faq-search input:focus-visible { outline: 2px solid var(--navy-button); outline-offset: 2px; }
/* 24x24, and it overhangs the 280px rail by 4px: on the source the magnifier
   runs x=1158..1182 at 1440 beside an input that ends at 1154, and x=284..308
   at 320 beside an input that ends at 280. Both builds draw it the same size,
   so 18px here was 6px small on the phone and the desktop alike. */
.faq-search svg {
  position: absolute;
  right: -4px;
  top: 50%;
  width: 24px;
  height: 24px;
  transform: translateY(-50%);
  color: var(--ink);
  pointer-events: none;
}

/* One bordered white card per question, 12px apart. */
.faq-list { display: grid; gap: 12px; }

.faq-item {
  border: 1px solid var(--navy);
  background: var(--paper);
}

/* 80px minimum, so a one-line question sits in an 82px card and a two-line one
   grows to 98 -- both measured. */
.faq-item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  min-height: 80px;
  padding: 24px;
  cursor: pointer;
  list-style: none;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-question {
  /* An <h3>, so the base heading rule's display face, 700 weight and bottom
     margin all have to be undone. */
  margin: 0;
  font-family: var(--body);
  font-size: 20px;
  font-weight: 400;
  line-height: 1.2;
  color: var(--ink);
}

/* Chevron, drawn in CSS rather than loaded as an icon font.

   12.5px at 1.5px is what reproduces the source's mark. Its `Expand-ChevronDown`
   svg is a 24x24 viewBox drawn at 30x30, and the path's own getBBox() is
   14.143 x 7.779 user units -- 17.7 x 9.7 painted, at both 1440 and 320. The
   earlier 10px at 2px painted 14 x 9, and being thicker made it proportionally
   too tall as well as too small. */
.faq-item summary::after {
  content: "";
  flex: 0 0 auto;
  width: 12.5px;
  height: 12.5px;
  margin-right: 4px;
  border-right: 1.5px solid var(--navy);
  border-bottom: 1.5px solid var(--navy);
  transform: translateY(-25%) rotate(45deg);
  /* No transition. The source does not rotate this: it swaps one SVG for
     another -- data-label goes Expand-ChevronDown to Collapse-ChevronUp with
     transform none and transition-duration 0s throughout. Measured by sampling
     the live icon while opening a question. A rotation here read as a slower,
     softer control than the source's. */
}
.faq-item[open] summary::after { transform: translateY(25%) rotate(-135deg); }

/* The panel is animated open by static/js/faq.js, not from here.
 *
 * This was first done in CSS with ::details-content plus `interpolate-size:
 * allow-keywords`, which is what lets height animate to `auto`. It works in
 * Chrome and does nothing at all in Firefox, which has not shipped
 * interpolate-size -- so the panel eased open in one browser and snapped in
 * the other, and the CSS reported itself as supported in whichever browser it
 * was tested in. Driving it from script is the only way to get one behavior
 * everywhere.
 *
 * overflow is hidden so the answer is clipped while its height is animating
 * rather than spilling out of the card. */
.faq-answer { overflow: hidden; }

.faq-item summary:hover .faq-question,
.faq-item summary:focus-visible .faq-question { color: var(--navy-button); }

/* The answer is flush with the top of the content box; only the sides and
   foot are padded. */
.faq-answer { padding: 0 24px 24px; }
.faq-answer p {
  margin: 0 0 var(--s-2);
  font-size: var(--size-body);
  line-height: 1.5;
}
.faq-answer p:last-of-type { margin-bottom: 0; }

/* The source's empty state: two lines of 16/22.4 in black, its heading run at
 * the same size and weight as the sentence under it. */
.faq-no-results {
  margin-top: var(--s-4);
  color: #000;
  font-size: 16px;
  line-height: 22.4px;
}
.faq-no-results p { margin: 0; }
/* The term echoed back under the search box. 16/22.4 at 400 in pure black,
 * measured on the live page with a term typed into it; the source opens 34px
 * under the input on the desktop build and 24 on the phone. */
.faq-showing {
  margin: 34px 0 0;
  font-size: 16px;
  line-height: 22.4px;
  font-weight: 400;
  color: #000;
}

/* An unanswered question is visible in preview but must not look like a
   finished page. */
.faq-placeholder { color: var(--rust); font-style: italic; }
.faq-item.is-empty .faq-question { color: var(--navy-mid); }

/* The share row at the foot of an open answer: 144x31, its left edge flush
   with the answer text, 16px below the last paragraph. */
/* 24x24 icons on a 40px pitch, so 16px between them and 144 across -- the
 * bar's measured width. Ours ran a 19px glyph inside a 31px box on a 9px gap,
 * which reaches the same 40px pitch by coincidence and so matched every
 * position while painting the icon 5px small. Measured on the live share row
 * at 1440 and again on the phone build, where it is the same 24. */
.share-bar {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 16px 0 0;
  padding: 0;
  list-style: none;
}
.share-link {
  display: flex;
  align-items: center;
  justify-content: center;
  /* 24 is also the WCAG 2.5.8 minimum target size exactly, so matching the
   * source here does not cost the AA criterion. */
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--navy);
  cursor: pointer;
}
.share-link svg { width: 24px; height: 24px; }
.share-link:hover, .share-link:focus-visible { color: var(--navy-button); }
.share-copy.is-copied { color: var(--rust); }

@media (max-width: 768px) {
  .faq-main { padding-inline: 0; padding-bottom: var(--s-8); }
  .faq-head { flex-direction: column; align-items: flex-start; }
  .faq-search { flex: 1 1 auto; max-width: none; width: 100%; }
  .faq-item summary { padding: var(--s-3); min-height: 0; }
  .faq-answer { padding: 0 var(--s-3) var(--s-3); }
}

/* --- Rebuilt page: attorney ------------------------------------------ */

/* Every number below is an ink position read off /team/allan-m.-kluger at
   1440, cross-checked against Quinn, Gabriel and Giarratano. The page is a
   navy hero, then two columns, then optional badges, then a motto band. */

.attorney-head {
  background: var(--navy);
  color: var(--paper);
  text-align: center;
  /* The band runs to y=482 with the header ending at 228, so 254 of it shows.
     It reaches up behind the header on the source, which changes nothing that
     is visible and is not reproduced. */
  height: 254px;
  box-sizing: border-box;
  padding-top: 75px;
}
.attorney-head h1 {
  color: var(--paper);
  font-size: 65px;
  line-height: 91px;
  margin: 0;
}
/* Italic, and set in the display face at 35 -- not the 16px body Montserrat
   that was here, which read as a caption rather than a title. */
.attorney-role {
  font-family: var(--display);
  font-size: 35px;
  line-height: 49px;
  font-style: italic;
  font-weight: 400;
  margin: 0;
}
/* Ranged left at the container edge. The source sets this in the same
   avenir-lt-w01_35-light the navigation uses, so it takes the same substitute
   for the same reason -- see .nav-top, where the measurements are. */
.attorney-back {
  font-family: 'Nunito Sans', Helvetica, Arial, sans-serif;
  font-weight: 300;
  font-size: 16px;
  line-height: 22.4px;
  letter-spacing: .02em;
  text-align: left;
  margin: 14px 0 0;
}
.attorney-back a { color: var(--paper); text-decoration: none; }
.attorney-back a:hover { text-decoration: underline; }

/* 650 + 17 + 313 = 980, the container's content width. The biography's own
   text starts 15px into its column, which is where the source puts it. */
.attorney-body {
  display: grid;
  /* 651 + 16 + 313 = 980. The biography's measure is 636 after its 15px
     inset, which is the source's; at 635 lines sitting on the boundary broke
     in the wrong places, in both directions. */
  grid-template-columns: 651px 313px;
  gap: 16px;
  align-items: start;
}
.attorney-bio { padding: 15px 0 0 15px; }
/* The source sets break-spaces on this copy: a trailing space at a line end is
   kept rather than collapsed, so it counts toward the line's width. Without it
   every line ran ~4px narrow and lines sitting near the measure broke a word
   later than the source's. */
.attorney-bio p,
.attorney-bio li { white-space: break-spaces; }
.attorney-bio p {
  font-size: 16px;
  line-height: 24px;
  /* 24, giving the 29px the source leaves between one paragraph's last line
     and the next one's first. */
  margin: 0 0 24px;
}
.attorney-bio p:last-child { margin-bottom: 0; }
/* Award lists: markers on the li, not the ul, and 24 of indent per level. */
.attorney-bio ul,
.attorney-bio ol { list-style: none; margin: 0; padding-left: 24px; }
.attorney-bio li {
  margin: 0;
  padding-left: 8px;
  font-size: 16px;
  line-height: 24px;
  list-style-type: disc;
}
.attorney-bio li li { list-style-type: circle; }
.attorney-bio li p { margin: 0; }

.attorney-photo { display: block; width: 313px; height: 420px; object-fit: cover; }

/* The panel is --shell and runs 322px under the photograph. */
.attorney-panel {
  background: var(--shell);
  /* 15 on the right, not 19. "Estate Planning & Administration" measures 279
     and a symmetric 19 leaves 275, which wrapped it onto a second line and
     pushed the three items under it down by a full row. */
  padding: 32px 15px 0 19px;
  min-height: 322px;
  box-sizing: border-box;
}
/* Indented 9px past the panel's own inset: the contact rows start at x=925
   where the heading and the practice list below them start at 916. */
.attorney-contact {
  list-style: none;
  margin: 0;
  padding-left: 9px;
  font-size: 16px;
  line-height: 22.4px;
  display: flex;
  flex-direction: column;
  /* 28px between the two rows' ink, against a 22.4 line box. */
  gap: 5.6px;
}
.attorney-contact li { display: flex; align-items: center; }
.attorney-contact a { color: var(--ink); text-decoration: none; }
.attorney-contact a:hover { text-decoration: underline; }
.attorney-icon { width: 21px; height: 21px; flex: none; margin-right: 16px; }

/* 183x3, black, and inset to the text column rather than the panel's edge. */
.attorney-rule {
  width: 183px;
  height: 3px;
  margin: 18px 0 0 46px;
  border: 0;
  background: rgb(0, 0, 0);
}
.attorney-practices-head {
  font-family: var(--body);
  font-size: 24px;
  line-height: 33.6px;
  font-weight: 700;
  color: var(--ink);
  margin: 18px 0 0;
}
/* Bold, and one item per line. The source lists each area on its own row. */
.attorney-practices {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 16px;
  line-height: 24px;
  font-weight: 700;
  color: var(--ink);
  margin-top: 10px;
}

/* A 980px window, clipped, holding a row that scrolls itself. */
.badge-gallery { position: relative; }
.attorney-badges {
  list-style: none;
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 14px;
  margin: 76px 0 0;
  padding: 0;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.attorney-badges::-webkit-scrollbar { display: none; }
.attorney-badges li { flex: none; }
.attorney-badges img { display: block; height: 150px; width: auto; }

.badge-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 23px;
  height: 39px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  filter: drop-shadow(0 1px 2px rgb(0 0 0 / 45%));
}
.badge-arrow[hidden] { display: none; }
.badge-arrow svg { display: block; width: 23px; height: 39px; fill: var(--paper); }
.badge-arrow-prev { left: 23px; transform: translateY(-50%) scaleX(-1); }
.badge-arrow-next { right: 23px; }
/* 224 below the biography with no badges; 46 when a badge row precedes it. */
.attorney-motto {
  margin-top: 224px;
  background: var(--navy);
  color: var(--paper);
  height: 155px;
  box-sizing: border-box;
  padding-top: 26px;
}
.attorney-badges-row + .attorney-motto { margin-top: 46px; }
.attorney-motto h2 {
  font-family: var(--display);
  font-size: 52px;
  line-height: 72.8px;
  font-weight: 700;
  color: var(--paper);
  margin: 0;
  white-space: nowrap;
}
.attorney-motto h2 sup {
  font-size: 20px;
  line-height: 0;
  vertical-align: 33px;
  margin-left: 5px;
}


/* --- Rebuilt page: case results -------------------------------------- */

.result-meta { margin: 0; display: flex; flex-wrap: wrap; gap: var(--s-1); }
.result-figure {
  font-family: var(--display);
  font-size: clamp(28px, 5vw, var(--size-h2));
  color: var(--navy-deep);
}
.disclaimer { font-size: var(--size-small); color: var(--navy-mid); max-width: 70ch; }

/* The top of a case-result post, rebuilt to the source's own shape. It used to
 * put the article's headline in the navy band with a breadcrumb over it; the
 * source puts a generic "Our Results." there, a strip of category tabs under
 * the band, and the headline inside the same bordered card the listing draws.
 * Measured on the live post at 1440:
 *
 *     band        rgb(35, 44, 83) = --navy, y 81..489 behind a 221px header
 *     band title  "Our Results." libre baskerville 700, 85px/119, white,
 *                 centred, its box 547x105 at y=308
 *     tabs        980x80 white at y=489, links montserrat 16/400 black on a
 *                 22px line, first at x=250 and about 40px apart
 *     card        940x437 at x=250 y=589, white, 1px solid rgb(232 230 230/75%)
 *     headline    montserrat 400 40px/50 in a 740px column, x=350
 *
 * The band title is a <p role="heading">, not a second <h1>; see the comment in
 * templates/pages/case_result.html for why. */
.result-band {
  /* 262 is the band's own height below the header: the source paints it from
     the header's foot at 227 down to 489. The 268 recorded here measured from
     221, a header height this site no longer has, and put every band below it
     6px low. `--banner-height` is .practice-head's own hook; its 346px default
     is the practice pages' band, not this one.
     80 rather than the source's 87 because its 105px box is the inline span's
     content height and ours is the block's 119px line box, so the text lands
     where its text does (the same trap as the news headline, in
     .news-article h1); the 6px comes off the foot, which carries nothing. */
  --banner-height: 262px;
  padding: 80px 0 63px;
}
.result-band-title {
  margin: 0;
  font-family: var(--display);
  font-size: 85px;
  line-height: 119px;
  font-weight: 700;
  color: var(--paper);
  text-align: center;
}
.result-tabs { background: var(--paper); }
.result-tabs-row {
  display: flex;
  align-items: center;
  gap: 40px;
  list-style: none;
  margin: 0;
  padding: 0 20px;
}
/* The row's 80px comes from the links rather than a pinned height: the source
   sets them on a 22px line at y=518, 29 into an 80px row, and 22 + 29 + 29 is
   that 80. Derived, so the row grows with its own type instead of clipping it
   if the face or size ever changes. */
.result-tabs-row a,
.result-tabs-row summary { padding-block: 29px; }
.result-tabs-row a,
.result-tabs-row summary {
  font-family: var(--body);
  font-size: 16px;
  font-weight: 400;
  line-height: 22px;
  color: var(--ink);
  text-decoration: none;
  cursor: pointer;
}
.result-tabs-row a:hover { text-decoration: underline; }
/* <details> rather than script: the strip has to work with none, and this is
   the same disclosure shape the rest of the site uses for an overflow menu. */
.result-tabs-more { position: relative; }
.result-tabs-more summary { list-style: none; }
.result-tabs-more summary::-webkit-details-marker { display: none; }
.result-tabs-more ul {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 20;
  min-width: 200px;
  margin: 0;
  padding: 8px 0;
  list-style: none;
  background: var(--paper);
  border: 1px solid rgb(232 230 230 / 75%);
}
.result-tabs-more ul a { display: block; padding: 8px 20px; }
.result-card {
  /* 20px under the strip: the source's tabs close at 569 and its card opens at
     589. */
  margin-top: 20px;
  box-sizing: border-box;
  width: 940px;
  max-width: 100%;
  margin-inline: auto;
  background: var(--paper);
  /* The listing card's own edge, which is what the source reuses here. */
  border: 1px solid rgb(232 230 230 / 75%);
  padding: 60px;
}
.result-card-title {
  max-width: 740px;
  margin: 19px auto 0;
  font-family: var(--body);
  font-size: 40px;
  line-height: 50px;
  font-weight: 400;
  color: var(--ink);
}

/* The post's body, in the same 740px column as the headline above it.
   Measured on the live post at 1440: 18px/27 montserrat at x=350, its first
   line 22px under the headline. It inherited the card's 16px and sat at
   x=311, a point small and 39px wide of the headline it belongs under. */
.result-card-body {
  max-width: 740px;
  margin: 22px auto 0;
  font-family: var(--body);
  font-size: 18px;
  line-height: 27px;
  color: var(--ink);
}
/* No margin: the two multi-paragraph posts separate their paragraphs with a
   stored `<br/>`, which is one 27px line and is the whole gap the source
   shows. A 27px bottom margin here as well doubled it to 54. Every other post
   is a single paragraph, so the margin was invisible outside those two. */
.result-card-body p {
  margin: 0;
}

/* The post's categories under its body. Measured on the live post at 1440:
   14px/21 montserrat black, underlined, the first at x=354 against a card
   opening at x=350, 28px under the body's last line. */
.result-card-cats {
  max-width: 740px;
  margin: 28px auto 0;
  font-family: var(--body);
  font-size: 14px;
  line-height: 21px;
  color: var(--ink);
}
.result-card-cats a {
  color: inherit;
  text-decoration: underline;
}
.result-card-cats-sep {
  /* The source sets the middot apart from the labels it divides. */
  padding-inline: 6px;
}

/* Recent Posts at 320, where the source turns the three-up grid into a slider:
 * seven items 248x288 on one row at a 260px pitch, one of them centred in the
 * canvas at x=36, the section 320x377 from y=777 with its heading 18/27 at
 * x=18. Wix translates the row with script; this scrolls and snaps instead,
 * which reads the same, keeps native momentum, and works with no script at all.
 * The pitch is the item plus a 12px gap. */
html[data-device="phone"] .recent-posts > .container {
  width: auto;
  padding-inline: 18px;
}
/* 62px from the card's closing rule to the strip, measured on the live phone
   page: the card ends at 715 and "Recent Posts" opens at 777. */
html[data-device="phone"] .recent-posts { margin-top: 59px; padding-bottom: 62px; }

html[data-device="phone"] .recent-posts-grid {
  display: flex;
  gap: 12px;
  /* The source opens its first card 47px under the heading's top. */
  margin-top: 0;
  /* Out through the container's own inset so a card can sit against the edge
     while the heading above it stays at 18. The 36px inset centres the resting
     slide in the 320 canvas the way the source does -- (320 - 248) / 2 -- which
     an 18px one left 18px wide of it. */
  margin-inline: -18px;
  padding-inline: 36px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: 36px;
  /* The scrollbar is a desktop affordance; the source shows none. */
  scrollbar-width: none;
}
html[data-device="phone"] .recent-posts-grid::-webkit-scrollbar { display: none; }
html[data-device="phone"] .recent-post {
  flex: 0 0 248px;
  scroll-snap-align: start;
  /* 288 here against the desktop card's 268.5, which is the source's own pair. */
  min-height: 288px;
  /* The source draws no box around a card at 320 -- the desktop card's 1px
     edge is a desktop-only thing, and it read as a line down the carousel. */
  border: 0;
  display: flex;
  flex-direction: column;
}
/* The rule at the card's foot: 1px of rgba(0,0,0,.2) across the 200px content
   measure, sitting 24px off the card's bottom with 33px of air above it. */
html[data-device="phone"] .recent-post-rule {
  margin-top: auto;
  height: 33px;
  border-top: 1px solid rgb(0 0 0 / 20%);
}
.recent-post-rule { display: none; }
html[data-device="phone"] .recent-post-rule { display: block; }

/* The carousel's three dots, centred under it: 6px circles on a 12px pitch,
   the active one the source's orange. */
.recent-posts-dots { display: none; }
html[data-device="phone"] .recent-posts-dots {
  display: flex;
  justify-content: center;
  gap: 6px;
  margin-top: 18px;
}
html[data-device="phone"] .recent-posts-dots span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgb(0 0 0);
  /* The source fades the inactive dots rather than colouring them grey; at
     full strength they read as three black dots instead of one marker. */
  opacity: 0.2;
}
html[data-device="phone"] .recent-posts-dots span.is-active {
  background: rgb(196 83 8);
  opacity: 1;
}
/* 18/27, which the shared rule below leaves to inherit and the phone build sets
   looser -- the source's heading measures 27px tall on both canvases. */
/* The source keeps the heading and "See All" on one row at 320 as well as at
   1440 -- heading at x=18, link ending on the 18px gutter at the other edge.
   They used to stack here, which put "See All" on its own line under the
   heading and the strip 50px further down than the source's. */
html[data-device="phone"] .recent-posts-head {
  display: flex;
  justify-content: space-between;
  /* Tops, not baselines: the source puts the 18px heading and the 14px link at
     the same y (777), which a shared baseline cannot do at two sizes. */
  align-items: flex-start;
}
/* Family and weight as well as size: this only set the size, so the heading
   fell through to the global h2 and painted Libre Baskerville 700 where the
   source paints montserrat 400. The desktop rule above states the family; the
   phone one did not. */
html[data-device="phone"] .recent-posts-head h2 {
  font-family: var(--body);
  font-size: 18px;
  line-height: 27px;
  font-weight: 400;
}
html[data-device="phone"] .recent-posts-all { font-size: 14px; line-height: 21px; }

/* The same page at 320. Measured on the live post with an iPhone UA: the band
 * heading is 35px/49 in a 225x43 box centred at y=157, the card runs the full
 * 320 with its copy in a 284px column at x=18, its headline 26px/36.4 -- and
 * there is NO category strip at all, so ours goes with it rather than being
 * squeezed onto a 280px row. */
/* `.practice-head.result-band`, not `.result-band` alone: the phone build's own
   .practice-head rule lands later in this file at the same specificity and
   would otherwise keep its padding. */
html[data-device="phone"] .practice-head.result-band {
  /* !important because the shared phone rule for .practice-head carries it on
     both of these, and 188px centred is the practice pages' band, not this
     one. The source's runs 134 to 223 -- 89px, its heading top-aligned at 157
     with 23px above it -- not the 272 recorded here before, which left the
     band 49px deep and pushed the whole page down by that much. Measured on
     the live post at 320 and agreed by tools/band_diff.py. */
  min-height: 0 !important;
  padding: 23px 0 17px !important;
  align-items: start;
}
html[data-device="phone"] .result-band-title { font-size: 35px; line-height: 49px; }
html[data-device="phone"] .result-tabs { display: none; }

/* The post's category disclosure is the phone build's alone: on the desktop
   page the source paints the tab row above, and `.results-cats` would render
   as the results index's sidebar. */
.result-phone-cats { display: none; }
/* The 18px gutter `.results-cats` expects: it pulls itself out by -18px to run
   the full canvas, which the results index's container supplies and this
   wrapper did not -- so the bar sat at -18 and its label at x=0 rather than
   the source's 18. */
html[data-device="phone"] .result-phone-cats {
  display: block;
  padding-inline: 18px;
}
html[data-device="phone"] .result-card {
  width: auto;
  /* max-width caps the box at the container's content width, so without
     releasing it the negative margins move the card left without widening it. */
  max-width: none;
  margin-inline: -20px;   /* out through .container's own gutter, to the edge */
  margin-top: 0;
  border: 0;
  /* 32 at the head: the source's card opens at 272 and its byline row sits at
     304, 32 tall, with the headline 8px under it at 344. The 72 here before
     was that same 344 measured with no byline rendered, so adding the row
     pushed the headline 40px past the source's.
     Nothing at the foot: the card ends on `.result-card-rule`, at 715. */
  padding: 32px 18px 0;
}
html[data-device="phone"] .result-card-title {
  max-width: none;
  margin-top: 0;
  font-size: 26px;
  line-height: 36.4px;
}

/* The card's closing rule, phone only: 1px of rgba(0,0,0,.2) across the 284px
   measure, 22px under the categories, with 18px of air under it. The card ends
   at the rule's foot and the Recent Posts strip opens 62px below that. */
.result-card-rule { display: none; }
html[data-device="phone"] .result-card-rule {
  display: block;
  margin-top: 22px;
  height: 18px;
  border-top: 1px solid rgb(0 0 0 / 20%);
}

/* The byline is the phone build's alone -- the source's desktop post has none.
   Measured at 320: the row is 32px tall from x=18, its avatar 32x32, the name
   12/15 montserrat at x=62, and the headline 8px under it. */
.result-byline { display: none; }
html[data-device="phone"] .result-byline {
  display: flex;
  /* The source sets the name against the TOP of the 32px row -- its row opens
     at 304 and the name's box at 305 -- not centred in it. */
  align-items: flex-start;
  /* 12px puts the name at 18 + 32 + 12 = 62, where the source's sits. */
  gap: 12px;
  margin: 0 0 8px;
  font-family: var(--body);
  font-size: 12px;
  line-height: 18px;
  font-weight: 400;
  color: var(--ink);
}
html[data-device="phone"] .result-byline-avatar {
  flex: none;
  width: 32px;
  height: 32px;
}

/* The phone post, measured on the live page at 320: the body is 16px at x=18
   and the two category links stack rather than sitting either side of a
   middot, at y=628 and y=656. */
html[data-device="phone"] .result-card-body {
  max-width: none;
  font-size: 16px;
  line-height: 24px;
}
html[data-device="phone"] .result-card-cats {
  max-width: none;
  /* 20px under the body's last line: the source's body sits at 584 on a 24px
     line and its first category at 628. */
  margin-top: 20px;
}
html[data-device="phone"] .result-card-cats a {
  display: block;
  /* 28px between the two links' tops, against a 21px line. */
  margin-bottom: 7px;
}
html[data-device="phone"] .result-card-cats-sep {
  display: none;
}

/* The results band closes the POST differently from the results index: at 320
   the source paints the disclaimer alone here, with no motto above it, and
   sets it in 10px. The index keeps its 27px heading -- see the live /results
   phone build -- so this is scoped to the post rather than to .results-note. */
html[data-device="phone"] .results-note-post h2 {
  display: none;
}
html[data-device="phone"] .results-note-post p {
  /* The source's band at 320 IS the disclaimer: 31px tall with no padding of
     its own, the text 10/18 inset 27px and measuring 262 wide. Ours carried
     44px of band padding and a 23.4px line box, which ran it to three lines
     in a 161px band. */
  font-size: 10px;
  line-height: 18px;
  padding-inline: 27px;
  margin: 0;
  /* The source centres the disclaimer at 320; ours read from the start edge. */
  text-align: center;
}
html[data-device="phone"] .results-note-post {
  /* The source's band runs 1215 to 1309 with the disclaimer at 1237: 22px
     above the text and 23 below it. */
  padding: 22px 0 23px;
}
/* The 27px inset is the text's, measured from the canvas edge -- not 27 on top
   of the container's own 20, which put it at 47. */
html[data-device="phone"] .results-note-post > .container {
  padding-inline: 0;
}

/* The "Recent Posts" strip that closes every case-result post.
 *
 * Measured on the live post
 * /post/11-800-000-settlement-in-a-wrongful-death-case-due-to-the-failure-to-properly-maintain-an-elevator
 * at 1440: the section runs x=250 to x=1190, so 940 wide, and is 315.5 tall --
 * a 27px header row, a 20px gap, and a 268.5px card row.
 *
 * Every selector is held off the phone build, which the source turns into a
 * seven-item carousel that this block does not attempt. */
/* 30px above the strip and 20px below its cards, both measured on the live
   post at 1440: the card's foot at 1026 to the heading at 1056, and the cards'
   foot at 1372 to the closing band at 1392. `.results-note` brings 11px of
   that 20 as its own margin -- it is the results index's rule too, so the
   remainder is stated here rather than by widening that one. */
html:not([data-device="phone"]) .recent-posts {
  margin-top: 30px;
  padding-bottom: 9px;
}
html:not([data-device="phone"]) .recent-posts > .container {
  max-width: 940px;
  padding-inline: 0;
}
html:not([data-device="phone"]) .recent-posts-head {
  display: flex;
  justify-content: space-between;
  font-size: 18px;
  line-height: 27px;
}
/* The header's 27px is the heading's own line box; the link stretches to it. */
html:not([data-device="phone"]) .recent-posts-head h2 {
  margin: 0;
  font-family: var(--body);
  font-size: 18px;
  line-height: 27px;
  font-weight: 400;
  letter-spacing: normal;
  color: var(--ink);
}
html:not([data-device="phone"]) .recent-posts-all {
  display: block;
  font-family: var(--body);
  font-size: 14px;
  line-height: 21px;
  font-weight: 400;
  color: var(--ink);
  text-decoration: none;
}
html:not([data-device="phone"]) .recent-post { min-height: 268.5px; }
/* The wide build shows three of the seven the phone slider carries, which is
   what the source's grid paints. */
html:not([data-device="phone"]) .recent-post:nth-child(n+4) { display: none; }
html:not([data-device="phone"]) .recent-posts-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 34px;
  margin-top: 20px;
}
/* Cards are 290.67 wide -- (940 - 2 x 34) / 3 -- and 268.5 tall on the source,
 * which reserves that height with a percentage padding rather than letting the
 * copy set it: its text ends 87px above the card's foot. */
.recent-post {
  padding: 24px;
  background: var(--paper);
  border: 1px solid rgba(232, 230, 230, .75);
  font-size: 18px;
  line-height: 18px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  /* The anchor point for the title link's overlay below. */
  position: relative;
  transition: transform .18s ease, box-shadow .18s ease;
}
/* The card lifts under a pointer. Behind `hover: hover` so a touch device does
   not leave a card stuck in the grown state after a tap. */
@media (hover: hover) {
  .recent-post:hover {
    transform: scale(1.012);
    box-shadow: 0 3px 10px rgba(0, 0, 0, .07);
  }
}
@media (prefers-reduced-motion: reduce) {
  .recent-post { transition: none; }
}
/* The whole card is the link's hit area, not just its title. The overlay is
   part of the anchor, so hovering the excerpt raises the title's hover state
   and a click anywhere in the card follows it -- without a second `<a>` around
   the card, which would nest a link inside a link.

   The cost is that the excerpt text can no longer be selected with a drag. */
.recent-post-title a::after {
  content: '';
  position: absolute;
  inset: 0;
}
.recent-post-title {
  margin: 0;
  font-family: var(--body);
  font-size: 18px;
  line-height: normal;
  font-weight: 400;
  letter-spacing: normal;
}
/* The source clamps the LINK, not the heading around it: its anchor measures
 * 240.7 x 44, two lines, with the rest clipped. */
/* Every link the post itself owns turns this blue under a pointer and under
   keyboard focus on the source -- the category strip, the card's own category
   links, "See All" and a recent post's title. Measured with tools/state_diff.py
   against /contact as a control, which shows only the shared header and footer
   differing; these eight were the page's own and changed colour nowhere.

   Listed rather than written as `.result a`, because the category sheet's rows
   live inside the same article and the source highlights those by background
   instead, at 6% black. */
/* Every link the post itself owns turns this blue under a pointer and under
   focus, on BOTH builds -- the category strip, the card's own category links,
   "See All" and a recent post's title. Measured with tools/state_diff.py
   against /contact as a control, which shows only the shared header and footer
   differing.

   Listed rather than written as `.result a`, because the category sheet's rows
   live inside the same article and the source highlights those by background
   instead, at 6% black. `html` on the "See All" pair matches the weight of the
   build-scoped rule that sets its resting colour, which otherwise outranks
   this one. */
.result-tabs-row a:hover,
.result-tabs-row a:focus,
.result-card-cats a:hover,
.result-card-cats a:focus,
html .recent-posts-all:hover,
html .recent-posts-all:focus,
.recent-post-title a:hover,
.recent-post-title a:focus { color: rgb(10 45 140); }

/* Underlined as well as recolored, but only with the pointer on the words --
   the link's ::after covers the card, so `a:hover` is true anywhere in it.
   The span sits above that overlay, so this fires on the text alone. Keyboard
   focus underlines from the anchor, where there is no pointer to place.
   The source recolors and never underlines; see docs/PARITY-AUDIT.md. */
.recent-post-title a > span { position: relative; z-index: 1; }
.recent-post-title a > span:hover,
.recent-post-title a:focus-visible { text-decoration: underline; }

.recent-post-title a {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  text-overflow: ellipsis;
  overflow-wrap: break-word;
  color: var(--ink);
  text-decoration: none;
}
/* 16px under the title, four 24px lines, clipped. The server cuts the excerpt
 * at 200 characters with no ellipsis, as the source stores it; the ellipsis a
 * reader sees is the clamp's. */
.recent-post-excerpt {
  margin: 16px 0 0;
  font-family: var(--body);
  font-size: 16px;
  line-height: 24px;
  font-weight: 400;
  letter-spacing: normal;
  color: var(--ink);
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  overflow-wrap: break-word;
  word-break: break-word;
  overflow: hidden;
}

.badge {
  display: inline-block;
  padding: 2px var(--s-2);
  font-size: 12px;
  letter-spacing: .04em;
  text-transform: uppercase;
  background: var(--gold);
  color: var(--navy-deep);
  text-decoration: none;
}
.badge-quiet { background: transparent; border: 1px solid var(--steel); color: var(--steel); }
.badge-on { background: var(--navy-deep); color: var(--paper); }

.result-filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-1);
  padding-block: var(--s-6) var(--s-4);
}
.result-filters .badge { background: transparent; border: 1px solid var(--rule, var(--shell)); color: var(--navy-mid); }
.result-filters .badge-on { background: var(--navy-deep); border-color: var(--navy-deep); color: var(--paper); }

.result-list { list-style: none; margin: 0; padding: 0; }
.result-list > li { padding: var(--s-4) 0; border-bottom: 1px solid var(--shell); }
.result-list a { text-decoration: none; display: block; }
.result-amount {
  display: block;
  font-family: var(--display);
  font-weight: 700;
  font-size: var(--size-h3);
  color: var(--navy-deep);
}
/* No `color` here. It used to say `color: var(--body)`, which is the FONT
   token -- `color: Montserrat, Helvetica, ...` is invalid, so the declaration
   was dropped and the title has always inherited. Inheriting is what it wants;
   this only stops the line claiming otherwise. */
.result-title { display: block; }
.result-list a:hover .result-amount { color: var(--rust); }
.result-tags { margin: var(--s-1) 0 0; display: flex; gap: var(--s-1); flex-wrap: wrap; }

.pagination {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding-block: var(--s-6);
  font-size: var(--size-small);
}
.pagination-status { color: var(--navy-mid); }

/* --- Rebuilt page: insights ------------------------------------------ */

.insight-body p { max-width: 68ch; }
/* No heading margins here. The article body's vertical rhythm is carried by
   `> br + *` further down, and a margin-top set at this end escapes that rule
   and stacks on top of it. */
.insight-date { display: block; font-size: var(--size-small); color: var(--navy-mid); }
.result-list a:hover .result-title { color: var(--rust); }

/* --- Rebuilt page: insight article ----------------------------------- */
/* Layout measured from captures/screenshots: navy title band, lead image at
   container width, byline and date below the image, then a two-column body
   with the enquiry panel on the right. */

/* Measured on the live article at 1440: the band runs 279 to 567, so 288 tall
 * with 52px of white above it -- it does not start at the header's foot. The
 * back link sits 20px into it and the title 62px, and the band closes 8px
 * under the title. */
.insight-head {
  background: var(--navy-deep);
  color: var(--paper);
  margin-top: 52px;
  padding-block: 20px 8px;
  text-align: center;
}
.insight-head h1 {
  color: var(--paper);
  font-family: var(--body);
  font-weight: 400;
  /* 56px, not 40: the source sets these titles at 56 and the h1 now carries
   * the "| Hourigan Kluger & Quinn" suffix, so it wraps to the 218px the live
   * one measures. No max-width either -- the source lets it fill the 980
   * container rather than holding it to 24 characters. */
  font-size: clamp(26px, 3.9vw, 56px);
  /* 1.3, which is the 72.8px line box the live title computes. At the
   * inherited 1.4 the three lines ran the band 20px past the source's 288. */
  line-height: 1.3;
  margin: 20px auto 0;
}
/* 16px at 1.4, the 22.4px line box the source computes for "All Articles" --
 * not the small step at the body's inherited 1.8, which read 14px/25.2. */
.insight-back {
  margin: 0;
  text-align: left;
  font-size: var(--size-body);
  line-height: 1.4;
  font-weight: 700;
}
.insight-back a { color: var(--paper); text-decoration: none; }
/* The source indents this 13px past the h1 below it, which starts flush at the
 * container's own edge. */
.insight-back { padding-left: 13px; }

/* 45px under the title band. The band's own bottom is at 569 here and the
 * source opens its hero at 614. */
.insight-hero { padding-top: 45px; }
/* 980x560 on the source. Left at auto the webp's own aspect gave 654 and put
 * everything below it 94px low. */
.insight-hero img { width: 100%; height: 560px; object-fit: cover; display: block; }

/* 14px/400 in an 18px line box, which is what the source's byline and date
 * both compute, and inset to the BODY COLUMN -- the source sets this block at
 * x=244 and 614 wide, not across the whole container. */
.insight-meta {
  /* 49px under the hero, which is where the source puts the byline. */
  padding-top: 49px;
  padding-inline: 14px 38px;
  font-size: 14px;
  /* 18, not the 22.4 the source's span computes. That 22.4 is the inline box's
   * line-height and this is the block, so adopting it would push the date 4px
   * below the source's 1252 -- rule 1, type on the span and geometry on the
   * block. Both lines land on the source's own y as it stands. */
  line-height: 18px;
  /* BLACK, which is what the source paints. It was --navy-mid, and that is
   * visible: rgb(50,65,88) against rgb(0,0,0) on both the byline and the date. */
  color: #000;
}
.insight-meta p { margin: 0; max-width: 607px; }
.insight-meta .byline { font-weight: 400; }
/* .insight-date carries its own color further up the file and would otherwise
 * beat the inherited one -- it is matched directly, so inheritance never
 * reaches it. */
.insight-meta .insight-date { color: inherit; }
/* 11px under the byline. Both lines sat flush, and the 16px that error hid
 * came back out of the lead's top margin below -- the two canceled at the
 * body and left the byline block the wrong shape at the right total height. */
.insight-meta .insight-date { margin-top: 11px; }
/* 24px at 1.4 in black: the lead is the source's own lead, not a caption.
 * Scoped under .insight-body so it outranks that block's own p rule, which
 * otherwise held the 24px text in a 24px line box. */
.insight-body .insight-lead {
  /* 16px under the layout's own 8, for the source's 24 between date and lead. */
  margin-top: 16px !important;
  /* The source separates the lead from the body by ~60px whatever follows it:
   * 61 on limited-tort-full-tort, whose body opens with a paragraph, and 59 on
   * teen-driver-accidents, whose body opens with a heading. The body's own
   * blocks all sit on zero margin, so this gap has to live here. */
  margin-bottom: 60px;
  font-size: 24px;
  line-height: 1.4;
  color: #000;
}

.insight-layout {
  display: grid;
  /* 273px, the source's sidebar width, set on the COLUMN only. At 250 the
   * longest label -- "Employment & Labor Law" -- wrapped inside a fixed 40px
   * row and overlapped the row beneath it.
   *
   * Do NOT reach for the source's insets with padding-inline here: it belongs
   * to .container's centering, and overriding it widened the whole block to
   * the viewport and ran the page 112px over. The source insets its content 14
   * left and 38 right inside a 230-1210 container, so our sidebar ends flush
   * at 1210 where the source's ends at 1172. That is the remaining difference
   * and it needs an inner wrapper, not padding. */
  grid-template-columns: 1fr 273px;
  gap: var(--s-6);
  align-items: start;
  /* The source's own insets, applied on the wrapped grid rather than on
   * .container: body column at x=244 and content ending at 1172, inside a
   * container spanning 230 to 1210. */
  padding-inline: 14px 38px;
  /* No bottom padding: the space under the body column belongs to the pager
   * below, which the source sets at 23px above and 17px below. The 8 above is
   * what is left of the source's 24 once the byline block carries its own
   * correct height -- the date's 11px and the hero's 5 used to be missing from
   * there and paid for out of this. */
  padding-block: 8px 0;
}
/* 16px on a 24px line box. The gaps between blocks are NOT a property of the
 * blocks: every one of them is a top-level <br> in the stored HTML, and the
 * source paints each as a 24px line box while leaving every <p>, <strong> and
 * <a> on zero margin. Putting the gap on the paragraph instead spaced the
 * "Related Articles" bullets -- three consecutive <p>s with no <br> between
 * them -- at 48px against the source's 24, which carried +25px into everything
 * below and left the page 37px tall. The <br> stays hidden and the block after
 * it carries its height, so a run with no <br> closes up on its own. */
/* The source renders every body paragraph at `white-space: break-spaces` with
 * a 40px tab stop, and uses real tabs to indent its bullet runs -- 201 of them
 * across 69 articles. Without this the tab collapses and the run starts 71px
 * left of the source's. */
.insight-body :is(p, h2, h3, h4, h5, li) { white-space: break-spaces; tab-size: 40px; }
/* A bullet run is a <p> holding tab, bullet, tab, text -- not a list item --
 * so the tab indents the FIRST line only and a wrapped line returns flush
 * left, under the bullet instead of under the text. That is what the source
 * does and it is a DELIBERATE DEPARTURE to fix it; see docs/PARITY-AUDIT.md
 * under "Deliberate departures from the source".
 *
 * 80px because the two tabs land the text on the second 40px stop, on both
 * builds: measured on the live phone build of /what-you-need-to-know/
 * personal-injury-insights/burn-injuries, "Workers' compensation benefits"
 * runs tab x=20 w40, bullet x=60, tab x=64.1 w35.9, text x=100 against a
 * paragraph edge of 20 -- +80 -- and the wrapped "benefits" at x=20. Desktop
 * at 1440 is the same arithmetic: edge 244, text 324, again +80.
 *
 * The padding/negative-indent pair leaves the first line exactly where it was
 * -- the negative indent gives line one its 80px back, so the tab stops and
 * the wrap point are unchanged -- and moves only the lines after it. Verified
 * in Chromium and Firefox; the wrapped word moves 20 -> 100 in both and line
 * one measures identically. `.insight-bullet` is stamped by
 * pages/management/commands/extract_insights.py. */
.insight-body p.insight-bullet { padding-left: 80px; text-indent: -80px; }
.insight-body p { max-width: none; line-height: 24px; }
.insight-body > br { display: none; }
.insight-body > :is(p, h2, h3, h4, h5, ul, ol) { margin: 0; }
/* EACH <br> is one 24px line box, and a list takes the gap like any other
 * block. Both were missing: the rule named five tags and not ul/ol, so a list
 * closed straight up against the paragraph above it, and it counted a run of
 * <br>s as one gap. /fireworks-guide puts two before every h4 and one before
 * every list -- 10 and 7 of them -- which came to 408px of the 462 that page
 * was short. 104 runs of two exist across the library against 1,199 of one. */
.insight-body > br + :is(p, h2, h3, h4, h5, ul, ol) { margin-top: 24px; }
.insight-body > br + br + :is(p, h2, h3, h4, h5, ul, ol) { margin-top: 48px; }

/* The same spacer, authored the other way. 20 of the 170 articles close each
 * block with a <br> INSIDE it -- <p>text<br></p> -- instead of putting one
 * between blocks, and the two shapes are mixed within a single article. A
 * trailing <br> paints no line box on its own, so those articles lost every
 * gap and ran up to 300px short.
 *
 * The height is the PARENT's line box, not a flat 24: the source measures the
 * h2 on /passenger-injury-claims at 126px for two lines of 42, and its
 * paragraphs at 96 for three lines of 24.
 *
 * Carried by the parent's padding rather than by the <br> itself. `display`
 * and `height` on a <br> are ignored -- it is a forced line break, not a box,
 * and setting both leaves the parent exactly as tall as before.
 *
 * :has() carries real layout here, so it is a browser-support question rather
 * than a convenience: Firefox has shipped it since 121 (December 2023),
 * Chrome since 105 and Safari since 15.4. Without it these 20 articles lose
 * every gap in that browser alone, which is the failure mode the FAQ panel's
 * ::details-content animation had. */
/* Lists, measured on /daycare-abuse-guide: the source runs the <ol> flush in
 * the 616px column at zero margin and no padding, indents each <li> by 24 to
 * 268, and sets the item on the body's own 24px line box. Left to the browser
 * defaults -- 16px margins, a 40px pad and the inherited 28.8px line -- the
 * five lists on that page came to 190px more than the source's. */
.insight-body :is(ul, ol) { margin: 0; padding-left: 0; }
.insight-body li { margin-left: 24px; line-height: 24px; }
/* Wix wraps each item's text in a <p>, and the margin rule above this block
 * reaches direct children of .insight-body only, so those kept the browser's
 * 1em and set the items 88px apart against the source's 72. */
.insight-body li p { margin: 0; }

.insight-body > p:has(> br:last-child)  { padding-bottom: 24px; }
.insight-body > h2:has(> br:last-child) { padding-bottom: 42px; }
.insight-body > h3:has(> br:last-child) { padding-bottom: 36px; }
.insight-body > h4:has(> br:last-child) { padding-bottom: 30px; }
.insight-body > h5:has(> br:last-child) { padding-bottom: 27px; }

/* Body headings. Wix picks the level per article rather than per depth -- one
 * article's section heading is an <h2>, the next one's an <h3> -- so the size
 * follows the TAG and not the position. Each measured on the live article:
 *
 *     h2  28/42     h3  24/36     h4  20/30     h5  18/27
 *
 * all Montserrat 700. The source writes them as <hN><strong><u>…</u></strong>
 * and then paints neither the 900 weight nor the underline that markup implies,
 * so both are canceled here; "Click here" inside a <p> keeps its underline
 * because these selectors are scoped to the heading. */
.insight-body > :is(h2, h3, h4, h5) {
  font-family: inherit;
  font-weight: 700;
  color: inherit;
}
.insight-body > h2 { font-size: 28px; line-height: 42px; }
.insight-body > h3 { font-size: 24px; line-height: 36px; }
.insight-body > h4 { font-size: 20px; line-height: 30px; }
.insight-body > h5 { font-size: 18px; line-height: 27px; }
.insight-body > :is(h2, h3, h4, h5) :is(strong, b) { font-weight: inherit; }
.insight-body > :is(h2, h3, h4, h5) u { text-decoration: none; }
.insight-body > :is(h2, h3, h4, h5) a { color: inherit; text-decoration: none; }
.insight-inline { width: 100%; height: auto; margin-block: var(--s-4); }

/* 16px body and a 24px heading, both measured against the live panel, which
 * read 14 and 18 here. */
/* The same grey and radius as the practice panel below it -- both sample
 * rgb(224, 226, 232) on the source, where this one was a bluer #E8EDF3. */
/* The sidebar starts 11px below the body column on the source, not level with
 * it: its lead runs from 1294 and the enquiry panel from 1305. */
.insight-aside { padding-top: 14px; }

.need-help {
  background: rgb(224 226 232);
  border-radius: 6px;
  /* The source's own insets, which add to its 201px panel: 13 above the
   * heading, 11.5 each side and 25 under the button. --s-4 all round gave 24
   * and a 225px column. The half pixel matters: at 12 the copy runs 249 wide
   * against the source's 250 and "Injury" wraps to a third line that the
   * source keeps on the second. */
  padding: 13px 11.5px 25px;
  font-size: var(--size-body);
  /* 20.8px, which is what the live panel's copy computes; the body's 1.8 gave
   * 28.8 and ran the panel tall. */
  line-height: 20.8px;
}
.need-help h2 {
  font-family: var(--body);
  font-size: 24px;
  /* --navy-band, rgb(38,48,89), and a 29px line box: the live heading measures
   * both, where ours read --navy-deep in a 34px box. Centered, as the source
   * centers it over left-aligned copy. */
  line-height: 29px;
  text-align: center;
  color: var(--navy-band);
  margin-bottom: 15px;
}
.need-help p { margin-bottom: 17px; }
/* Navy, not the site's gold .btn: the source paints this one 207x40 in
 * rgb(11, 47, 91) with a 6px radius and a 16px/700 white label at 1.6px of
 * tracking. Ours was the shared gold button at 14px/600 in navy INK, which is
 * the opposite arrangement. */
.need-help .btn {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 40px;
  margin: 0;
  padding: 0;
  background: #0B2F5B;
  border-radius: 6px;
  color: var(--paper);
  font-size: var(--size-body);
  font-weight: 700;
  letter-spacing: 1.6px;
  /* Normal, not the body's 1.8: inherited it put the label in a 28.8px box
   * inside a 40px button. */
  line-height: normal;
  /* Sentence case: the shared .btn uppercases its label and the source does
   * not -- it reads "Get in Touch", not "GET IN TOUCH". */
  text-transform: none;
  /* 207 wide and centered in the panel, which insets it 9px on the source. */
  width: 207px;
  margin-inline: auto;
  text-align: center;
}
.need-help .btn:hover { background: var(--navy); }

@media (max-width: 800px) {
  .insight-layout { grid-template-columns: 1fr; }
}


/* --- Rebuilt page: insight index -------------------------------------
 *
 * /what-you-need-to-know and its Spanish twin. Type sizes are the inline
 * values the captured page declares, read with
 * `tools/wix_outline.py captures/html/what-you-need-to-know.html`; the source
 * overrides its own theme fonts inline on every run, so the --font_N
 * variables do not describe what renders.
 *
 * This replaced a three-column row list — title, summary, thumbnail — that
 * bore no relation to the source and rendered all 82 articles at once.
 * docs/PARITY-AUDIT.md item 2 measured that at 13,716px taller than the
 * capture. */

/* The banner is 293px here, not the 346 the practice pages use, and its title
 * is a flat 56px rather than the 66px clamp — measured on the live page at
 * 1440, where the band runs y=227 to y=520. */
/* 87px in: the source starts "What You Need To Know" at y=314, 87 below the
 * band's visible top at 227 -- not the 72 the two indexes and /contact use. */
.practice-head.hero-insights { min-height: 293px; padding-block: 87px 0; }

/* The category landings, a SEPARATE name from the index above on purpose: the
 * two bands are different heights, and the last time one variant covered two
 * page types the later rule won and made every FAQ index 139px too tall.
 *
 * 333px, and it does not grow with the title. Both landings measure a 333px
 * band with the title starting at y=314, though "Business & Commercial Law
 * Insights" wraps to 157px against Personal Injury's 78 -- so this is the
 * source's own fixed height, not a number absorbing something else. */
.practice-head.hero-insights-landing {
  min-height: 333px;
  padding-block: 87px 0;
  /* A sixth navy, and none of the five tokens: the landing band computes
   * rgb(1, 29, 75) on the source where every other page head is --navy. That
   * token is right and stays -- /attorney-referrals, /contact and /faqs each
   * sample identically to the live band -- so this is the landing being
   * different, not the palette being wrong. Both landings measure it.
   *
   * It shows here because these are the only heads with no photograph over
   * them; elsewhere the picture and its wash cover the fill. */
  background: #011D4B;
}

/* 25px under the title on both landings, measured from each title's own foot:
 * 392 -> 417 on one, 471 -> 496 on the other. The index's subtitle sits tight
 * to its title and is not touched here. */
.practice-head.hero-insights-landing .hero-sub { margin-top: 25px; }
/* 16px on a 28.8px line, not the shared 14: measured on the live index band,
 * where the shared size ran it 6px short. */
.practice-head.hero-insights .hero-sub { font-size: 16px; line-height: 28.8px; }

/* Montserrat 56/400, not the Libre Baskerville 700 the other banners use.
 * This page sets its headings in the body face throughout — measured on the
 * live page, where every heading here computes to montserrat. */
/* The source embosses the title and its subtitle on this band -- a white
 * highlight down-right and a black one up-left, both at 60% -- which is how
 * white type stays legible over the photograph with no wash behind it. It is
 * a text-shadow, so no measurement here that named its properties by hand
 * could see it. */
.practice-head.hero-insights h1,
.practice-head.hero-insights h1 + .hero-sub,
.practice-head.hero-insights .hero-sub {
  text-shadow: 1px 1px 1px rgb(255 255 255 / 60%), -1px -1px 1px rgb(0 0 0 / 60%);
}
.practice-head.hero-insights h1,
.practice-head.hero-insights-landing h1 {
  font-family: var(--body);
  /* 5.72vw is 56 at 980, the tablet canvas; at 3.9vw this resolved to 38.22
   * there and the maximum was unreachable, so the title rendered 18px small.
   * Measured on /what-you-need-to-know against the source's 56px/78.4. */
  font-size: clamp(32px, 5.72vw, 56px);
  font-weight: 400;
  /* 56 at 1.4 is the 78.4px line box the live page computes. Inherited, the
   * shared 89.6px put this title in a 90px box. */
  line-height: 1.4;
}

/* 22px centered in a 792px column, narrower than the 980 container. At 24/1.6
 * in 800 it ran to three lines against the source's two. */
.insights-intro {
  font-size: 22px;
  line-height: 30.8px;
  text-align: center;
  max-width: 792px;
  margin: var(--s-6) auto var(--s-8);
}

/* Fixed 437px columns rather than fractions of the row: the source lays out
 * one card of that width and reserves a second slot beside it, so a fraction
 * would stretch the single visible card across the whole container. */
/* Inset 40px from the container, where the article rows below sit at 26: the
 * card starts at x=263 on the live page against the container's 223. */
.insight-sections {
  display: grid;
  grid-template-columns: repeat(auto-fit, 437px);
  gap: var(--s-4);
  /* 16px between the two 437px cards on the source -- they sit at x=270 and
   * x=723. The 24px the shared gap gives put the second card, and so its
   * icon, 8px right of the first card's. Column only; the phone stacks them
   * and keeps the row gap. */
  column-gap: 16px;
  list-style: none;
  padding: 0;
  margin: 0 0 var(--s-6) var(--s-6);
}

/* Icon left at 126px, text right. Navy card with white type and a 10px radius.
 *
 * Re-measured against the live card 2026-08-28, which is 437x209 and NOT
 * --navy-deep: it computes rgb(1, 29, 75), the same sixth navy the category
 * landing's band uses. The card was 34px too tall in a color off by
 * (3, -10, 17), with square corners against the source's 10px. */
.insight-section-card {
  display: grid;
  /* No gap: the copy starts at x=398 on the live card, which is exactly the
   * icon's right edge. */
  grid-template-columns: 126px 1fr;
  align-items: start;
  min-height: 209px;
  /* 11 on the right, not 14: the source runs the blurb 291px wide from x=135
   * in a 437 card, which leaves 11. Each side is 1px short of that, because
   * the 1px border below sits inside the box and would otherwise push every
   * child a pixel down and to the right. */
  padding: 13px 10px 13px 8px;
  background: #011D4B;
  border-radius: 10px;
  /* A 1px white edge and a soft drop shadow, both of which the source paints
   * and neither of which any measurement here had looked for: Wix names them
   * --brd/--brw and --shd, and the card computes
   * `box-shadow: rgba(0,0,0,.6) 0 1px 4px`. Found by diffing EVERY computed
   * property against the live card rather than a hand-written list of the
   * ones worth checking -- the list had no entry for a shadow, so no run
   * could ever have reported one. */
  border: 1px solid var(--paper);
  box-shadow: 0 1px 4px rgb(0 0 0 / 60%);
  color: var(--paper);
}

/* 126x145 on the source, and lightened: it paints the same dark artwork we
 * ship through a filter that composites 46% white over it. The filter lives in
 * insights_list.html, copied from the live page. Without it the icon reads
 * near-black on the navy card where the source's is light grey. */
.insight-section-icon {
  width: 126px;
  height: auto;
  display: block;
  object-fit: cover;
  filter: url(#icon-lighten);
}

/* The source crops both icons before painting them and we ship the uncropped
 * originals, so their intrinsic ratios are not the ratios the source draws.
 * Its two URLs carry the crop: the person is fill/w_126,h_145 and the
 * briefcase crop/x_29,y_0,w_552,h_539 then fill/w_126,h_123, both al_c --
 * a centered cover, which is object-fit above. Left to their own ratios the
 * person drew 17px tall and the briefcase 12px short, in opposite directions,
 * which is why the two cards' icons did not line up with each other. The
 * ratios hold at every width the cards are painted at: 126x145 and 126x123 on
 * desktop, 90x104 and 90x88 on the phone. */
.insight-section-card--personal-injury .insight-section-icon {
  aspect-ratio: 126 / 145;
}
.insight-section-card--business-and-commercial-law .insight-section-icon {
  aspect-ratio: 126 / 123;
}

/* 6px, which puts the title's first line on the source's y=20. */
.insight-section-body { padding-top: 6px; }

/* 24px, and a paragraph rather than a heading on the source. Kept as a
 * paragraph: the card's own link names the section, and promoting it would
 * put two competing headings above the article list. */
.insight-section-name {
  font-family: var(--body);
  font-size: 24px;
  /* 33.6px, which is 24 x 1.4 and what the live card computes. 1.3 held it in
   * a 31.2px line. */
  line-height: 33.6px;
  font-weight: 400;
  /* The source gives each card's text column its own width -- Wix places them
   * absolutely -- and both titles land on two lines as a result. One shared
   * measure cannot reproduce that, so each card states its own below; this is
   * the narrower of the two, so a category with no rule still wraps. */
  max-width: 229px;
  /* 11px, for the source's 78 between the title's top and the blurb's. */
  margin: 0 0 11px;
}

/* Measured on the live cards at 1440: the text column is 229px on Personal
 * Injury and 283px on Business & Commercial Law, which wraps each title to two
 * lines and leaves both "View Articles" buttons at y=805. A single 180px
 * measure fit the first title and pushed the second onto a third line, taking
 * its button 34px below its neighbor's. */
.insight-section-card--personal-injury .insight-section-name { max-width: 229px; }
.insight-section-card--business-and-commercial-law .insight-section-name { max-width: 283px; }

.insight-section-blurb {
  font-size: 14px;
  /* 19.6px, 14 x 1.4, measured on the live card; 1.6 ran it at 22.4. The
   * source holds it to 291px, two lines. */
  line-height: 19.6px;
  max-width: 291px;
  /* 8px, for the source's 47 between the blurb's top and the button's. */
  margin: 0 0 8px;
}

/* The "View Articles" button: 205x40, outlined in white on the navy card,
 * where .btn is solid gold. */
.btn-outline {
  display: inline-block;
  width: 205px;
  /* 40px tall on a line box rather than padding: the source's button is
   * 205x40 with a 10px radius, and var(--s-2) top and bottom made it 51. */
  height: 40px;
  line-height: 38px;
  padding: 0;
  border: 1px solid currentColor;
  border-radius: 10px;
  color: var(--paper);
  font-size: var(--size-small);
  letter-spacing: .06em;
  text-align: center;
  text-decoration: none;
}
.btn-outline:hover { background: rgb(255 255 255 / 12%); }

/* "Latest Legal Insights", 22px centered — smaller than the 24px intro above
 * it, which is why neither is var(--size-h2). */
.insights-latest {
  font-family: var(--body);
  font-size: 22px;
  font-weight: 400;
  text-align: center;
  margin: 0 0 var(--s-4);
}

.insight-cards { list-style: none; padding: 0; margin: 0; }

/* Title left, section and summary center, thumbnail right. Column widths
 * measured on the live page at 1440: 251, 345 and 265 inside a 980 container,
 * so the two flexible columns sit in a 1 : 1.375 ratio. */
.insight-card {
  display: grid;
  grid-template-columns: 1fr 1.375fr 265px;
  gap: 33px;
  align-items: start;
  position: relative;
  box-sizing: border-box;
  /* Row height measured at 334px on three paired rows (Side Impact
   * Collisions, Teen Driver Accidents, Hit and Run Accidents) at 1440px,
   * identical across all three despite summary lengths of 70/96/96px, so
   * the source pins the row rather than letting content flow it. */
  height: 334px;
  /* 26 each side, so the three columns land on 251 / 345 / 265 inside the
   * 980 container and the row starts where the live one does. 48px top
   * inset is the title's dy from row top, measured on all three rows. */
  padding: 48px 26px 0;
  border-bottom: 1px solid rgb(4 19 58 / 12%);
}

/* Read More's own dy (243px, fixed) is measured relative to this box's
 * top, which sits at the same 48px inset as the title. */
.insight-card-body { position: relative; }

/* The row is the TITLE's height plus a constant 171 -- 48px of inset above it
 * and 123 below -- which is 334, 363 and 395 at 1440 for two-, three- and
 * four-line titles. The `height: 334px` above was read off three rows that
 * happen to share a two-line title and differ only in summary, the one
 * measurement the row ignores.
 *
 * The 48px inset is the title's alone. The source does not apply it to the
 * middle column: its category text sits at 15 from the row's top and its
 * summary at 81, against our 48 and 98. That difference is why this column
 * used to reach past the title and set the row height itself.
 *
 * Confined to a min-width query so none of it reaches the phone build, whose
 * rules live under html[data-device="phone"] and carry lower specificity. */
@media (min-width: 801px) {
  .insights:not(.insights-landing) .insight-card {
    height: auto;
    /* The source's shortest row, kept as a floor so a short article does not
     * collapse the rhythm of the list. */
    min-height: 334px;
    padding-bottom: 40px;
  }
  /* -36 puts the column's first line at the source's 15 rather than 48, which
   * is the title's inset alone. */
  .insights:not(.insights-landing) .insight-card-body {
    margin-top: -36px;
    /* The column's own inset. check_metrics reported this as a dx of -6 on
     * every one of the column's three runs, on every row of the page. */
    padding-left: 6px;
  }
  .insights:not(.insights-landing) .insight-card-summary { width: 333px; margin-top: 43px; }
  /* Follows the summary at one constant gap rather than being anchored near
   * the row's foot. Anchoring it there is what makes the source's spacing
   * ragged: the row is sized by the title and the summary's length varies
   * independently of it, so the white between them runs 56px on one article
   * and 130 on another. See docs/PARITY-AUDIT.md. */
  .insights:not(.insights-landing) .insight-card-more {
    position: static;
    margin-top: 24px;
  }
}

/* 26px, between --size-h3 (24) and --size-h2 (36), so neither token fits. */
.insight-card-title {
  font-family: var(--body);
  font-size: 26px;
  /* `normal`, as the source leaves it. 1.3 gave a 33.8px line and ran each
   * card's title 7px tall over ten cards. */
  line-height: normal;
  font-weight: 400;
  margin: 0;
}
.insight-card-title a { color: var(--ink); text-decoration: none; }
.insight-card-title a:hover { text-decoration: underline; }

.insight-card-section,
.insight-card-summary {
  font-size: var(--size-body);
  line-height: 1.6;
  margin: 0 0 var(--s-4);
}

/* 243px row-top dy is constant across the three paired rows regardless of
 * summary length, so it is pinned to the row rather than flowing after the
 * summary; 195px = 243 - 48 (the row's top inset, see .insight-card-body). */
.insight-card-more { position: absolute; top: 195px; left: 0; margin: 0; }
.insight-card-more a {
  /* Avenir on the source, so Nunito Sans 300 -- the stand-in measured for the
   * nav, where Montserrat ran 27% more ink and 13.7% wide. Here Montserrat put
   * "Read More" at 76px against the source's 69. Avenir itself is Monotype's
   * and licensed to Wix, not to us; docs/PARITY-AUDIT.md 3b tracks it. */
  font-family: 'Nunito Sans', Helvetica, Arial, sans-serif;
  font-weight: 300;
  font-size: var(--size-small);
  color: var(--rust);
  text-decoration: none;
  /* 14px x 1.4 = 19.6px, the source's computed line-height for this link;
   * it does not inherit the body's 1.8. */
  line-height: 1.4;
}
.insight-card-more a:hover { text-decoration: underline; }

/* Source always paints a 265x137 crop regardless of the source image's
 * native aspect ratio. */
.insight-card-thumb img { width: 100%; height: 137px; object-fit: cover; display: block; }

/* The same card, 54px shorter on a category landing than on the index. Measured
 * on four landing cards, all identical and all differing from the index card
 * for the same article: the row is 280 against 334, "Read More" sits at 189
 * from the row top against 243, and the thumbnail starts at 21 against 46.
 * Only the title's own 48px inset is common to both.
 *
 * The thumbnail's -27px is that 21 against the 48 the text column is inset by;
 * it rides above the text rather than aligning with it.
 *
 * A floor, not a pin. 280 is the source's row and a short card still lands on
 * it, but the row leaves only 232px under its 48px inset, and the two
 * "Comprehensive Guide: Recognizing..." titles measure 320 and 256 -- so they
 * ran 34px and 88px past their own card into the one below. That is the
 * "Overlapping Text" a client reviewer reported on
 * /what-you-need-to-know/business-and-commercial-law. `height: auto` as well as
 * the floor, because the base rule above pins 334 and min-height alone leaves
 * it in force; the index needs both for the same reason. */
.insights-landing .insight-card { height: auto; min-height: 280px; }
.insights-landing .insight-card-more { top: 141px; }
.insights-landing .insight-card-thumb { margin-top: -27px; }

@media (max-width: 800px) {
  /* Released with the index's, for the same reason: a fixed row clips a
   * stacked card. */
  .insights-landing .insight-card { height: auto; }
  .insights-landing .insight-card-more { position: static; }
  .insights-landing .insight-card-thumb { margin-top: 0; }
}

@media (max-width: 800px) {
  /* The 40px inset is a desktop alignment and does not survive a narrow
   * column: keeping it pushed the card 28px past the viewport at 390. */
  .insight-sections { grid-template-columns: 1fr; margin-left: 0; }
  .insights-intro { font-size: 18px; }
  /* The fixed 334px row height and 48px top inset are desktop-only
   * measurements (this pass did not measure the stacked mobile layout), so
   * a narrow column reverts to flowing content instead of clipping it. */
  .insight-card {
    grid-template-columns: 1fr;
    gap: var(--s-3);
    padding-inline: 0;
    height: auto;
    padding-top: var(--s-5);
  }
  .insight-card-title { font-size: 22px; }
  .insight-card-thumb { max-width: 320px; }
  .insight-card-more { position: static; margin-top: var(--s-3); }
}

@media (max-width: 440px) {
  /* The icon and the copy cannot both hold their desktop widths here — the
   * 126px column plus the button's 205px is wider than the card. */
  .insight-section-card { grid-template-columns: 84px 1fr; }
  .insight-section-icon { width: 84px; }
  .btn-outline { width: 100%; max-width: 205px; }
}

/* Support staff listing. No photographs on the source page — name, role and
 * contact details only. */

/* --- Rebuilt page: one /in-the-news article ---------------------------
 * Measured off the live champion-of-justice article at 1440px; the table is
 * in notes/wip/news-migration.md. A 680px column, not the site's 980, and no
 * banner — this page used to open with a 254px navy header the source does
 * not have. */
/* The section is a fixed 2228px on the source — 227 to the footer at 2455 —
 * and both articles are therefore exactly 4349px tall despite differing in
 * length by 31px. Wix sizes it once and lets the copy sit at the top, so a
 * min-height reproduces it where flow layout cannot. */
.news-article {
  min-height: 2228px;
  box-sizing: border-box;
  padding-block: 34px 51px;                   /* 227 -> the back link's text at 266 */
  /* A column, so the pager can sit at the foot of the fixed height rather
     than directly under a body whose length varies. */
  display: flex;
  flex-direction: column;
}
/* The padding is added ON TOP of the 680, the same way .container adds its own
 * on top of --container. Setting max-width to a bare 680 leaves 632px of
 * content and rewraps every paragraph in the article. */
.news-article-col {
  max-width: calc(680px + var(--s-4) * 2);
  margin: 0 auto;
  padding-inline: var(--s-4);
  width: 100%;
  flex: 1;
  display: flex;
  flex-direction: column;
}

/* Nunito Sans 300, the stand-in for the source's avenir-lt-w01_35-light, same
 * as the header nav and the listing's "Read Article". In the body font this
 * label measured 4px wide. */
.news-back { margin: 0 0 20px; }               /* headline at 311 */
.news-back a,
.news-pager a,
.news-pager span {
  font-family: 'Nunito Sans', Helvetica, Arial, sans-serif;
  font-weight: 300;
  font-size: var(--size-body);
  text-decoration: none;
}
.news-back a { color: var(--ink); }
.news-back a:hover { text-decoration: underline; }

/* Previous and Next at the two ends of the 680px column, on the last line of
 * the fixed-height section: their text sits at y=2382 against a section
 * running 227 to 2455. The unavailable end is rgb(199,199,199) on the source
 * and is not a link. */
.news-pager {
  display: flex;
  justify-content: space-between;
  margin-top: auto;                            /* pinned to the foot, not to the copy */
  /* 22px, which is what the source's line box measures. The block is bottom
     pinned, so its height decides where the words land. */
  line-height: 1.375;
}
.news-pager a { color: var(--ink); }
.news-pager a:hover { text-decoration: underline; }
.news-pager span { color: rgb(199 199 199); }

/* 46px at 1.4, which the source computes as a 64.4px line box. Read the
 * heading's OWN box for this, not the <span> Wix nests inside it: the span
 * measures 121px because an inline box is content height, while the heading
 * is 129. Sizing against the span gave 1.32 and set the two lines of a
 * wrapped headline 4px too close. */
.news-article h1 {
  font-family: var(--body);
  font-size: clamp(30px, 3.2vw, 46px);
  font-weight: 400;
  line-height: 1.4;
  /* Negative, because the source's standfirst starts before the headline's box
   * ends -- Wix positions the two independently and lets them overlap. The
   * fraction is not fussiness: the headline is 2 x 64.4 = 128.8 tall and the
   * standfirst sits 118 below its top, so a round -11 leaves everything under
   * it a pixel adrift. */
  margin: 0 0 -10.8px;
}

.news-standfirst-lead {
  font-size: 20px;
  line-height: 1.6;
  margin: 0 0 5px;                    /* standfirst ends 493, image at 498 */
}

/* 680x382 on the source, cropped from the center of the original — the same
 * `al_c` fill the listing thumbnails use. */
.news-lead {
  width: 100%;
  aspect-ratio: 680 / 382;
  object-fit: cover;
  display: block;
  margin: 0 0 46px;                   /* image ends 880, body at 926 */
  background: var(--shell);
}

/* `normal`, not the 1.8 body default: the source's paragraphs paint a 19px
 * line box at 16px, and its empty paragraphs are 19px tall for the same
 * reason. */
.news-article-body { line-height: normal; }
.news-article-body p { margin: 0; }
.news-article-body h2,
.news-article-body h3,
.news-article-body h4 {
  font-family: var(--body);
  font-size: 24px;
  font-weight: 700;
  /* 29px flat, which is what the source paints. As a ratio this is 1.2, and
   * 24 x 1.2 = 28.8 -- a fifth of a pixel that accumulates down the article
   * and leaves every block below the second subheading 1px adrift. */
  line-height: 29px;
  margin: 0;
}
/* The source wraps each subheading's text in a bold span, which arrives here
 * as <strong>. Left alone it computes to 900 against an already-700 heading,
 * because `bolder` is relative. */
.news-article-body h2 strong,
.news-article-body h3 strong,
.news-article-body h4 strong { font-weight: inherit; }
/* One blank line, which is what the source puts here. Irregular by content —
 * some subheadings have one above them and some do not — so it is carried on
 * the element rather than applied to every element of a kind.
 *
 * The height depends on which tag was left empty: a blank paragraph paints a
 * 19px line box and a blank heading a 29px one. The champion-of-justice
 * article has one of each. */
.news-article-body .after-break { margin-top: 19px; }
.news-article-body .after-break-heading { margin-top: 29px; }

/* --- Rebuilt page: /in-the-news ---------------------------------------
 * The press-coverage listing. Measured off the live page at 1440px; the full
 * table is in notes/wip/news-migration.md. Two columns of numbers matter: the
 * heading sits in a 780px column and the cards in a 754px one, which is why
 * there are two containers here rather than the site's usual 980.
 *
 * This page has no banner. It used to render partials/_page_hero.html, which
 * put a 346px navy band and a 66px title on a page whose source has neither. */
.news-index { padding-block: 49px 22px; }   /* 227->276 at the top, ->1120 at the foot */

/* Montserrat, not the display face. Every other page title on this site is
 * Libre Baskerville; the source sets this one in the body font at 400. */
.news-index h1 {
  max-width: 780px;
  margin: 0 auto;
  font-family: var(--body);
  /* 5.72vw is 56 at 980, the tablet canvas. At 3.9vw the middle term resolved
   * to 38.22 there, so the 56px maximum was unreachable on any width that
   * build ships and this title rendered 18px small and 24 short. Invisible at
   * 1440, where 3.9vw clears 56 and the clamp holds. */
  font-size: clamp(32px, 5.72vw, 56px);
  font-weight: 400;
  line-height: 1.4;
  text-align: center;
}

.news-list { max-width: 754px; margin: 0 auto; }

/* 265px thumbnail, a 23px gutter, then the text. 329 tall including the rule,
 * which is taller than any of the content — the source's cards are a fixed
 * height and the copy sits at the top of them. */
.news-card {
  display: grid;
  grid-template-columns: 265px 1fr;
  gap: 23px;
  align-items: start;
  min-height: 329px;
  padding: 3px;
  border: 1px solid var(--shell);
  background: var(--paper);
  box-sizing: border-box;
}
.news-card + .news-card { margin-top: 58px; }   /* 382 -> 769, less the 329 card */
.news-index .news-list { margin-top: 28px; }    /* heading ends 354, card starts 382 */

.news-thumb {
  width: 265px;
  height: 265px;
  object-fit: cover;
  display: block;
  background: var(--shell);
}

.news-card-text { padding-top: 25px; max-width: 450px; }  /* content starts 386, h2 at 411 */
/* The 36px floor is what makes both cards land. The source gives this block a
 * minimum slot and then a constant 8px gap, so a one-line title (28px tall)
 * still occupies 36 and a three-line one (84px) pushes the standfirst down by
 * its own height. A plain 16px margin fits the one-line card and leaves the
 * three-line card 8px low, which is not two bugs but one wrong model. */
.news-card-text h2 {
  font-family: var(--body);
  font-size: 20px;
  font-weight: 700;
  line-height: 1.4;
  min-height: 36px;
  margin: 0 0 8px;
}
.news-card-text h2 a { color: var(--ink); text-decoration: none; }
.news-card-text h2 a:hover { text-decoration: underline; }

/* The link sits 99px below the top of the standfirst on both cards, whether
 * the standfirst runs to one line or two — the source gives this block a fixed
 * height rather than a margin, so a fixed height is what reproduces it. */
.news-standfirst {
  font-size: var(--size-body);
  line-height: 1.6;
  margin: 0;
  min-height: 99px;
  max-width: 432px;
}

/* 22px and rust, sampled off the live page at rgb(196, 83, 8). Not a button:
 * the source draws it as a plain link even though Wix calls it one.
 *
 * Nunito Sans 300, not the body font. The source sets this in
 * avenir-lt-w01_35-light, the same unlicensable light cut as the header nav,
 * and Nunito Sans 300 is the stand-in that section already settled on. Left in
 * Montserrat the label measured 15px wider than the source's. */
.news-more { margin: 0; }
.news-more a {
  font-family: 'Nunito Sans', Helvetica, Arial, sans-serif;
  font-weight: 300;
  font-size: 22px;
  line-height: 1.4;
  color: var(--rust);
  text-decoration: none;
  white-space: nowrap;
  /* The source fades to rgb(150,63,6) over 0.4s rather than underlining. */
  transition: color 0.4s ease;
}
.news-more a:hover { color: #963F06; }

@media (max-width: 768px) {
  /* The 2228px pin is a desktop measurement of a page that does not reflow.
     On a phone the copy is taller than that anyway, and where it is not the
     min-height would show as dead space above the footer. */
  .news-article { min-height: 0; }
  .news-card {
    grid-template-columns: 1fr;
    min-height: 0;
    gap: var(--s-4);
    padding: var(--s-4);
  }
  .news-thumb { width: 100%; height: auto; aspect-ratio: 1; }
  .news-card-text { padding-top: 0; }
  .news-standfirst { margin-bottom: var(--s-4); max-width: none; }
}

/* The intake form embed. A fixed height because the form is cross-origin and
 * cannot report its own; tall enough for the longest state of the form. */
.intake-form { margin-block: var(--s-6); }
.intake-form iframe {
  width: 100%;
  min-height: 820px;
  border: 0;
  display: block;
}

/* --- Rebuilt pages: the legal documents -------------------------------
 * /privacy and /terms. Both are a 24px opening line and a column of 16px
 * prose with no banner, so the type is shared on `.legal-doc` and only the
 * padding below is per page.
 *
 * Measured off the live /privacy at 1440px; the full table is in
 * notes/wip/privacy-migration.md. A paragraph has no margin and a 1.4 line
 * box, and a section heading sits 45px below whatever precedes it.
 *
 * That 45px is not a chosen number. /privacy separates its sections with
 * two empty 22px paragraphs, which is what this replaces -- along with the
 * two zero-width-space paragraphs Wix leaves at each end of the document.
 * /terms spaces its sections unevenly, one blank line before some and two
 * before others, so it keeps the source's spacer paragraphs instead and
 * ships no <h2> at all. */

/* 227->278 at the top on both. The foot differs: /privacy ends at 1971 and
 * /terms at 1675, both against a footer that follows immediately. */
.privacy { padding-block: 51px 91px; }
.terms { padding-block: 51px 108px; }

/* 24px, the size the source sets its opening line at. It is a paragraph
 * there; the source ships no heading of any level on either page. */
.legal-doc h1 {
  font-family: var(--body);
  font-size: 24px;
  font-weight: 400;
  line-height: 1.4;
  margin: 0;
}

.legal-doc-body { line-height: 1.4; }
.legal-doc-body p { margin: 0; }
.legal-doc-body h2 {
  /* 16px and bold: the source renders these as ordinary body text in a bold
   * span, so a heading that looked like a heading would be a difference. */
  font-family: var(--body);
  font-size: var(--size-body);
  font-weight: 700;
  line-height: 1.4;
  margin: 45px 0 0;
}
/* The date line sits directly under the title, with no gap. */
.legal-doc-body > p:first-child { margin: 0; }

/* Bullets indent 8px from the text column, their contents 21px further. */
.legal-doc-body ul { margin: 0; padding-left: 29px; }
.legal-doc-body li { margin: 0; }
.legal-doc-body li p { margin: 0; }

/* --- Rebuilt page: contact -------------------------------------------
 * Measured off the live /contact at 1440px; the full table is in
 * notes/wip/contact-migration.md. The band boundaries are 227 / 488 / 773 /
 * 1674 / 1843 / 2518 / 2679, and every number below is a difference between
 * two of them. */

/* 261px, not the 346 the practice pages use: the band runs y=227 to y=488.
 * Hero height varies by page type on the source -- see docs/PARITY-AUDIT.md
 * 1b, where assuming one height shipped a defect. */
/* 72px, not the 123 the practice banners use: the source starts "Contact Us"
 * at y=299, which is 72 below the band's visible top at 227. */
.practice-head.hero-contact { min-height: 261px; padding-block: 72px 0; }
/* 85px, the page default, rather than the 66px the practice banners drop to:
 * "Contact Us" measures 120px tall on the live page, which is 85px at the
 * site's 1.4 line-height. */
.practice-head.hero-contact h1 {
  /* 8.68vw is 85 at 980, the tablet canvas; at 6vw this resolved to 58.8
   * there and the maximum was unreachable. See .hero-faq-index h1. */
  /* Flat, not a clamp. 8.68vw reaches 85 exactly AT the 980 tablet canvas and
   * undershoots below it -- 67.7px at a 780 window against the source's
   * constant 85 -- because the desktop build holds a 980 canvas there (the
   * min-width on body) while vw keeps tracking the smaller window. Measured
   * live at 780, 980 and 1440: 85/119 at all three. */
  font-size: var(--size-hero);
  /* Set, not inherited: the shared rule pins 89.6px, which is 1.4 of the 64px
   * the practice banners use, and left this title in a 90px box. */
  line-height: 1.4;
  margin: 0;
}

/* The motto band starts 1355px below the top of this block in both languages,
 * because the source pins it and lets the space after the form flex -- 169px
 * in English, 115 in Spanish, where the heading wraps to two lines and pushes
 * everything under it down 54px. Fixing the trailing gap instead would leave
 * the Spanish page 54px taller than the source. */
.contact-main { min-height: 1355px; }

/* Heading top sits 42px below the band, and the form 51px below the address. */
.contact-details { padding-block: 42px 51px; }

/* The source indents this block 192px inside the 980px column while the form
 * below it runs the full width. Dropped at the point the indent would leave
 * less room for the text than for the margin. */
.contact-inner { padding-left: 192px; }
@media (max-width: 768px) {
  .contact-inner { padding-left: 0; }
  /* The 1355px pin is a desktop measurement. On a phone the block is shorter
     than that and the min-height would show as dead space under the form. */
  .contact-main { min-height: 0; }
}

/* 293px is the source's box for this heading. It changes nothing in English,
 * where "Get in Touch" fits on one line, and is what makes "Ponte en
 * contacto" wrap onto two the way the Spanish page does. */
.contact-details h2 {
  font-size: 42px;
  line-height: 1.3;
  margin: 0 0 11px;
  max-width: 293px;
}

/* Label column 126px, measured from the gap between the labels at x=422 and
 * their values at x=548. Rows are 19px apart with no gap between them, which
 * is the natural line box of 16px Montserrat -- hence the explicit `normal`
 * rather than the 1.8 body line-height. */
.contact-list {
  display: grid;
  grid-template-columns: 126px auto;
  line-height: normal;
  margin: 0 0 21px;
}
.contact-list dt,
.contact-list dd { margin: 0; }

/* 0.04em, which check_metrics reads off the live page as 0.64px at 16px. It
 * runs through every body line in this block and the footer's; without it the
 * rows measure 4 to 11px narrow. */
.contact-list,
.contact-office,
.contact-details address { letter-spacing: 0.04em; }

/* 1.4, not the 1.8 body default: the label measures 22px tall on the live
 * page and the two-line address 45px, which is 16px at 1.4 both times. */
.contact-office,
.contact-details address {
  line-height: 1.4;
  margin: 0;
}
.contact-details address { font-style: normal; }

/* 901px on the live page, against the 820 the homepage's copy of this embed
 * needs. Set here rather than on .intake-form so the two pages do not have to
 * agree on a height they do not share. */
.contact-form .intake-form { margin-block: 0; }
.contact-form .intake-form iframe { min-height: 901px; height: 901px; }

/* The motto band: one 836px section carrying the photograph, with a 161px
 * navy strip over its bottom edge. Full bleed by design -- the source runs it
 * edge to edge, so it has no .container.
 *
 * The strip overlays the photograph rather than sitting below it. The image
 * is cropped to 836, not to the 675 left visible, which is what puts the
 * office sign where the source puts it. */
.motto {
  position: relative;
  height: 836px;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
.motto-strip {
  position: absolute;
  inset: auto 0 0 0;
  background: var(--navy);
  height: 161px;
  padding-top: 44px;
  /* The heading sits at the CONTAINER'S LEFT EDGE — x=230 at 1440 — on every
   * page that carries this band: /contact, /attorney-referrals, both FAQ
   * indexes and the insight index all measure align=start there. It reads as
   * centered because at 52px the line is 957px wide inside a 980px container,
   * which is why this shipped centered and only showed up as a 4px dx. */
  text-align: left;
  padding-inline: max(var(--s-4), (100% - var(--container)) / 2);
  /* The mark sits across an atomic-inline boundary from the heading, which is
   * a soft wrap opportunity: the Spanish line measures 976px inside a 980px
   * container, so the ® alone dropped to a second line at x=230 where the
   * source keeps it beside the heading's tail at x=1185. Lifted under 768px,
   * where the heading shrinks with 7vw and has to be free to wrap. */
  white-space: nowrap;
}
/* inline-block, so the heading keeps its own line box -- as a plain inline it
 * reported 64px tall against the source's 73 -- while still sitting on one
 * line with the trademark mark beside it. */
.motto-heading {
  display: inline-block;
  font-family: var(--display);
  font-size: min(52px, 7vw);
  font-weight: 700;
  line-height: var(--line-hero);
  color: var(--paper);
  margin: 0;
}
/* The source sets this mark on the BASELINE in a 28px line box, not raised:
 * it computes font-size 20, line-height 28, vertical-align baseline, and sits
 * flush with the heading's own baseline. `super` lifted it 64px above where
 * the source paints it. */
.motto-mark {
  color: var(--paper);
  font-size: 20px;
  line-height: 28px;
  /* Top of the line box, not the baseline. The source paints the mark's top 2px
   * under the heading's own top -- it is a SIBLING of the heading, positioned
   * independently, so a baseline alignment drops it to the foot of a 73px line
   * and 35px below where the source has it. */
  vertical-align: top;
}

@media (max-width: 768px) {
  .motto { height: 420px; }
  .motto-strip { height: auto; padding: var(--s-4); white-space: normal; }
}

/* The motto without its photograph. /attorney-referrals and the two FAQ
 * indexes paint only the navy strip, so the section measures the strip's own
 * 161px and nothing more. */
.motto.strip-only { height: 161px; background: none; }
@media (max-width: 768px) {
  .motto.strip-only { height: auto; }
}


/* --- Rebuilt page: attorney referrals ------------------------------------
 *
 * Measured off the live page at 1440px with tools/component_report.py, as dy from
 * y=227 where the header ends. Geometry is read off each heading's block and
 * type off the span inside it, which are not the same box.
 *
 *    123  h1 block, dx=230 dw=980; the run inside it 85px, dx=308 dw=825
 *    345  the standfirst, 26px, dw=952
 *    433  first paragraph, 18px
 *    541  second paragraph
 *    757  third paragraph
 *    972  the motto heading, 52px
 *
 * The hero is authored at y=80 and 454 tall, so it ends at 534 with the header
 * covering its first 147px. 306 is the part that is ever visible.
 */
/* The title is not centered in the visible band: the source centers it in the
 * authored height, which the header then covers the top 147px of. Aligning to
 * the top and spacing down 118px reproduces that without pretending the hidden
 * part is there.
 *
 * The band grows with the title rather than being one number, which is what
 * the two locales together show: the source authors 454 for the English
 * one-liner and 566 for "Remisiones de abogados", which wraps to two. Minus
 * the header's 147 that is 306 and 419, and 118 + line-box + 63 lands on both.
 * A fixed 306 left the Spanish page 63px short and every band under it with it. */
.practice-head.hero-referrals {
  min-height: 306px;
  align-items: flex-start;
  padding-block: 118px 63px;
}
/* 85px, against the 66px shared default that "Car Accidents" needs: this
 * title's run measures 825px wide on the source and 640 at the default.
 *
 * line-height is set here rather than inherited: the source computes 1.4, or
 * 119px a line, and the inherited 89.6px made the band 360px on the Spanish
 * page against the 419 the padding model above targets. Measure this on the
 * h1, not on the span inside it -- the span carries content height and the
 * block carries the line box. */
.practice-head.hero-referrals h1 {
  /* 8.68vw is 85 at 980, the tablet canvas; at 6vw this resolved to 58.8
   * there and the maximum was unreachable. See .hero-faq-index h1. */
  /* Flat, not a clamp. 8.68vw reaches 85 exactly AT the 980 tablet canvas and
   * undershoots below it -- 67.7px at a 780 window against the source's
   * constant 85 -- because the desktop build holds a 980 canvas there (the
   * min-width on body) while vw keeps tracking the smaller window. Measured
   * live at 780, 980 and 1440: 85/119 at all three. */
  font-size: var(--size-hero);
  line-height: 1.4;
  margin: 0;
}

/* 40 above, against the shared 56: the standfirst sits 38px below the hero on
 * the source. 61 below, which is what puts the motto strip at y=1151. */
.referrals-body { padding-block: 40px 61px; }
/* The 54px the source leaves between the standfirst and the first paragraph,
 * less the 31 the h3's own line box already contributes. */
.referrals-body h3 {
  font-size: 26px;
  line-height: 1.2;
  font-weight: 700;
  margin: 0 0 23px;
}
/* No margins, and no measure limit. The gaps between these paragraphs are the
 * source's own empty spacer paragraphs, carried through in the body HTML;
 * giving the paragraphs margins as well counts every gap twice. */
.referrals-body p {
  font-size: 18px;
  line-height: 1.5;
  max-width: none;
  margin: 0;
}


/* --- Rebuilt page: /faqs ----------------------------------------------
 *
 * The FAQ hub. Measured off the live /faqs at 1440px; the full table is in
 * notes/wip/faqs-hub-migration.md. /es-us/faqs measures identically, so
 * nothing here branches on locale.
 *
 * The category card itself is styled as .faq-picker* well above this, near the
 * shared components; only the motto strip under it is here.
 */

/* The strip with no photograph above it. /contact overlays the same strip on
 * an 836px image; here the source paints the strip alone. */
.motto.motto-bare { height: 161px; }
/* Heading against the container's left edge, not centered: the source sets it
 * at x=230, which is where the 980px container starts at 1440. */
.motto.motto-bare .motto-strip {
  text-align: left;
  padding-inline: max(var(--s-4), (100% - var(--container)) / 2);
}

@media (max-width: 768px) {
  /* No photograph to overlay, so the strip sets the band's height itself. */
  .motto.motto-bare { height: auto; }
  .motto.motto-bare .motto-strip {
    position: static;
    padding: var(--s-6) var(--s-4);
  }
}


/* ==========================================================================
   FOOTER — shared by every page
   ========================================================================== */

/* --- Site footer -------------------------------------------------------
 *
 * Geometry read from the computed-style capture (captures/reference/dom/),
 * NOT from a screenshot, and verified identical across 66 pages. Screenshot
 * measurement got this wrong twice in the same way: the photograph sits under
 * a navy gradient that fades it toward the band color, so a color-boundary
 * scan called the photo 288px when the element is 702px.
 *
 * The content column is 1180px: the card and "Let's Talk." both start at
 * x=131 and the logo block ends at x=1310. An earlier reading of x=150 was
 * the glyph ink edge, not the element box.
 *
 * NOTE: the "No One Will Work Harder For You." band is NOT part of the
 * footer. It is an authored page section that appears above the footer on
 * a minority of pages, and its contents vary per page — heading alone,
 * heading plus the results disclaimer, or heading plus a paragraph and a
 * call to action. It used to be rendered here, which put a legal disclaimer
 * on ~500 pages that had no business carrying one.
 */
/* The footer column widens with the viewport instead of staying a fixed width.
   Measured on the source at three widths: its left margin grows by a quarter of
   the viewport delta (130 at 1440, 233 at 1850, 250 at 1920), which makes the
   column itself 50vw + 460px.

   A fixed 1180px matched at 1440 and drifted badly above it -- at 1850 the
   content sat 100px narrower on each side than the source. Both footer bands
   use this container, and both scale this way. */
/* max(), because the desktop layout has a 980 floor (see the min-width on body):
   below that the canvas stops shrinking but `vw` keeps tracking the window, so
   at an 800px window this resolved 130px narrower than the canvas it sits in and
   the column drifted inward from the source's constant 16px inset. 490 is 50vw
   at 980. */
.footer-wide {
  width: calc(max(50vw, 490px) + 460px);
  max-width: 100%;
  margin: 0 auto;
}

/* One section, 962px tall, navy-mid. The photograph fills the whole section
 * (1440x962); a separate 702px-tall gradient sits over its top, running solid
 * navy at 0% to transparent at 76.5625%. Reading the 702px element as the
 * photograph — rather than as the overlay on top of it — is what produced a
 * 288px photo band earlier, then a 702px one. The card starts 174px down. */
.footer-story {
  position: relative;
  /* How far the photograph lags the page, read by static/js/parallax.js so the
     rate and the layer height above cannot drift apart. 0 stops the effect. */
  --footer-parallax-rate: .8;
  background: var(--navy-mid);
  min-height: 962px;
  box-sizing: border-box;
  /* The photograph below lags the page and travels ~700px either side of the
   * band, so the band has to clip it. */
  overflow: hidden;
  /* Padding rather than a margin on the card: a top margin on the first
   * child collapses out through the section, which opened a gap above the
   * band and pinned the card to its top edge. */
  padding-top: 174px;
}
.footer-story-photo {
  position: absolute;
  inset: 0 0 auto 0;
  /* Viewport-tall, not band-tall, and this is a requirement rather than a
   * preference. The layer sits at `rate * (scrollY - bandTop)`, so the band's
   * bottom edge is the one that can be uncovered, and working out the worst
   * case -- the moment the band's foot reaches the viewport's foot -- gives
   *
   *     height >= (1 - rate) * bandHeight + rate * viewportHeight
   *
   * which is a weighted average of the band and the viewport, and so can never
   * exceed the larger of the two. `max(100%, 100vh)` is therefore sufficient at
   * every viewport and for any rate, without a tuned number in it.
   *
   * Pinning this to the band's own height drops the viewport term and breaks
   * exactly when the viewport is the taller of the two -- which on a phone it
   * always is. A 476px band in an 844px window needs 770 and had 476, so the
   * lower 295px of it was bare navy behind the card. */
  height: max(100%, 100vh);
  background-image: var(--footer-photo);
  background-size: cover;
  background-position: center;
  /* The source paints this photograph at 0.69 over the band's --navy-mid, the
     same construction the practice banner and .types-photo use. At full opacity
     the picture reads warm and bright against a footer the source keeps navy:
     a patch below the scrim measured (138,104,68) here against (110,92,74)
     live, and 0.69 predicts (111,92,74). */
  opacity: .69;
  /* `transform` is written straight onto this element by
   * static/js/parallax.js, which measures the band and moves the layer at the
   * source's 0.8 of the scroll. It used to arrive through a custom property on
   * the section, which invalidates style for every node in the band on each
   * frame; the layer is its own element now so the write stays on the
   * compositor. Untouched without script, which leaves the band exactly as it
   * was before the effect existed. */
  will-change: transform;
}
.footer-story::after {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  /* The source's exact stops, not an approximation. */
  height: 702px;
  background: linear-gradient(rgb(35, 44, 83) 0%, rgba(35, 44, 83, 0) 76.5625%);
}
.footer-story .footer-wide { position: relative; z-index: 1; }

/* The story band -- and only the story band -- goes full width once the window
 * is narrow enough that `50vw + 460px` no longer fills it. At a 980 viewport
 * that formula yields 942, which inset the story copy 16px to the right of the
 * source's. The contact band below it is already right at that width and moves
 * 16px the wrong way if this is applied to both, which is how the two were
 * told apart. */
@media (max-width: 1028px) {
  .footer-story .footer-wide { width: 100%; }
}

.footer-card {
  background: var(--paper);
  width: 490px;
  max-width: 100%;
  min-height: 405px;
  /* 56 above the heading, 44 to its left: the heading sits at x=175 in a
   * card whose box starts at x=131. Height grows for Spanish, which measures
   * 429 against English's 405. */
  padding: 56px 44px 58px;
  /* The card starts one pixel past its wrapper. That is Wix hand-positioning,
     not a rounding artifact -- both sides report an integer x and a 1440px
     document, and the same offset holds at 1850. */
  margin-left: 1px;
  box-sizing: border-box;
}
.footer-card h2 {
  color: var(--ink);
  font-family: var(--display);
  font-size: 36px;
  font-weight: 700;
  /* 93px over two lines, then a 38px gap to the paragraph. */
  line-height: 46.8px;
  margin: 0 0 38px;
}
/* No max-width. The card's own padding already gives a 402px column, and
   capping the paragraph at 400 was two pixels short of it -- enough to push
   one word onto a fifth line and drag the buttons below 26px down the page. */
.footer-card p { color: var(--ink); font-size: 16px; line-height: 24px; letter-spacing: .04em;
                 margin: 0 0 23px; }
/* Selector has to out-rank `.footer-card p`, which is (0,1,1) and was
 * keeping a 26px bottom margin on this element. */
.footer-card p.footer-card-links { display: flex; gap: 26px; flex-wrap: nowrap; letter-spacing: normal; margin: 0; }
.footer-card-links a {
  /* 2px, and a white fill: measured off the button's own computed style. */
  border: 2px solid var(--steel);
  background: var(--paper);
  color: var(--steel);
  font-size: 14px;
  font-weight: 700;
  /* 180x40 on the source: 18px of text, 10px padding, 1px border each side.
   * Without an explicit line-height these inherit the 1.8 body value and
   * come out 45 tall. */
  line-height: 18px;
  /* Fixed 180, not a minimum: both locales use 180x40 buttons on a single
   * row, and the source truncates the longer Spanish labels to fit rather
   * than widening the button -- see the ellipsis on the label span below.
   * Letting them size to content wrapped them onto a second row and made the
   * Spanish card 66px too tall. */
  width: 180px;
  flex: none;
  box-sizing: border-box;
  /* 9 + 18 line + 9 + two 2px borders = the measured 40. Horizontally the
   * source leaves 2px before the label box and 18px after it for the
   * chevron, which is what puts its 180px button around a 160px label. */
  padding: 9px 2px;
  text-align: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  transition: background-color .2s, color .2s, fill .2s;
  text-decoration: none;
  white-space: nowrap;
}

/* "Let's Talk." sits 80px into this band; the logo block 26px into it. */
/* Fixed height, because the band does not size to its contents on the
 * source: the logo block runs from y=3347 to 3724 inside a band that ends at
 * 3709, so it overflows by 15px. Letting the grid set the height instead made
 * the band 437 rather than 388. */
.footer-talk {
  background: var(--paper);
  color: var(--ink);
  /* 437, not 388: the footer map iframe measures 350 tall on both the
   * homepage and /car-accidents, so the talk band takes the rest. */
  height: 437px;
  box-sizing: border-box;
  padding: 26px 0 0;
}
/* Underlined: captures/html/index.html sets `text-decoration:underline` as an
 * inline style on the phone, email and address runs. getComputedStyle on the
 * innermost text-bearing span reports "none" because text-decoration-line is
 * not an inherited property and Wix declares it on an ancestor span, not the
 * span with the text -- the line still paints, because the browser draws a
 * decoration from the declaring box down through its descendants regardless
 * of what the descendant's own computed value says. Confirmed by screenshot
 * of the live footer at 1440px: 570-287-3000, hkq@hkqlaw.com and the Kingston
 * address are all underlined by default, not only on hover. */
.footer-talk a,
.site-footer address a { color: var(--ink); text-decoration: underline; }
.footer-talk-grid {
  display: grid;
  align-items: start;
  /* The logo block measures 461x377 and ends at x=1310. */
  grid-template-columns: 1fr 461px;
  gap: var(--s-6);
  align-items: start;
}
.footer-talk h2 {
  color: var(--ink);
  font-family: var(--display);
  /* 42px, not 32: measured off the element, not off ink extents. */
  font-size: 42px;
  font-weight: 700;
  /* 54.6px, which is 42 x 1.3 and what the live heading computes. 52 was
   * measured off the painted ink rather than off the element. */
  line-height: 54.6px;
  margin: 54px 0 30px;
}

.footer-contact {
  display: grid;
  /* Values start at x=315 against labels at x=131: a 184px first column. */
  grid-template-columns: 184px 1fr;
  gap: 0;
  margin: 0 0 23px;
  font-size: 16px;
  line-height: 19px;
  letter-spacing: .04em;
}
.footer-contact dt, .footer-contact dd { margin: 0; }
/* The source sets `overflow-wrap: break-word` on the label spans, which only
   bites in the 73px phone column: "Correo electrónico:" breaks there into three
   lines of 42.8, 72.41 and 3.03px rather than overflowing on two. */
.footer-contact dt { overflow-wrap: break-word; }
.footer-office { font-size: 16px; line-height: 22.4px; font-weight: 700; letter-spacing: .04em; margin: 0; }
.footer-office strong { font-weight: 700; }
.site-footer address { font-style: normal; font-size: 16px; line-height: 22.4px; letter-spacing: .04em; }

.footer-row { display: flex; align-items: center; gap: 41px; margin-top: 21px; }
/* The source positions the icons and the selector independently, and the
   selector sits 4px lower than the icons rather than sharing their center
   line. Relative, so it shifts without changing the row's height. */
.footer-row .locale-select { position: relative; top: 4px; }
.footer-social { list-style: none; display: flex; gap: 10px; margin: 0 0 0 -11px; padding: 0; }
/* 39px icons on a 49px pitch, starting 11px left of the text column. */
.footer-social img { display: block; width: 39px; height: 39px; }

/* Both of these ran off the viewport at phone width, which made every page on
 * the site scroll sideways. The source never reflows -- it serves one 980px
 * desktop layout -- so there is nothing to measure against here and no
 * desktop geometry at risk: the rules below apply only below 768. */
@media (max-width: 768px) {
  /* Two 180px buttons and a 26px gap need 386px before the card's padding. */
  .footer-card p.footer-card-links { flex-wrap: wrap; gap: var(--s-2); }
  /* The -11px pull aligns the icons with the text column on a fixed layout;
     inside a padded column it puts them past the left edge. */
  .footer-social { margin-left: 0; }
}
/* Hover grays the label to rgb(112,112,112) on the source. */
/* The language selector, measured off the live control: white, a 1px grey
   border with no radius, 16px Montserrat, and a chevron inset 15px from the
   right to match the 15px text inset on the left. The footer instance is
   113x45; the one under the intake form is 112x48. */
.locale-select {
  appearance: none;
  -webkit-appearance: none;
  box-sizing: border-box;
  width: 113px;
  height: 45px;
  padding: 0 15px;
  border: 1px solid rgb(149, 149, 149);
  border-radius: 0;
  background: var(--paper) url('../img/site/locale-chevron.svg') no-repeat right 15px center;
  background-size: 12px auto;
  font-family: var(--body);
  font-size: 16px;
  color: var(--ink);
  cursor: pointer;
  transition: color .2s;
}
.locale-select:hover { color: rgb(112, 112, 112); }

.footer-logo-block img { display: block; width: 100%; height: auto; }

/* 350, measured off the iframe itself rather than inferred from a gap. */
.footer-map { height: 350px; }
.footer-map iframe,
.footer-map #office-map { width: 100%; height: 100%; border: 0; display: block; }
.map-info { font-size: 13px; line-height: 1.4; }

/* 40 above and below a 65px block of two lines, which is the source's 145 all
 * in. Measured on the live footer at 1440 and again on the 980 tablet canvas,
 * where it is the same band: 46px of padding and a 10px gap between the lines
 * made it 167 and put every page carrying this footer 22px long. */
.footer-legal {
  background: var(--navy);
  color: var(--paper);
  text-align: center;
  padding: 40px 0;
}
.footer-legal p { margin: 0; }
/* 20px bold over 16px regular, both white — measured, not the small-text
 * default this previously used for both lines. */
/* 36px, measured on the live line; 24 was the size's own default. */
.footer-copyright { font-size: 20px; font-weight: 700; line-height: 36px; }
/* 28.8px, 16 x 1.8, which is what the live credit line computes. */
/* No gap above it: the source's two lines are a 65px block, which is this
 * line's 28.8 box under the copyright's 36 with nothing between them. */
.footer-credit { font-size: 16px; font-weight: 400; line-height: 28.8px; letter-spacing: .04em; margin-top: 0 !important; }

@media (max-width: 900px) {
  .footer-talk-grid { grid-template-columns: 1fr; }
  .footer-story { min-height: 0; }
  /* The gradient only, not the photograph. `::before` moves, so a pinned
     height uncovers the band's bottom edge as it travels -- the derivation is
     on `.footer-story-photo`, and this rule reaches every viewport under
     900px, not just the phone build. */
  .footer-story::after { height: 200px; }
  .footer-story { padding-top: 140px; }
  .footer-card { margin-left: 0; }
  .header-inner { padding: var(--s-3) var(--s-4); min-height: 0; flex-wrap: wrap; }
}


/* ==========================================================================
   TEAM
   ========================================================================== */

/* --- /team ------------------------------------------------------------
 * Measured from captures/reference/dom/1440/team.json.gz. Every number here
 * came off the element, not off a screenshot. */

/* The hero is 324px on this page, not the 346 the practice pages use — hero
 * height varies by page type and the shared partial cannot assume one value. */
.team-head {
  background: var(--navy);
  color: var(--paper);
  text-align: center;
  height: 324px;
  box-sizing: border-box;
  padding-top: 100px;
  /* The band is a fixed height sized for one line of title plus the subtitle.
     If the title wraps, the subtitle is pushed out of the navy and onto the
     grey below it -- so the title does not wrap, and the band clips instead.
     That is what the source does at these widths too. */
  overflow: hidden;
}
.team-head h1 {
  color: var(--paper);
  font-size: 85px;
  /* 119px, and a negative margin under it. The source sets a line box far
     taller than the type and then pulls the line beneath back up into it --
     leading and gap are one measurement here, not two. */
  line-height: 119px;
  margin: 0 0 -19px;
  white-space: nowrap;
}
.team-head-sub {
  font-family: var(--display);
  font-size: 46px;
  font-style: italic;
  font-weight: 400;
  line-height: 64.4px;
  margin: 0;
}

/* The grid sits on a light grey band, not on white. */
/* 73 above the first row, 25 below the last. */
.team-grid-wrap { background: var(--shell); padding: 73px 0 25px; }

.team-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  /* 528px cards on a 38px gap, centerd: two columns at 1440, three at 1920.
   * This page is the only one on the site whose desktop layout reflows. */
  grid-template-columns: repeat(auto-fill, 528px);
  gap: 38px;
  justify-content: center;
}

.team-card {
  display: grid;
  grid-template-columns: 250px 1fr;
  width: 528px;
  height: 352px;
  background: var(--navy-deep);
  color: var(--paper);
  overflow: hidden;
}
.team-card-photo { width: 250px; height: 352px; object-fit: cover; display: block; }

.team-card-panel {
  /* 21px of side padding, so the text column is ~235 wide. That is what
   * makes "Senior Principal, Commercial Department" wrap to two lines at
   * 231, exactly as the source does. */
  padding: 30px 21px 0;
  text-align: center;
}
/* The name escapes the panel's padding and never wraps. Names run to 271px
 * ("Anjelica N. Singer Homza") against a 236px padded column, so constraining
 * them breaks "Michael A. Lombardo III" across two lines. The source centers
 * them on the panel and lets them use its full 278px. */
.team-card-name {
  font-size: 20px;
  line-height: 28px;
  margin: 0 -21px 11px;
  color: var(--paper);
  white-space: nowrap;
}
.team-card-name a { color: var(--paper); text-decoration: none; }
.team-card-name a:hover { text-decoration: underline; }
/* 22px line box: one line measures 19 tall on the source and two measure
 * 41, which is 22 + 19 rather than twice anything. */
/* The role escapes the panel's side padding the way the name does. Held inside
   it the column is 236px, and "Head of Commercial Department" wrapped to two
   lines where the source keeps it on one -- the source gives this line the
   panel's full 278px and only wraps the roles genuinely longer than that. */
.team-card-role { font-size: 16px; line-height: 22px; margin: 0 -21px 15px; }
.team-card-practice {
  font-size: 16px;
  line-height: 22.4px;
  font-style: italic;
  /* Divider 14 below the text, then 16 to the contact rows. */
  margin: 0 -21px 16px;
  /* 241px of measure, not the panel's padded 236. This line escapes the
     panel's padding like the name and role do, then takes its own 18px inset
     -- which is what the source gives it. */
  padding: 0 18px 14px;
  position: relative;
}
/* A short centerd rule, not a full-width border. */
.team-card-practice::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  /* 76 x 3, centerd — measured off the card, where it spans x 101..176 of a
   * 278px panel and occupies three full rows. */
  width: 76px;
  height: 3px;
  transform: translateX(-50%);
  background: var(--paper);
}
/* Left-aligned, unlike the centerd text above: the rows start at x=271 in a
 * panel that starts at 250. */
.team-card-contact {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 14px;
  /* 19.6 is the text's own leading; the 30px row pitch is the row's, not the
     line box's. Carrying the pitch as line-height gave every contact line a
     30px box against the source's 18 -- the same pitch, painted differently. */
  line-height: 19.6px;
  text-align: left;
}
.team-card-contact li { display: flex; align-items: center; min-height: 30px; }
.team-card-contact a { color: var(--paper); text-decoration: none; }
.team-card-contact a:hover { text-decoration: underline; }
.team-icon {
  width: 21px;
  height: 21px;
  flex: none;
  /* 16px to the text, which puts it at x=308. */
  margin-right: 16px;
}
/* Flows with the content; it is not pinned to the card's bottom. On the
 * source it sits at y=241 on a short card and y=286 on a wrapped one. */
.team-card-more { margin: 22px 0 0; }
.team-card-more a {
  /* 135x29 overall on the source: an 18px label, 3.5px above and below,
   * 16px each side, 2px border. Inline-flex so the chevron sits beside the
   * label with the measured 4px gap rather than inside the text run. */
  display: inline-flex;
  align-items: center;
  gap: 4px;
  box-sizing: border-box;
  border: 2px solid var(--steel);
  color: var(--steel);
  font-size: 14px;
  font-weight: 700;
  line-height: 18px;
  padding: 3.5px 16px;
  text-decoration: none;
  background: var(--navy-deep);
  transition: background-color .2s, color .2s, fill .2s;
}

/* Hover, measured off the source: the border color floods the button and
 * both the label and the chevron go white. The chevron's rest blue
 * (135,181,220) is not the label's (130,160,186), but on hover they meet at
 * white. 0.2s, matching the source's transition. */
.team-card-more a:hover,
.team-card-more a:focus-visible {
  background: var(--steel);
  color: var(--paper);
}
.team-card-more a:hover .team-chevron,
.team-card-more a:focus-visible .team-chevron {
  fill: var(--paper);
}

@media (max-width: 620px) {
  .team-grid { grid-template-columns: 1fr; }
  .team-card { width: 100%; height: auto; grid-template-columns: 1fr; }
  /* Cropped, not letting the portrait run to its natural height. The source
     shows a 280x340 crop in a 320px window; at natural aspect ours came out
     562px tall in a 375px one, which is most of a phone screen for one photo.
     The card is inset 20px either side, as the source insets it. */
  .team-card { width: calc(100% - 40px); margin-inline: auto; }
  /* Grid items floor at their min-content width unless told otherwise, which
     let one card's panel run 297 wide inside a 280 card. */
  .team-card > * { min-width: 0; }
  .team-card-photo {
    width: 100%;
    height: auto;
    aspect-ratio: 280 / 340;
    object-fit: cover;
    object-position: 50% 20%;
  }

  /* The card's type on mobile is the source's own mobile scale, which is
     larger than its desktop one -- 22px for the name against 20 -- and then
     scaled again, because the source lays out at a fixed 320 and lets the phone
     enlarge the whole page to fit. Expressing these in vw reproduces that
     scaling without adopting the fixed viewport: 6.875vw IS 22px at 320. The
     clamps keep it sane at the top of this breakpoint, where a phone layout is
     being shown on something tablet-sized. */
  /* Wraps here, unlike desktop. The source gives the name the card's full
     280px at the 320 canvas and lets "Kathleen Quinn DePillis" and "Anjelica
     N. Singer Homza" run to two lines; nowrap ran them off the card. */
  .team-card-name {
    font-size: clamp(20px, 6.875vw, 26px);
    line-height: 1.4;
    white-space: normal;
  }
  .team-card-role { font-size: clamp(16px, 5vw, 19px); line-height: 1.4; }
  .team-card-practice { font-size: clamp(14px, 4.4vw, 17px); line-height: 1.5; }
  .team-card-contact { font-size: clamp(14px, 4.7vw, 18px); line-height: 1.5; }
  .team-card-more a {
    min-width: clamp(160px, 50vw, 190px);
    height: clamp(42px, 13vw, 49px);
  }
  .team-card-panel { padding: 26px 20px 30px; }
  /* The band grows instead of clipping, and the title is sized to hold one
     line at phone widths -- the source keeps "Meet Our Team" unbroken. */
  .team-head { height: auto; padding: 48px 0; overflow: visible; }
  .team-head h1 {
    font-size: clamp(26px, 9.4vw, 46px);
    line-height: 1.2;
    margin-bottom: 4px;
    white-space: nowrap;
  }
  .team-head-sub { font-size: clamp(20px, 6vw, 28px); line-height: 1.4; }
  /* 73px above the first card is a desktop measurement; on a phone it reads as
     a dead grey band under the title. */
  .team-grid-wrap { padding: 32px 0 24px; }
  .team-grid { padding-top: 0; }
}




/* 12x12, filled, and a brighter blue than the label beside it. */
.team-chevron { width: 12px; height: 12px; flex: none; fill: rgb(135, 181, 220); }


/* --- Footer button chevron + hover -------------------------------------
 * Measured on the live site: hover floods the button with the border color
 * and turns both the label and the chevron white. The chevron is the same
 * 0 0 60 60 filled mark the attorney cards use, and its rest blue
 * (135,181,220) differs from the label's (130,160,186). */
.footer-chevron { width: 12px; height: 12px; flex: none; fill: rgb(135, 181, 220); }
.footer-card-links a:hover,
.footer-card-links a:focus-visible {
  background: var(--steel);
  color: var(--paper);
}
.footer-card-links a:hover .footer-chevron,
.footer-card-links a:focus-visible .footer-chevron { fill: var(--paper); }

/* The label must not wrap now that the chevron shares the 180px box, and it
 * is clipped rather than allowed to spill: the source truncates, painting
 * "Conozca a nuestro e..." inside a 180px button on
 * /es-us/attorney-referrals rather than running the glyphs past the border.
 * min-width:0 is what lets a flex item shrink below its content width. */
.footer-card-links a > span {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  /* flex:1 gives the label the source's own 160px box -- 180 less the 2px
   * before it and the 4px gap, 12px chevron and 2px after it -- so a
   * truncated Spanish label starts where the source's does rather than
   * shrink-wrapping and centering 14px right of it. min-width:0 is what
   * allows a flex item to shrink below its content width at all. */
  flex: 1;
  min-width: 0;
}


/* ==========================================================================
   STAFF
   ========================================================================== */

/* --- The band between page content and the footer ----------------------
 * Shared, but its height is per page: 169 on /team, 225 on /staff. The text
 * sits 76px down in both. */
.page-band {
  background: var(--navy);
  height: var(--band-height, 169px);
  box-sizing: border-box;
  padding-top: 71px;
  text-align: center;
  /* Fixed height, same reasoning as .team-head: one line or it spills. */
  overflow: hidden;
}
.page-band a,
.page-band span {
  font-family: var(--display);
  font-size: 63px;
  font-style: italic;
  font-weight: 400;
  line-height: 88.2px;
  white-space: nowrap;
  color: var(--paper);
  text-decoration: none;
}

/* --- /staff -----------------------------------------------------------
 * Measured from captures/reference/dom/1440/staff.json.gz. */
.staff-head {
  background: var(--navy);
  color: var(--paper);
  text-align: center;
  height: 324px;
  box-sizing: border-box;
  padding-top: 83px;
}
/* 1.4 leading on both, as everywhere else on this page -- 119px on the title
   and 64.4 on the line under it. `line-height: 1` put the title's ink 10px
   high, and would wrap the Spanish title ("Conozca a nuestro equipo") on the
   wrong rhythm, which is the case that makes this worth stating properly
   rather than nudging the padding until English looked right.

   The negative margin is arithmetic, not a fudge. The source places these as
   two independently positioned blocks and their ink boxes overlap by 25px: an
   85px line box carries descender space that "Meet Our Team" -- which has no
   descenders -- does not use, so the words clear each other while the boxes do
   not. Stacking the two in normal flow has to give that space back. */
.staff-head h1 {
  color: var(--paper);
  font-size: 85px;
  line-height: 119px;
  margin: 0 0 -25px;
}
.staff-head-sub {
  font-family: var(--display);
  font-size: 46px;
  font-style: italic;
  font-weight: 400;
  line-height: 64.4px;
  margin: 0;
}

/* 41 above the first row, 52 below the last. */
.staff-grid-wrap { background: var(--shell); padding: 41px 0 52px; }
.staff-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  /* 285px cards on a 38px gutter, centered: four columns at 1440. */
  grid-template-columns: repeat(auto-fill, 285px);
  gap: 38px;
  justify-content: center;
}

.staff-card {
  width: 285px;
  height: 568px;
  background: var(--paper);
  overflow: hidden;
}
.staff-card-photo { width: 285px; height: 365px; object-fit: cover; display: block; }
.staff-card-body { text-align: center; }
/* Leading throughout this card was read off the wrong elements. The source
   sets 28px on the name, 22.4 on the role and 19.6 on the contact rows -- 1.4
   of the font size in all three -- against the 24/19/38 that were here. The
   ink lands in the right place at the top of the card either way, which is why
   a page-level check reported /staff exact to the pixel while every one of the
   22 cards had its contact rows 11px low. */
.staff-card-name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 20px;
  line-height: 28px;
  /* 17/0, not 19/4: the taller line boxes above absorb what those margins used
     to supply, and the four parts land on the source's 384, 411, 472 and 510. */
  margin: 17px 0 0;
  color: var(--ink);
}
.staff-card-role {
  font-size: 16px;
  line-height: 22.4px;
  margin: 0 0 18px;
  padding-bottom: 21px;
  position: relative;
  color: var(--ink);
}
/* The same 76x3 rule the attorney cards carry, in the colour this one is
   actually painted: sampled off the live page it is pure black, not the navy
   that was assumed here. The attorney card's is white, because it sits on a
   navy panel -- "the same rule" has only ever meant the same geometry.

   Positioned at 104 rather than centred. Centring 76 in the 285px card gives
   104.5 and the browser rounds it up; the source puts it at 104. Same reason
   for `bottom: -1px`, which lands it on the card's +451 instead of +450. */
.staff-card-role::after {
  content: '';
  position: absolute;
  left: 104px;
  bottom: -1px;
  width: 76px;
  height: 3px;
  background: rgb(0, 0, 0);
}
/* 19.6px of leading and a real gap between the rows, not one 38px line box
   doing both jobs. The rows sit 38px apart either way, so the pitch looked
   right; what it cost was the icon, which `align-items: center` centres
   against the line box -- at 38 it floated in the middle of a box nearly twice
   its height instead of sitting on the text. */
.staff-card-contact {
  list-style: none;
  margin: 0;
  padding: 0 0 0 25px;
  font-size: 14px;
  line-height: 19.6px;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 17px;
}
.staff-card-contact li { display: flex; align-items: center; }
.staff-card-contact a { color: var(--ink); text-decoration: none; }
.staff-card-contact a:hover { text-decoration: underline; }
/* Navy discs with white glyphs — inverted from the attorney cards, which sit
 * on navy and use white discs. */
.staff-icon { width: 21px; height: 21px; flex: none; margin-right: 6px; }

@media (max-width: 700px) {
  .staff-grid { grid-template-columns: 1fr; }
  /* 280x353, measured on the live phone build. `width: 100%` with `height:
     auto` let each photo scale to its own aspect ratio, so they ran 427 to 480
     tall against the source's flat 353 -- a different wrong number per card,
     ~100px each, on a page that carries twenty of them. The base rule's
     `object-fit: cover` still does the cropping. */
  .staff-card { width: 280px; height: auto; margin-inline: auto; }
  .staff-card-photo { width: 280px; height: 353px; }
  .staff-head { height: auto; padding: 60px 0; }
  .staff-head h1 { font-size: 46px; }
  .staff-head-sub { font-size: 28px; }
  .page-band { height: auto; padding: 40px 0; overflow: visible; }
  .page-band a, .page-band span { font-size: 32px; line-height: 1.4; white-space: normal; }
}


/* ==========================================================================
   HOMEPAGE
   ========================================================================== */

/* --- Homepage ----------------------------------------------------------
 * Measured off the live page after a full scroll. Section colors are the
 * source's own, not the site tokens: rgb(38,48,89) for the Billions band
 * against --navy rgb(35,44,83), and rgb(162,141,103) for the wins band
 * against --gold rgb(213,183,126). */

.home-hero { height: 873px; box-sizing: border-box; text-align: center; padding-top: 59px; position: relative; overflow: hidden; }
/* No scrim on this section. The fade over the group photograph's foot is
   .home-group-fade, a span in templates/pages/home.html: a second copy here
   doubled it, which ran the ramp ~20 levels dark through its middle and washed
   the photograph out above it. */
.home-lead { font-size: 20px; line-height: 24px; color: var(--navy-band); margin: 0; }
.home-phone { display: block; position: relative; text-decoration: none; margin: 23px 0 0; }
/* The SVG carries the white card (a rounded rect, 18px radius once scaled);
 * the shadow under it is not in the file, so it is applied here. */
.home-phone img {
  width: 836px;
  height: 118px;
  margin: 0 auto;
  display: block;
  /* The source's own values, read out of its SVG filter rather than guessed:
     feGaussianBlur stdDeviation="17", feOffset dx="6" dy="6", and an alpha of
     0.6 in the colour matrix. An SVG deviation is half a CSS blur radius, so
     17 is 34px here. Ours was 0 4px 12px at 16%, which barely painted. */
  filter: drop-shadow(6px 6px 34px rgb(0 0 0 / 60%));
}
/* The label overlays the card rather than following it. The source paints it in
 * a 115x20.6 mesh block whose top sits 97px below the card's top, so with a
 * 118px card its last 21px fall inside the card's bottom edge, tight under the
 * number. Measured on hkqlaw.com at 1440 and 980: card y=333 h=118, label block
 * y=430 w=115, painted text x=681.2/451.2 w=70.7 at 10px/19.6.
 * The block's left edge is 61px left of the canvas center at both widths --
 * centering it instead put the text 4px right of the source's.
 * 98 rather than the source's 97 because the source's block is 20.6 tall
 * against our 19.6 line box, so the glyphs sit a pixel lower inside it; 98
 * lands the painted text on the source's y=434 at both widths. */
.home-phone-note {
  display: block;
  position: absolute;
  top: 98px;
  left: calc(50% - 61px);
  width: 115px;
  font-size: 10px;
  line-height: 19.6px;
  letter-spacing: .1em;
  color: var(--navy-band);
  text-decoration: underline;
}
/* 32px of leading, measured: the source wraps this to two lines and sets them
   32 apart where 24 was here. The phone rule below carries its own 20.8 and is
   unaffected. Never compared until now, because the source splits the line into
   two spans and we do not, so check_metrics reported it as one MISSING and one
   EXTRA run rather than pairing it -- see rule 20.
   These two lines share one 629px mesh block on the source, at x=426 of 1440
   and x=196 of 980 -- 20.5px right of the canvas center rather than centered on
   it, which left both of them 20px left of the source's; calc(50% - 294px)
   reproduces both widths. The 37px above is the source's own margin-bottom on
   the Click to Call block, which ends level with the card at 450.6/451, and
   there is no margin between the two paragraphs: the strapline's line box runs
   488-520 and the sub-line's opens at 520, its 35.2px of leading putting the
   glyphs at the source's y=524. */
.home-strapline {
  width: 629px;
  margin: 37px 0 0 calc(50% - 294px);
  font-size: 20px;
  line-height: 32px;
  font-weight: 700;
  color: var(--navy-band);
}
.home-substrap {
  width: 629px;
  margin: 0 0 0 calc(50% - 294px);
  font-size: 22px;
  line-height: 35.2px;
  letter-spacing: .1em;
  color: var(--navy-band);
}
.home-cta { margin: 24px 0 0; }
/* 374x62 with an 8px radius, measured off the element. */
.home-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 374px;
  height: 62px;
  background: var(--navy-band);
  color: var(--paper);
  border-radius: 8px;
  font-family: 'Nunito Sans', Helvetica, Arial, sans-serif;
  font-size: 16px;
  font-weight: 700;
  line-height: 19px;
  letter-spacing: .1em;
  text-decoration: none;
  /* Wix's --shd on this button, read off the live element:
     `rgba(0,0,0,.54) 0 0 22px 1px`. No gate here reads box-shadow except
     tools/style_diff.py, which is why it went unnoticed. */
  box-shadow: 0 0 22px 1px rgb(0 0 0 / 54%);
  transition: background-color .2s ease;
}
/* Both buttons darken to the same blue on hover, from different resting
   colors -- navy for the hero one, steel for "Get help now". */
.home-btn:hover,
.home-btn:focus-visible { background: var(--btn-blue-hover); }

.home-btn-light {
  background: var(--btn-blue);
  /* The steel "Get help now" button computes `box-shadow: none` on the live
     page; only the navy hero button carries one. */
  box-shadow: none;
  width: 241px;
  height: 40px;
  /* 8px, as on every other button here. This was 0. */
  border-radius: 8px;
  font-size: 12px;
  line-height: 14px;
}
/* `cover`, not `contain`. Wix asks its CDN for fill/w_1113,h_438,al_c, which
   scales to cover and center-crops; `contain` letterboxed our 1800x834 export
   inside the 2.541 box and rendered the group only 945px wide, which read as
   the photograph being too small. */
.home-group { width: 1113px; height: 438px; object-fit: cover; object-position: center; margin: 22px auto 0; display: block; }

/* The source paints this over the bottom of the group photograph as a separate
   full-bleed SVG rect, not as part of the image -- the PNG is a transparent
   cutout. Negative margin rather than absolute positioning so it anchors to the
   photo's own bottom edge and contributes no height. */
.home-group-fade {
  display: block;
  width: 100%;
  height: 300px;
  margin-top: -300px;
  position: relative;
  z-index: 1;
  pointer-events: none;
  /* Stopped every 10% because the source is an SVG gradient and SVG
     interpolates straight alpha where CSS gradients premultiply. Two stops
     alone ran the ramp up to 20 points dark through its middle. Each stop is
     the straight-alpha value at that point: color lerped #D9D9D9 -> #86AFCC,
     alpha equal to the position. */
  background: linear-gradient(to bottom,
    rgba(217, 217, 217, 0),
    rgba(209, 213, 216, .1) 10%,
    rgba(200, 209, 214, .2) 20%,
    rgba(192, 204, 213, .3) 30%,
    rgba(184, 200, 212, .4) 40%,
    rgba(176, 196, 211, .5) 50%,
    rgba(167, 192, 209, .6) 60%,
    rgba(159, 188, 208, .7) 70%,
    rgba(151, 183, 207, .8) 80%,
    rgba(142, 179, 205, .9) 90%,
    #86AFCC);
}
/* Pinned to the viewport, not to the hero: the source keeps this in the
   bottom-right corner at every scroll position, at 50px from both edges and
   at every viewport size. Homepage only -- it is not on /team or /contact. */
.home-contact-dot {
  position: fixed;
  right: 50px;
  bottom: 50px;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 62px;
  height: 62px;
  border-radius: 200px;
  background: rgb(255, 255, 255);
  transition: background-color .2s;
}
.home-contact-dot svg { width: 29px; height: 29px; fill: rgb(4, 19, 58); transition: fill .2s; }
.home-contact-dot:hover, .home-contact-dot:focus-visible { background: rgb(11, 47, 91); }
.home-contact-dot:hover svg, .home-contact-dot:focus-visible svg { fill: rgb(255, 255, 255); }

/* rgb(38,48,89), not var(--navy). The site uses two navies and this band is
   the lighter one; only the footer's legal strip is the #232C53 that --navy
   holds. Measured, because the two are three points apart and indistinguishable
   by eye. */
.home-motto { background: var(--navy-band); color: var(--paper); height: 108px; box-sizing: border-box; padding-top: 28px; }
/* Assistant, not Montserrat, and 40px rather than 24. The text is
   left-aligned inside a 693px box that is itself centered, which is why it
   starts at x=373 and does not look centered on the page. */
.home-motto p {
  width: 693px;
  margin: 0 auto;
  text-align: left;
  font-family: 'Assistant', Helvetica, Arial, sans-serif;
  font-weight: 300;
  font-size: 40px;
  line-height: normal;
  /* The source tracks this line out by 0.05em -- 2px against the desktop
     40px, 0.95px against the phone build's 19. Hardcoding the 2px was right on
     desktop and ran the phone line 24px wide of the source. */
  letter-spacing: 0.05em;
}
.home-motto p strong { font-weight: 600; }

/* Black, with the archive photograph behind the copy. */
.home-story {
  height: 519px;
  box-sizing: border-box;
  position: relative;
  /* The archive photograph behind the copy. The source paints it on its own
     layer at 69% opacity over black, which is what darkens it -- painting it
     straight onto the section, as we did, gives the photograph at full
     strength and a visibly lighter band.

     Natural size, not `cover`: the source crops a 1440x519 window out of the
     1706x648 original at 1:1 (its computed background-size is `auto`), so
     centering at natural size reproduces Wix's crop offset (x_133, y_65). */
  background: var(--ink);
  color: var(--paper);
  overflow: hidden;
}
.home-story::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--story-photo) center / auto no-repeat;
  opacity: .69;
}
.home-story-inner { position: relative; max-width: 1440px; margin: 0 auto; padding: 104px 277px 0 748px; text-align: right; }
.home-story h2 {
  font-family: var(--body);
  font-size: 56px;
  font-weight: 700;
  line-height: 1;
  color: rgb(163, 217, 246);
  text-decoration: underline;
  margin: 0 0 21px;
}
.home-story p { font-size: 18px; line-height: 32.4px; margin: 0; }
.home-story-more { margin: 30px 0 0 !important; }
.home-story-more a { font-family: var(--helv); font-size: 45px; font-weight: 700; letter-spacing: .01em; color: var(--btn-blue); text-decoration: underline; }

.home-billions {
  background: var(--navy-band);
  color: var(--paper);
  text-align: center;
  height: 518px;
  box-sizing: border-box;
  padding-top: 57px;
}
.home-billions-mark { width: 923px; height: 76px; margin: 0 auto; display: block; }
.home-tagline { font-size: 18px; line-height: 32.4px; font-weight: 700; margin: 43px 0 0; }
.home-tagline-rule {
  width: 184px;
  height: 7px;
  box-sizing: border-box;
  margin: 0 auto;
  border: 0;
  border-top: 1px solid var(--shell);
}
.home-billions-body { font-size: 18px; line-height: 32.4px; max-width: 816px; margin: 37px auto 0; }
.home-billions p:last-child { margin: 54px 0 0; }

/* The "Our Recent Wins" band. Every number here is measured off the live
   homepage at 1440 (captures/reference/), where the band sits at y=2245 with a
   fixed 309px height and six centered rows at these offsets from its top:
   label 40, rule 80, amount 105, arrows 137, detail 193, dots 254. */
.home-wins { height: 309px; background: var(--paper); }
/* The band fades as one piece — arrows and dots included — so the gold lives
   on the inner element and the section behind it is the white it passes
   through. A cross-fade between two stacked slides would not look the same. */
.home-wins-inner {
  position: relative;
  height: 100%;
  box-sizing: border-box;
  padding-top: 40px;
  background: rgb(162, 141, 103);
  color: var(--paper);
  text-align: center;
  opacity: 1;
  transition: opacity 233ms linear;
}
.home-wins.is-fading .home-wins-inner { opacity: 0; }

.home-wins-label { font-size: 16px; line-height: 19px; margin: 0; }
.home-wins-rule {
  width: 36px;
  height: 5px;
  box-sizing: border-box;
  margin: 21px auto 0;
  border: 0;
  border-top: 1px solid var(--paper);
}
/* Not Montserrat. Wix nests four spans here and the innermost overrides the
   family to helvetica-w01-bold — Monotype's Helvetica W01 Bold, which we
   cannot self-host. Helvetica and Arial are metrically compatible with it:
   all three measure the amount string at exactly 548px, so this substitutes
   without moving a pixel, on any platform. */
.home-win-amount {
  font-family: Helvetica, Arial, sans-serif;
  font-weight: 700;
  font-size: 50px;
  line-height: 65px;
  margin: 20px 0 0;
}
.home-win-detail { font-size: 18px; line-height: 22px; margin: 23px 0 0; }

.home-wins-arrow {
  position: absolute;
  top: 137px;
  width: 16px;
  height: 34px;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
}
.home-wins-arrow svg { display: block; width: 16px; height: auto; fill: var(--paper); stroke: var(--paper); }
.home-wins-prev { left: 100px; }
/* One chevron path, mirrored — which is exactly what the source does. */
.home-wins-next { right: 100px; transform: scaleX(-1); }

.home-wins-dots { position: absolute; top: 254px; left: 0; right: 0; }
.home-wins-dots ol {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 9px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.home-wins-dots li { padding: 0 8px; line-height: 0; }
.home-wins-dots button {
  display: block;
  width: 6px;
  height: 6px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--paper);
  cursor: pointer;
}
/* The current slide is a hollow ring two pixels wider, not a brighter dot. */
.home-wins-dots li[aria-current="true"] button {
  width: 9px;
  height: 9px;
  box-sizing: border-box;
  background: none;
  border: 2px solid var(--paper);
}
.home-wins-data { display: none; }

.home-practice-band { background: var(--steel); color: var(--paper); text-align: center; height: 110px; box-sizing: border-box; padding-top: 28px; overflow: hidden; }
.home-practice-band h2 {
  color: var(--paper);
  font-family: var(--helv);
  font-weight: 300;
  font-size: 40px;
  line-height: 48px;
  margin: 0;
  /* Same shrink-and-fade as the motto, but NOT about the page center. The
     source scales a 513px box starting at x=541, which puts its origin at
     797.5 -- 77.5px right of center -- so the heading drifts further left on
     the way in than a centered scale would take it. The motto's wrapper is
     genuinely centered (719.5), which is why only this one needs the offset. */
  transform-origin: calc(50% + 77.5px) 50%;
}

/* The three blocks alternate text/photograph, on a pale blue wash. */
/* Fixed height and per-row heights: the source spaces these three blocks
 * unevenly (images at 97, 432 and 890 into the section) because Wix
 * positions them absolutely, so a uniform gap cannot reproduce it. */
.home-practice {
  /* Runs bottom-up: white at the top of the section deepening to blue at the
     bottom. Copied from the source's own declaration -- ours previously ran the
     other way, blue fading to white, which left the section reading as plain
     white where the source is most saturated. */
  background: linear-gradient(0deg, rgb(201, 233, 255) 0.877193%, rgb(255, 255, 255) 100%);
  height: 1285px;
  box-sizing: border-box;
  padding: 97px 0 0;
}
/* Column widths and gutter come from the row, not from here: the source's
   three rows do not share a grid. Centered, because the section as a whole
   tracks the viewport the way the rest of the page does. */
.home-practice-row {
  display: grid;
  grid-template-columns: var(--text-w) var(--photo-w);
  gap: 0 var(--col-gap);
  justify-content: center;
  align-items: start;
  margin: 0;
  position: relative;
  left: var(--row-offset, 0);
}
.home-practice-row-flip { grid-template-columns: var(--photo-w) var(--text-w); }
.home-practice-row:nth-of-type(1) { height: 335px; }
.home-practice-row:nth-of-type(2) { height: 458px; }
.home-practice-row-flip .home-practice-text { order: 2; }
.home-practice-row-flip .home-practice-media { order: 1; }
.home-practice-media { position: relative; }
.home-practice-media > img { display: block; width: 100%; height: auto; }
/* The icon sits above the heading, left-aligned with it, and its top lines up
   with the top of the row's photograph. */
.home-practice-icon {
  display: block;
  margin: var(--icon-top, 0) 0 var(--icon-gap, 8px);
}
.home-practice-text h3 { font-size: 28px; line-height: 34px; font-weight: 400; color: var(--navy-band); margin: 0 0 var(--heading-gap, 16px); }
.home-practice-text p { font-size: 14px; line-height: 21px; margin: 0 0 22px; }
/* The first block's paragraph is not set like the other two. The source paints
   it in helvetica-w01-roman at 16/22.4 on BOTH builds, and blocks two and three
   in montserrat at 14 (desktop) and 15 (phone). One rule for all three agreed
   with two of them, which is how it read as settled -- rule 2 of
   .claude/rules/parity-measurement.md, on a component with three instances. */
.home-practice-row:nth-of-type(1) .home-practice-text p {
  font-family: var(--helv);
  font-size: 16px;
  /* 22.07, the leading the source's ten lines actually measure (221). */
  line-height: 22.07px;
}
/* Laid over the photograph, in the light steel blue with a hard offset shadow
   -- not the navy rectangle in the text column that was here before. Position
   comes from the row's own --btn-x/y/w, because the source places each of the
   three differently: two overlap the lower part of their photograph and the
   third clears it entirely. */
.home-practice-btn {
  position: absolute;
  left: var(--btn-x);
  top: var(--btn-y);
  width: var(--btn-w);
  height: 40px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Nunito Sans', Helvetica, Arial, sans-serif;
  background: var(--btn-blue);
  color: var(--paper);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .1em;
  line-height: 11px;
  border-radius: 8px;
  box-shadow: 3px 3px 2px 0 rgb(0, 0, 0);
  text-decoration: none;
  transition: background-color .2s ease;
}
/* Darkens on hover; the label, shadow and radius do not change. */
.home-practice-btn:hover,
.home-practice-btn:focus-visible {
  background: var(--btn-blue-hover);
}

.home-form { position: relative; text-align: center; padding: 90px 0 0; }
/* Navy, not the body ink. The heading, its rule and the line beneath it are
   all rgb(38,48,89); only the form fields below them are black. */
.home-form h2 { font-family: var(--body); font-size: 38px; line-height: 46px; font-weight: 400; letter-spacing: .01em; color: var(--navy-band); margin: 0; }
.home-form-rule {
  width: 284px;
  height: 7px;
  box-sizing: border-box;
  margin: 6px auto 0;
  border: 0;
  border-top: 3px solid var(--navy-band);
}
.home-form h2 span { font-weight: 700; }
.home-form-sub { font-family: var(--helv); font-weight: 300; font-size: 25px; line-height: 30px; letter-spacing: .01em; color: var(--navy-band); margin: 13px 0 0; }
.home-form-sub strong { font-weight: 700; }
/* The homepage embed is 980x1202; /contact's is a different height, so this
 * is scoped rather than changed in the shared partial. */
.home-form { height: 1495px; box-sizing: border-box; }
.home-form .intake-form { max-width: 980px; margin: 34px auto 0; }
.home-form .intake-form iframe { min-height: 1202px; height: 1202px; }
/* The form section's language selector sits over the lower part of the embed,
   which is blank space. Absolute, because that is how the source places it and
   the only way to reach the measured y without padding the section out. */
.home-form .locale-select {
  position: absolute;
  top: 1081px;
  left: 50%;
  margin-left: -56px;
  width: 112px;
  height: 48px;
}
.home-form .visually-hidden { position: absolute; }

.home-call { background: var(--navy-band); color: var(--paper); text-align: center; height: 533px; box-sizing: border-box; padding-top: 113px; overflow: hidden; }
.home-call h2 {
  color: var(--paper);
  font-family: var(--helv);
  font-weight: 300;
  font-size: 40px;
  line-height: 48px;
  letter-spacing: .01em;
  margin: 0;
  /* Off-center scale origin, as on the practice heading: the source's wrapper
     for this line is a 658px box at x=427, putting its origin 36px right of
     the page center. The lockup, phone number and icons below it are all
     genuinely centered, so the offset belongs only here. */
  transform-origin: calc(50% + 36px) 50%;
}
.home-call h2 strong { font-weight: 700; }
.home-call-number { margin: 81px 0 0; }
.home-call-number img { width: 887px; height: 101px; margin: 0 auto; display: block; }
.home-call-phone { font-size: 43px; line-height: 60.2px; margin: 21px 0 0; }
.home-call-phone a { color: var(--paper); text-decoration: none; }
.home-social { list-style: none; display: flex; justify-content: center; gap: 10px; margin: 25px 0 0; padding: 0; }
.home-social img { width: 39px; height: 39px; display: block; }

/* 979, not 1100. The source holds its 980 layout all the way down to 980 --
   that width is its tablet canvas, and every tablet gets the desktop build
   there -- so reflowing above 980 diverges from it on every tablet. Below 980
   there is no source behavior to match: it just scrolls sideways, and phones
   never see this because they get the 320 canvas instead. */
/* 400, not 979: the desktop build now holds a 980 canvas at any window (the
   min-width on body), so a viewport media query at 979 fires while the canvas
   is still 980 and paints this narrow layout 980px wide -- the homepage's
   practice photographs drew 980x611 at a 780 window against the source's
   395x246. The phone build sets `<meta name="viewport" content="width=320">`
   in templates/base.html and the tablet sets 980, so 400 selects the phone
   canvas alone, which is the only one these rules were reaching. */
@media (max-width: 400px) {
  .home-hero { height: auto; padding-bottom: 40px; }
  /* Fixed-pixel artwork, all of it wider than a phone: the hero phone card,
     the team group shot, the "Billions Won." lockup and the call band's
     1-888-HKQ-LAW1 lockup at 887px, which was bleeding off both edges. */
  .home-phone img,
  .home-group,
  .home-billions-mark,
  .home-call-number img { width: 100%; height: auto; }
  .home-story { height: auto; }
  .home-story-inner { padding: 60px var(--s-4); }
  .home-billions, .home-wins, .home-call { height: auto; padding-bottom: 50px; }
  /* --row-offset is the block's recorded horizontal nudge inside the desktop
     grid. Once the row is a single column there is no grid to nudge within,
     and carrying it just pulled every practice row 5px off the left edge. */
  .home-practice-row { grid-template-columns: 1fr; gap: 20px; left: 0; }
  .home-practice-row-flip .home-practice-text,
  .home-practice-row-flip img { order: initial; }

  /* Three fixed widths this block never covered, and together they held the
     homepage document 693px wide at the 320 phone canvas. That does not show
     up as a clipped edge: the page declares its own layout viewport, so the
     browser shrinks the whole document to fit the overflow on screen and the
     entire homepage renders at about half scale with dead space beside it.

     The motto's 693px box is the widest of them. It is a real measurement --
     the line is left-aligned inside a centered 693px box, which is what puts
     it at x=373 on desktop -- but there is nothing to center it in here. */
  /* Every band on this page is a fixed-height box holding absolutely placed
     content, because that is how the source builds it and how it was measured.
     Four of those heights were released above; these are the rest, and leaving
     them was not a cosmetic problem -- content taller than its box simply
     carried on into the band below it, so the practice rows painted their
     headings and buttons across the next row's photograph.

     `.home-practice-band` additionally clips, so "Our Practice Areas" lost its
     second line entirely rather than overflowing visibly. */
  .home-practice-band { height: auto; padding-bottom: 28px; overflow: visible; }
  .home-practice { height: auto; }
  .home-practice-row:nth-of-type(1),
  .home-practice-row:nth-of-type(2) { height: auto; }
  .home-form { height: auto; }
  .home-wins-inner { height: auto; padding-bottom: 40px; }

  /* The carousel's controls are placed from the band's fixed geometry -- the
     arrows 137px down and 100px in, the dots at 254px. Once the amount and its
     caption wrap, all three sit on top of the text. The arrows go to the
     vertical middle at the edges and the dots return to the flow. */
  .home-wins-arrow { top: 50%; transform: translateY(-50%); }
  .home-wins-prev { left: 8px; }
  .home-wins-next { right: 8px; transform: translateY(-50%) scaleX(-1); }
  .home-wins-dots { position: static; margin-top: 24px; }

  .home-motto { height: auto; padding-bottom: 28px; }
  .home-motto p { width: auto; }
  .home-btn { width: 100%; max-width: 374px; }
  /* The practice-row button is absolutely placed from recorded coordinates
     (--btn-x/--btn-y/--btn-w). Those are desktop positions and put it past the
     right edge here, so it returns to the flow under its own copy. */
  .home-practice-btn {
    position: static;
    width: 100%;
    max-width: var(--btn-w);
    margin-top: 20px;
  }
}


/* --- Entrance motion -------------------------------------------------------
   Wix animates elements in as they are scrolled to. The values here are fitted
   to a frame-by-frame capture of the live hero photograph: it starts at 80%
   scale, 120px low and fully transparent, and settles over roughly two seconds
   on an ease-in-out curve. Opacity finishes earlier than the transform, which
   is why the two are timed separately rather than sharing one transition.

   Only the hero carries this so far. The homepage has 41 animated elements in
   at least three effects (this one, a clip-path wipe on the wins band, and a
   rotate-X flip on the vector lockups); the rest are not measured yet. */
[data-reveal='rise'] {
  opacity: 0;
  transform: translateY(120px) scale(.8);
  transition: transform 2000ms cubic-bezier(.5, 0, .5, 1),
              opacity 2030ms cubic-bezier(.88, 0, .35, 1);
}
[data-reveal='rise'].is-revealed {
  opacity: 1;
  transform: none;
}

/* Someone who has asked their system for less motion gets the settled state
   with no animation. This is a deliberate departure from the source, which
   plays the animation regardless.

   Every property any effect below starts from has to be reset here, not just
   transform and opacity: `shrink` and `drop` start from a `scale`, `wink` from
   a `clip-path`, `fade-late` from a `filter`. Resetting only two of them left
   those elements parked in their start state with no animation to leave it. */
@media (prefers-reduced-motion: reduce) {
  [data-reveal] {
    transition: none;
    animation: none;
    opacity: 1;
    transform: none;
    scale: 1;
    clip-path: none;
    filter: none;
  }
}

/* The story band. "Our Story." slides in horizontally with no fade; the
   paragraph and the chevron fade with no movement. All three start together.
   Measured off the live page frame by frame.

   The heading starts flush against the right edge of the viewport. That
   distance is not a constant -- the source's content column is centered, so it
   grows with the window -- and `50vw - 139px` is the same offset expressed
   relative to the viewport, which is 580.7px at 1440 and stays correct
   elsewhere. */
[data-reveal='slide-right'] {
  transform: translateX(calc(50vw - 139px));
  transition: transform 1150ms cubic-bezier(.5, 0, .5, 1);
}
[data-reveal='slide-right'].is-revealed { transform: none; }

[data-reveal='fade'] {
  opacity: 0;
  transition: opacity 1224ms cubic-bezier(.33, 0, .67, 1);
}
[data-reveal='fade'].is-revealed { opacity: 1; }

/* Half a rise: 60px and no scale, fading as it travels. Measured on
   /our-story's opening sentence, where both properties reach 15.2% a quarter
   of the way through, 51.4% at half and 85.9% at three quarters -- a symmetric
   ease, and the same one for the movement as for the fade. 1238ms is the
   duration; 1146 of it is the part you can see it moving. */
[data-reveal='lift'] {
  opacity: 0;
  transform: translateY(60px);
  transition: transform 1221ms cubic-bezier(.5, 0, .5, 1),
              opacity 1221ms cubic-bezier(.5, 0, .5, 1);
}
[data-reveal='lift'].is-revealed {
  opacity: 1;
  transform: none;
}

/* The motto band starts 20% oversized and shrinks as it fades. Wix drives this
   with the standalone `scale` property rather than `transform`, which is why a
   transform-only reading of the page reports no scale at all -- worth knowing
   before concluding any of these are simple fades.

   scale and opacity carry different curves: the fade is front-loaded (43% in
   the first quarter) while the shrink is a symmetric ease-in-out, so they get
   separate transitions rather than one shared timing. Scaling is about the
   box's center, which is the default and matches the source. */
[data-reveal='shrink'] {
  scale: 1.2;
  opacity: 0;
  transition: scale 1120ms cubic-bezier(.5, 0, .5, 1),
              opacity 985ms cubic-bezier(0, 0, .45, 1);
}
[data-reveal='shrink'].is-revealed { scale: 1; opacity: 1; }

/* The "BILLIONS WON." lockup flips up on a hinge: perspective(800px) with
   rotateX running from -90deg to flat. The 800px is not a guess -- it falls
   out of the live matrix3d, whose two perspective terms satisfy
   sin^2 + cos^2 = 1 only at exactly 800. The rotation overshoots about 8% past
   flat and settles back, hence the >1 control point. */
[data-reveal='flip'] {
  /* Hinged on the TOP edge, not the center of the box. This is the difference
     between "close enough" and correct: with the default center origin the
     lockup drifts 38px vertically while it opens and starts 46px too wide,
     because perspective magnifies the half swinging toward the viewer.

     Hinging on the top edge reproduces the live geometry exactly -- projected
     height and bounding width match to 0.1px at every angle sampled. Wix gets
     there by baking a compensating translate into its matrix; setting the
     origin says the same thing in one line. */
  transform-origin: 50% 0;
  transform: perspective(800px) rotateX(-90deg);
  opacity: 0;
  transition: transform 1187ms cubic-bezier(.23, 1.3, .47, 1.09),
              opacity 1145ms cubic-bezier(0, 0, .45, 1);
}
[data-reveal='flip'].is-revealed {
  transform: perspective(800px) rotateX(0deg);
  opacity: 1;
}

/* The body copy under the tagline starts ~850ms after everything else in the
   band. The delay is the effect -- without it the whole band arrives at once.

   The source pairs its fade with motion-blurIn, a 6px blur running 2000ms on
   the same 800ms delay. Reading opacity alone missed it, because a blur does
   not move the box or change its computed opacity. */
[data-reveal='fade-late'] {
  opacity: 0;
  filter: blur(6px);
  transition: opacity 1400ms cubic-bezier(.5, 0, .8, 1) 850ms,
              filter 2000ms cubic-bezier(.47, 0, .74, .71) 800ms;
}
[data-reveal='fade-late'].is-revealed { opacity: 1; filter: blur(0); }

/* The rule under the tagline wipes in as twelve vertical slats, each starting
   at an 8% interval and growing at its own rate, which cascades left to right.
   Both polygons are read off the live element; the end values are nudged up so
   neighbouring slats overlap and leave no hairline gaps once settled. */
[data-reveal='wipe'] { clip-path: polygon(0% 0%, 0% 100%, 0% 100%, 0% 0%, 8% 0%, 8% 100%, 8% 100%, 8% 0%, 16% 0%, 16% 100%, 16% 100%, 16% 0%, 25% 0%, 25% 100%, 25% 100%, 25% 0%, 33% 0%, 33% 100%, 33% 100%, 33% 0%, 41% 0%, 41% 100%, 41% 100%, 41% 0%, 50% 0%, 50% 100%, 50% 100%, 50% 0%, 58% 0%, 58% 100%, 58% 100%, 58% 0%, 66% 0%, 66% 100%, 66% 100%, 66% 0%, 75% 0%, 75% 100%, 75% 100%, 75% 0%, 83% 0%, 83% 100%, 83% 100%, 83% 0%, 91% 0%, 91% 100%, 91% 100%, 91% 0%); }
[data-reveal='wipe'].is-revealed {
  animation: slat-wipe 1175ms cubic-bezier(.33, 0, .67, 1) forwards;
}
/* The hero's Contact Us button, the call band's number and the social row.
   Same shape as `shrink` but starting from 1.6 rather than 1.2, which is the
   source's --motion-scale on those components (motion-dropIn, 1200ms, paired
   with a 960ms motion-fadeIn). */
[data-reveal='drop'] {
  scale: 1.6;
  opacity: 0;
  transition: scale 1200ms cubic-bezier(.25, .46, .45, .94),
              opacity 960ms cubic-bezier(.25, .46, .45, .94);
}
[data-reveal='drop'].is-revealed { scale: 1; opacity: 1; }

/* The wins band. Three of the source's effects land on one element:
   motion-winkInClip opens a clip-path from a hairline at the vertical center,
   motion-winkInRotate scales it from flat to full height, and motion-fadeIn
   runs alongside -- 1200ms, 1020ms and 1200ms respectively. */
[data-reveal='wink'] {
  clip-path: polygon(0% 50%, 100% 50%, 100% 50%, 0% 50%);
  transform: scaleY(0);
  opacity: 0;
  transition: clip-path 1200ms cubic-bezier(.86, 0, .07, 1),
              transform 1020ms cubic-bezier(.86, 0, .07, 1),
              opacity 1200ms cubic-bezier(.25, .46, .45, .94);
}
[data-reveal='wink'].is-revealed {
  clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
  transform: scaleY(1);
  opacity: 1;
}

/* The source staggers the hero rather than starting it all at once: the phone
   card and its label wait 1s behind the lead, and the button 1.2s. The delay
   is part of the effect, so it is declared once here rather than duplicated
   into every effect that needs one. */
[data-reveal][data-reveal-delay='1000'] { transition-delay: 1000ms; }
[data-reveal][data-reveal-delay='1200'] { transition-delay: 1200ms; }

@keyframes slat-wipe {
  from { clip-path: polygon(0% 0%, 0% 100%, 0% 100%, 0% 0%, 8% 0%, 8% 100%, 8% 100%, 8% 0%, 16% 0%, 16% 100%, 16% 100%, 16% 0%, 25% 0%, 25% 100%, 25% 100%, 25% 0%, 33% 0%, 33% 100%, 33% 100%, 33% 0%, 41% 0%, 41% 100%, 41% 100%, 41% 0%, 50% 0%, 50% 100%, 50% 100%, 50% 0%, 58% 0%, 58% 100%, 58% 100%, 58% 0%, 66% 0%, 66% 100%, 66% 100%, 66% 0%, 75% 0%, 75% 100%, 75% 100%, 75% 0%, 83% 0%, 83% 100%, 83% 100%, 83% 0%, 91% 0%, 91% 100%, 91% 100%, 91% 0%); }
  to   { clip-path: polygon(0% 0%, 0% 100%, 8.5% 100%, 8.5% 0%, 8% 0%, 8% 100%, 18.5% 100%, 18.5% 0%, 16% 0%, 16% 100%, 29.5% 100%, 29.5% 0%, 25% 0%, 25% 100%, 41.5% 100%, 41.5% 0%, 33% 0%, 33% 100%, 55.5% 100%, 55.5% 0%, 41% 0%, 41% 100%, 70.5% 100%, 70.5% 0%, 50% 0%, 50% 100%, 87.5% 100%, 87.5% 0%, 58% 0%, 58% 100%, 105.5% 100%, 105.5% 0%, 66% 0%, 66% 100%, 124.5% 100%, 124.5% 0%, 75% 0%, 75% 100%, 145.5% 100%, 145.5% 0%, 83% 0%, 83% 100%, 168.5% 100%, 168.5% 0%, 91% 0%, 91% 100%, 191% 100%, 191% 0%); }
}


/* ==========================================================================
   PRACTICE HUBS — /personal-injury, /business-law, /estate-and-trusts
   ========================================================================== */

/* The banner video runs 490px tall starting 144px behind the header, so only
   its lower 346px is ever visible. Reproducing that offset rather than just
   cropping to 346 keeps the same part of the frame on screen as the source. */
.hub-hero {
  position: relative;
  height: 346px;
  overflow: hidden;
  background: var(--navy);
  display: flex;
  align-items: flex-start;
  justify-content: center;
}
.hub-hero-video {
  position: absolute;
  /* The clip is a 490px band starting 147px above this one, the same shape the
     practice banners use for their photograph. */
  top: -147px;
  left: 0;
  width: 100%;
  height: 490px;
  object-fit: cover;
  /* Anchored to the top of the frame, not its middle. The source crops it that
     way, and centring it showed a visibly different part of the clip -- the
     same mistake the banner photographs had. */
  object-position: 50% 0%;
  /* 0.3 over navy is the whole treatment -- the clip is barely there. */
  opacity: .3;
  pointer-events: none;
}
.hub-hero h1 {
  position: relative;
  margin: 120px 0 0;
  font-family: var(--display);
  font-size: 66px;
  line-height: 89.6px;
  font-weight: 700;
  color: var(--paper);
  text-align: center;
}

.hub-inner { width: 980px; margin: 0 auto; }

/* 91px, not 104: measured against the source's hook baseline at y=665. */
.hub-intro { padding: var(--hook-gap-above, 91px) 0 0; }
.hub-hook {
  font-family: var(--display);
  /* Size comes from the page (see PracticeHub.hook_size); the ratio does not.
     1.2 is Wix's default leading and holds at both 44px and 48px -- pinning the
     line-height to the font size cost 8.8px of height on the 44px hubs. */
  font-size: 48px;
  line-height: 1.2;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 50px;
}
.hub-intro p { font-size: 16px; line-height: 28.8px; margin: 0; }

/* Outlined, not filled: 2px steel with steel text, squared off, filling on
   hover. Same control on all three bands, only the width differs. */
.hub-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 186px;
  height: 40px;
  margin-top: 35px;
  padding: 0 14px;
  box-sizing: border-box;
  border: 2px solid var(--steel);
  border-radius: 0;
  background: none;
  color: var(--steel);
  font-family: var(--body);
  font-size: 14px;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
  text-decoration: none;
  gap: 5px;
  transition: background-color .2s ease, color .2s ease;
}
/* Every one of these buttons carries a chevron after its label, in a lighter
   blue than the border. */
.hub-btn-chevron { width: 12px; height: 12px; flex: none; fill: rgb(135, 181, 220); }
.hub-btn:hover .hub-btn-chevron,
.hub-btn:focus-visible .hub-btn-chevron { fill: var(--paper); }
.hub-btn-wide { min-width: 360px; }
/* The intro band's button sits a pixel lower than the shared 35px default. */
.hub-intro .hub-btn { margin-top: 36px; }
/* The gap above the button is not the same in all three bands on the source. */
.hub-results-panel .hub-btn { margin-top: 28px; }
.hub-closing .hub-btn { margin-top: 25px; }
.hub-btn:hover,
.hub-btn:focus-visible { background: var(--steel); color: var(--paper); }

/* The practice-area panel button, outlined in white rather than steel because
   it sits on navy. It is also roomier -- 25px of side padding against 14, and
   3px between label and chevron against 5, which is 20px of extra width on the
   same label. Measured off the live panel button; do not fold these back into
   .hub-btn, the homepage buttons really are the tighter shape.

   This has to come after .hub-btn. Both are single-class selectors, so source
   order decides, and while it sat up in the practice section every override
   here was discarded. */
/* Width per page, like the closing button's -- as a floor, not a fixed size.
   The source hand-sets 272px and its label fits because Avenir is narrower
   than the Montserrat we substitute for it. Pinning `width` to that number
   wrapped the label onto a second line on fourteen pages, which is worse than
   a button a few pixels wide of the source. It matches exactly wherever the
   label fits and grows only where the face forces it. */
.hub-btn-onnavy { min-width: var(--types-cta-width, auto); }
.hub-btn-onnavy {
  border-color: var(--paper);
  color: var(--paper);
  /* The source fills this navy rather than leaving it transparent over the
     navy panel. Identical while the panel is directly behind it, and not
     identical the moment anything else is. */
  background: var(--navy-deep);
  margin-top: 23px;
  /* None, as the source has none: its width is the hand-set number and the
     label centres inside it. 25px either side acted as a floor on the content,
     so any label over about 210px pushed the button past its recorded width --
     327 against the source's 291 on /construction-accidents. */
  padding: 0;
  gap: 3px;
}
.hub-btn-onnavy .hub-btn-chevron { fill: var(--paper); }
/* Measured on the live panel button with the pointer over it: the fill goes
   steel, the border follows it (so it still reads borderless), and the label
   and chevron stay the paper white they already are -- the source's label is
   its own element with a fixed white color, not one that inherits the
   button's `color`, so nothing here should repaint it on hover. */
.hub-btn-onnavy:hover,
.hub-btn-onnavy:focus-visible { background: var(--steel); border-color: var(--steel); }

/* Photograph on the left half, navy panel on the right, both 504 tall. */
.hub-results {
  display: grid;
  grid-template-columns: 1fr 1fr;
  height: 504px;
  background: var(--navy);
  margin-top: 68px;
}
/* 0.53, so the navy panel behind shows through and tints the photograph. The
   source stacks an opaque <img> inside a wrapper at opacity .53 over a
   rgb(35,44,83) div; ours painted the photograph at full opacity on the same
   navy and read as an untinted picture. The blend is checkable: .53 of our
   photograph's mean (99,65,71) plus .47 of the navy is (69,55,77), which is the
   source's measured mean pixel exactly. */
.hub-results-photo { display: block; width: 100%; height: 504px; object-fit: cover; opacity: .53; }
/* A 485px column centered in the panel, not a fixed left inset: the source
   keeps it centered, so a padding drifted as the half grew. */
.hub-results-panel { padding-top: 111px; box-sizing: border-box; }
/* 490, matching .types-panel-inner. At 485 the body copy broke one word early
   on every line. */
.hub-results-inner { width: 490px; margin: 0 auto; }
.hub-results-panel h2 {
  font-family: var(--display);
  font-size: 48px;
  line-height: 57.6px;
  font-weight: 700;
  color: var(--paper);
  margin: 0 0 14px;
}
.hub-results-panel p {
  font-size: 16px;
  line-height: 28.8px;
  color: var(--paper);
  /* 490, matching the column it sits in. At 485 it broke a word early. */
  max-width: 490px;
  margin: 0;
}

/* 21 cards on a four-column grid, 225x175 each. */
.hub-grid { background: var(--mist);
  padding: var(--grid-pad-top, 99px) 0 var(--grid-pad-bottom, 100px); }
/* Flex rather than grid, because the source centers a short last row and a
   4-track grid cannot: /business-law's fifth card sits at x=607, and as a grid
   item it was pinned to the first column at x=231. Four 225px cards with 26px
   between them fill the 978px row exactly, so full rows land on the same
   pixels either way -- only the remainder row moves. */
.hub-grid ul {
  list-style: none;
  margin: 0 auto;
  padding: 0;
  width: 978px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  column-gap: 26px;
  /* 175 image + 9 + 28 label + 62 = the source's 274px row pitch.
     A hub that recorded its own gap passes it in as --card-row-gap. */
  row-gap: var(--card-row-gap, 62px);
}
/* The fixed width the grid columns used to impose. As flex items these size to
   their content, so "Food Delivery Driver Accidents" made its card 110px wider
   than a card, and only three then fit on a row. */
.hub-grid li { flex: 0 0 225px; width: 225px; }
.hub-grid a { display: block; text-decoration: none; }
.hub-grid img { display: block; width: 225px; height: 175px; object-fit: cover; }
.hub-grid span {
  display: block;
  margin-top: 9px;
  font-size: 20px;
  line-height: 28px;
  font-weight: 700;
  /* Underlined, and navy-deep rather than black: these labels are the card's
     link text and the source draws them as links. Same on all three hubs. */
  color: var(--navy-deep);
  text-decoration: underline;
  text-align: center;
}

.hub-closing { background: var(--navy); padding: 59px 0 59px; color: var(--paper); }
.hub-closing h2 {
  font-family: var(--display);
  font-size: 48px;
  line-height: 48px;
  font-weight: 700;
  margin: 0 0 18px;
}
/* An explicit 20px raise, not `super`. The source sets this mark as a plain
   20px inline span; `super` left it 3px low and `baseline` 20px low, and
   neither keyword lands on the source's position. */
.hub-closing h2 sup { font-size: 20px; line-height: 28px; vertical-align: 20px; }
/* 0.05em of tracking, which the source sets inline on this paragraph and
   nowhere else in the band. It is load-bearing: without it the copy fits 273px
   more on its first line and wraps a line short of the source. */
.hub-closing p { font-size: 16px; line-height: 28.8px; margin: 0; letter-spacing: 0.05em; }

@media (prefers-reduced-motion: reduce) {
  /* The poster still shows instead of the loop. */
  .hub-hero-video { display: none; }
  .hub-hero {
    background: var(--navy) url('../img/site/hub-hero.webp') center / cover no-repeat;
  }
}

/* 979 for the same reason as the homepage block above: 980 is the source's
   tablet canvas and it shows the full desktop hub there. Reflowing at 1100
   moved the results band 245px and the card grid 126px on /business-law the
   moment an iPad loaded it. */
/* 400, not 979: the desktop build now holds a 980 canvas at any window (the
   min-width on body), so a viewport media query at 979 fires while the canvas
   is still 980 and paints this narrow layout 980px wide -- the homepage's
   practice photographs drew 980x611 at a 780 window against the source's
   395x246. The phone build sets `<meta name="viewport" content="width=320">`
   in templates/base.html and the tablet sets 980, so 400 selects the phone
   canvas alone, which is the only one these rules were reaching. */
@media (max-width: 400px) {
  .hub-inner, .hub-grid ul { width: auto; padding-inline: var(--s-4); }
  .hub-grid ul { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
  .hub-results { grid-template-columns: 1fr; height: auto; }
  .hub-results-panel { padding: var(--s-6) var(--s-4); }
}

/* ============================================================================
   RESULTS LISTING
   The settlements index: a navy title band, a category list in the left margin,
   and the posts in a white card. Measured off /results at 1440.
   ========================================================================= */

/* A flat navy band, no photograph. 260px of it shows below the header -- the
   source's band runs y=80 to y=488 and the header covers the first 148. */
.results-head {
  background: var(--navy);
  height: 260px;
  box-sizing: border-box;
  padding-top: 71px;
  text-align: center;
}
.results-head h1 {
  color: var(--paper);
  font-family: var(--display);
  /* 700. The source's h1 element says 400, but the span that actually paints
     inside it is bold -- the same nesting the practice banners use. */
  font-weight: 700;
  font-size: 85px;
  line-height: 119px;
  margin: 0;
}

/* The category list sits in the left margin, outside the 980px container, and
   the post card is wider than the text column inside it. Both come from the
   source: categories at x=52, card at x=250, copy at x=350. */
.results-layout {
  display: grid;
  grid-template-columns: 179px 940px;
  column-gap: 20px;
  margin-left: -179px;
  padding-top: 14px;
}
/* Both boxes are outlined in the same near-white rule the source uses. */
.results-cats {
  align-self: start;
  margin-top: 1px;
  background: var(--paper);
  border: 1px solid rgb(232 230 230 / 75%);
  box-sizing: border-box;
}
.results-cats ul { list-style: none; margin: 0; padding: 0; }
.results-cats a {
  display: block;
  padding: 12px;
  font-size: 15px;
  line-height: 22.5px;
  color: var(--ink);
  text-decoration: none;
}
/* The source does not mark the current category at all: on
   /results/categories/business-litigation its "Business Results" span computes
   400, the same as the five below it. The phone build already carried a rule
   undoing this bold; the desktop half of the same defect was left in place. */
.results-cats a[aria-current] { font-weight: 400; }

/* Each post is a card with generous inner padding: 60px top and bottom, 100px
   either side, which is what puts the copy at x=350 in a 940px card. */
.result-post {
  background: var(--paper);
  border: 1px solid rgb(232 230 230 / 75%);
  box-sizing: border-box;
  /* 80 at the foot, not 60: the source leaves a 20px row under the copy.
     99 at the sides puts the copy at x=350 once the border is counted. */
  padding: 60px 99px 80px;
}
.result-post + .result-post { margin-top: 32px; }
/* The source reserves a 24px row above the headline of the newest post -- and
   only that one -- for its "save post" control. It follows the post, not the
   position: it shows wherever that post leads a list, and never on a list some
   other post leads.

   That control is a Wix Blog member feature and does not survive the migration,
   so the row is kept and the icon is not drawn. Holding the space keeps the
   page's geometry without shipping a button that cannot work. */
.result-post.has-save-slot h2 { margin-top: 42px; }
.result-post h2 {
  font-family: var(--body);
  font-size: 40px;
  line-height: 50px;
  font-weight: 400;
  margin: 18px 0 0;
  /* Two lines minimum. The source reserves the second line whether the
     headline needs it or not, which is why its one-line posts still stand 307px
     tall against our 260. */
  min-height: 100px;
}
.result-post h2 a { color: var(--ink); text-decoration: none; }
.result-body { margin-top: 20px; font-size: 18px; line-height: 27px; }
/* A link inside a result's body is the source's blue and carries no underline;
   ours inherited the page's black and an underline. */
.result-body a { color: rgb(10 45 140); text-decoration: none; }
.result-body p { margin: 0; }

/* Phone only: the source rules off the list before the pager. Measured on the
   live results index at 320 -- x=18, 284 wide, 1px of black at 20%, its top
   25px under the last excerpt and the pager opening 50px below it. The wide
   build draws no such line. */
.results-feed-rule { display: none; }
html[data-device="phone"] .results-feed-rule {
  display: block;
  height: 1px;
  /* The source's own numbers are 25 above and 50 below. Two of ours are
     already spent: `.results-pager` brings a 30px top margin, and
     `.result-post` closes on 42px where the source closes on 24, so the last
     excerpt's box already sits 18px lower than its counterpart. 7 and 20 put
     the rule where the source draws it relative to the text. */
  margin: 7px 0 8px;
  background: rgb(0 0 0 / 20%);
}

/* The pager: nine same-sized slots, centered. Keeping the arrows as inert
   squares when they cannot be followed is what holds the row's rhythm. */
.results-pager {
  display: flex;
  justify-content: center;
  margin: 30px 0;
}
.pager-page,
.pager-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin: 0 3px;
  box-sizing: border-box;
  font-size: 18px;
  color: var(--ink);
  text-decoration: none;
}
.pager-page.is-current { color: rgb(10, 45, 140); }
/* 7x12 filled chevrons, the size the source draws them. The doubles are two of
   these touching, so no gap between them. */
.pager-icon { width: 7px; height: 12px; fill: currentColor; }
.pager-arrow.is-off { opacity: .35; }
/* The "1/39" readout belongs to the 320 build only; the desktop source paints
   nine numbered slots and no count. */
.pager-count { display: none; }

/* The source serves a different pager on the phone: no numbered slots, and a
   current/total readout between the previous and next arrows. Measured off the
   live /results at 320, where the band is 68 tall and sits 1px under the last
   card, and the five 36x36 slots run at a 48px pitch from x=40 to x=280 with
   the readout's 18px "1/39" in the middle. Nine 36px slots do not fit a 284px
   row, so the desktop form shrank each one to 25.6 here. */
html[data-device="phone"] .results-pager {
  margin: 1px 0 0;
  padding: 16px 0;
}
html[data-device="phone"] .pager-page { display: none; }
html[data-device="phone"] .pager-arrow {
  flex: none;
  width: 36px;
  height: 36px;
  margin: 0 6px;
}
html[data-device="phone"] .pager-icon { width: 7px; height: 12px; }
html[data-device="phone"] .pager-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  min-width: 48px;
  margin: 0 6px;
  font-size: 18px;
  line-height: 22px;
  color: var(--ink);
}

/* The feed's sentinel takes up no room: the source shows nothing at the end of
   a category feed, and any height here would trip the observer early. */
.results-more { height: 0; overflow: hidden; }

/* The "every case is fact specific" note, which has to sit under a page of
   settlement figures. */
.results-note {
  background: var(--navy);
  color: var(--paper);
  margin-top: 11px;
  padding: 44px 0 0;
  height: 187px;
  box-sizing: border-box;
}
.results-note h2 {
  font-family: var(--display);
  font-size: 52px;
  line-height: 72.8px;
  font-weight: 700;
  color: var(--paper);
  margin: 0;
  /* One line, always. The text measures 956.8px in a 980px box and the
     registered mark takes the remaining 23 exactly -- the source has no slack
     here either, so any difference in how a machine rasterises the face tips it
     onto a second line. That overflows a band fixed at 187px and pushes the
     note out of sight, which is a much worse failure than the mark sitting a
     pixel proud. */
  white-space: nowrap;
}
/* Sits above the cap line and clear of the last word, as the source sets it. */
.results-note h2 sup {
  font-size: 20px;
  line-height: 0;
  vertical-align: 33px;
  margin-left: 5px;
}
.results-note p {
  font-size: 13px;
  line-height: 23.4px;
  font-weight: 700;
  margin: 3px 0 0;
}

/* The closing band at 320 on the RESULTS INDEX, measured on the live page as
   one piece, because its three parts interact:

       band top 1327, height 290, no padding of its own
       motto    1349-1420   two lines, 27px on a 37.8px line, 264 wide
       (R)      1435        its own line, 28px, against the right edge
       NOTE     1474-1542   14/25.2, centred
       band foot 1617       75px under the disclaimer

   Two things were wrong and could not be fixed separately. The reflow rule
   below resets the heading's font-size and not its line-height, so 28px text
   sat on the desktop's 72.8px line. And `sup` carries `vertical-align: 33px`,
   so the mark was inside the heading's inline flow, inflating the gap BETWEEN
   its two lines and pushing "Harder For You." down. `display: block` lifts it
   out of that flow onto its own line, which is where the source paints it.

   `:not(.results-note-post)` because the case-result post paints this band
   differently at 320 -- no motto at all and a 10px disclaimer -- and its rules
   sit earlier in this file, where a plain `.results-note` phone rule here would
   outrank them on source order. */
html[data-device="phone"] .results-note:not(.results-note-post) {
  padding: 19px 0 65px;
}
html[data-device="phone"] .results-note:not(.results-note-post) h2 {
  font-size: 27px;
  line-height: 37.8px;
  margin: 0;
}
html[data-device="phone"] .results-note:not(.results-note-post) h2 sup {
  display: block;
  vertical-align: baseline;
  font-size: 20px;
  line-height: 28px;
  margin: 10px 0 0;
  text-align: right;
}
html[data-device="phone"] .results-note:not(.results-note-post) p {
  font-size: 14px;
  line-height: 25.2px;
  text-align: center;
  margin: 10px 0 0;
}

/* Deliberately still 1200, where every other reflow rule in this file was
   moved to 979 to keep the 980 tablet canvas on the desktop layout.

   The source keeps its two columns at 980 and the -179px margin puts the
   category list at x=-166 -- off the left edge, clipped, unreachable. Tablet
   visitors to hkqlaw.com cannot use the category filter at all. Matching that
   would cost the reader working navigation to buy 56px of page height, so this
   one page reflows instead. Signed off as a known divergence; do not "fix" it
   by lowering the threshold to 979 with the others. */
@media (max-width: 1200px) {
  /* `.results-layout` is handled at 1090 below, not here: the source glitches
     its filter off the canvas between 980 and 1200, so that range is split
     between the two arrangements that work rather than reproducing the
     glitch. */
  .result-post { padding: var(--s-6) var(--s-5); }
  /* Narrow enough that one line is not possible; let the band grow instead. */
  .results-note { height: auto; padding-bottom: 44px; }
  .results-note h2 { white-space: normal; font-size: clamp(28px, 4vw, 52px); }
}

/* The source paints its category filter at x=-166 between 980 and 1200 --
   off the canvas, clipped, unreachable. That is a Wix glitch, not a layout, so
   it is not reproduced (rule 11). The client's call on 2026-09-17 was to split
   the glitching range between the two arrangements that do work: hold the
   stacked one further up, and bring the sidebar in sooner.

   So the desktop's left sidebar now starts at 1091 rather than 1201, and below
   that the list sits UNDER the feed as the phone build puts it, rather than
   above it where the source paints blank space.

   Held off the phone build, which picks its layout from the user agent and
   already has both a disclosure at the top and the foot list. */
@media (max-width: 1090px) {
  /* The single column applies to the phone build too -- it is what that build
     has always had, and holding it back took /results at 320 from +4px to
     -172px. Only the reordering is withheld there, because the phone already
     puts a disclosure at the top and the full list at the foot. */
  .results-layout {
    grid-template-columns: 1fr;
    margin-left: 0;
  }
  html:not([data-device="phone"]) .results-cats { order: 2; }
}
/* The upper half of the glitching range: the sidebar is back beside the feed,
   but the desktop's -179px pull would put it at x=-93 here -- clipped, which
   is the glitch itself. Dropped, so the column starts at the container's own
   edge and the feed takes what is left. */
@media (min-width: 1091px) and (max-width: 1200px) {
  .results-layout {
    grid-template-columns: 179px minmax(0, 1fr);
    margin-left: 0;
  }
}

/* ============================================================================
   OUR STORY
   A page of four stacked bands rather than the banner-and-column every other
   content page uses. All of these numbers are ink positions read off the live
   page at 1440, so they are stated as the gaps between bands rather than as
   band heights -- the copy is editable, and a fixed height would clip it the
   first time somebody adds a sentence.
   ========================================================================= */

/* Everything in this article centers on x=715, not on the page's 720. The
   offset is the source's and it is specific to this section -- the footer on
   the same page centers on 720 and matches ours exactly -- so it goes on the
   article's own blocks rather than on a shared container. Measured with no
   scrollbar on either side, so it is a real 5px and not a gutter artifact.

   `left`, not `translateX`: every one of these blocks also carries an entrance
   animation, and two of those animate `transform`. A translate here would be
   overwritten the moment the reveal fired, and the block would jump 5px as it
   settled. */
.story-head,
.story-photo,
.story-lead p,
.story-body { position: relative; left: -5px; }

/* -12 rather than the -5 the rest of the article takes. The source centers
   this line with the trailing whitespace in its last text node counted, so its
   visible title sits 7px left of where a line of the same ink would centre.
   Dropping the space (see our_story.html) is right for the rendering and
   leaves the centring to be corrected here. */
/* Entrance motion. Four elements animate on this page and the effects are the
   shared ones, but the timings are this page's own -- Wix sets them per
   element, and these are slower on the homepage where `fade` and `rise` were
   first measured. Overriding the timing rather than minting new effect names
   keeps the vocabulary small: the start and end states are identical.

     title  fade                       1146ms
     photo  rise, 120px + scale .8     transform 1144ms, opacity 895ms
     lead   lift, 60px                 1146ms   (the effect's own default)
     copy   fade                       1146ms

   The photo's opacity finishes ~240ms before its movement does, which is why
   the two are stated separately. Its curve is sharper than the others': the
   transform is 8.6% done at a quarter of the way through and 92.1% at three
   quarters, against 14.6/85.4 for a plain symmetric ease.

   These are durations, not the spans they were measured over. A frame-by-frame
   reading only sees the part of the curve where the value is actually moving --
   1146ms for the fades -- and an eased transition spends the rest of its time
   in the flat tails at either end. Setting the duration to the visible span
   made ours finish 85ms early. The ratio differs per curve, which is why the
   sharper `rise` needs proportionally more: 0.926 of its duration is visible
   for the symmetric ease, 0.90 for this one. */
.story [data-reveal='fade'] {
  transition: opacity 1221ms cubic-bezier(.5, 0, .5, 1);
}
.story [data-reveal='rise'] {
  transition: transform 1157ms cubic-bezier(.7, 0, .3, 1),
              opacity 994ms cubic-bezier(.7, 0, .3, 1);
}

.story-head { text-align: center; padding-top: 13px; left: -12px; }
/* 56px Montserrat in the footer navy, not the display face the other page
   titles use. "story" is the only bold word in the line. */
.story-head h1 {
  font-family: var(--body);
  font-size: 56px;
  font-weight: 400;
  line-height: normal;
  color: rgb(50, 65, 88);
  margin: 0;
}
.story-head h1 strong { font-weight: 700; }

/* 1094x421, centered, cropped to fill. The stored file is a wider original
   (1800x834) and the source serves a 1094x421 derivative of it, so the crop
   has to happen here rather than being baked into the asset. */
.story-photo {
  display: block;
  width: 1094px;
  max-width: 100%;
  height: 421px;
  object-fit: cover;
  object-position: center;
  /* -9 at the bottom: the source runs the navy band up under the photograph's
     last nine pixels rather than butting the two together. */
  margin: 9px auto -9px;
}

/* Above the photograph, which overlaps it by 9px. Both the -5px centering
   offset and the rise animation put the photograph in the positioned paint
   layer -- `position: relative` for one, a transform for the other -- so
   without a z-index here it painted over the top of this band and the overlap
   showed as the picture sitting on the navy instead of tucking behind it. */
.story-lead {
  position: relative;
  z-index: 1;
  background: rgb(38, 48, 89);
  color: var(--paper);
  padding: 47px 0 48px;
}
/* 828, and the measure is load-bearing. The sentence has to break after
   "been": at 800 it broke before it, which put the closing clause on a third
   line, lengthened the band by a whole line and pushed every paragraph below
   it down. The window is narrow -- 819 is the least that fits "been" on the
   first line and 840 the width at which "a" joins it. */
.story-lead p {
  max-width: 828px;
  margin: 0 auto;
  font-size: 24px;
  line-height: 33.6px;
  /* Left where the source centers: centered prose is hard to read at this
     length. Client-approved; see docs/PARITY-AUDIT.md. */
  text-align: left;
}
.story-lead strong { font-weight: 700; }

/* 760px, centered on the page. The source centers the copy inside it too; ours
   ranges it left, for the reason on .story-lead p above. */
.story-body {
  max-width: 760px;
  margin: 0 auto;
  padding: 41px 0 150px;
  font-size: 16px;
  line-height: 28.8px;
  text-align: left;
}
.story-body p { margin: 0 0 29px; }
.story-body p:last-child { margin-bottom: 0; }
/* The section heading is set at body size on the source, and was set at body
   weight too -- it read as a heading by position, not by type. Bold at the
   client's direction; see docs/PARITY-AUDIT.md. Its other distinction is that
   the paragraph under it follows immediately instead of at the 29px the other
   paragraphs use. */
.story-body h2 {
  font-family: inherit;
  font-size: 16px;
  line-height: 28.8px;
  font-weight: 700;
  margin: 0;
}

/* ============================================================================
   NARROW WIDTHS
   The source does not respond at all below 1024 -- it holds its 980px layout
   and scrolls sideways. Ours reflows instead, and these are the places where a
   fixed width refused to give and pushed the page wider than the window.
   Each one was found by measuring document.scrollWidth against clientWidth at
   1280, 1230, 1100, 1024, 900, 768, 620, 480, 390 and 360.
   ========================================================================= */

/* The header is a flex row of fixed-size items -- wordmark, nav, login, search
   -- and none of them shrink. Below about 1230 the search box was simply
   pushed past the right edge, on every page. It wraps from there down rather
   than at 900, which was far too late. */
@media (max-width: 1230px) {
  .header-inner {
    flex-wrap: wrap;
    padding: var(--s-4) var(--s-5);
    /* The 228px band is kept rather than collapsed. The source holds the same
       header height all the way down to its 980 tablet canvas -- measured at
       227 there against 228 at 1440 -- so letting ours shrink to 168 pushed
       every page 60px up the moment a tablet loaded it.

       The source fits one row into 980 only by painting the nav on top of the
       wordmark, which clips it to "Ho". Ours wraps to two rows inside the same
       band instead: same height, same everything below it, firm name legible. */
  }
  .header-search { margin-left: 0; }
}

/* Phone header, arranged the way the source arranges its own: wordmark and
   burger together on the first row, the search field full width underneath,
   and no Log In -- the source drops it from the mobile header entirely.
   Left to wrap on its own the four items took three ragged rows. */
@media (max-width: 899px) {
  .header-inner {
    align-items: center;
    /* 16 and 8. At 24/16 the wordmark and burger together needed 356px in a
       351px row and the burger dropped to a line of its own. */
    gap: 8px;
    padding: 16px;
  }
  .logo { order: 1; flex: 0 1 auto; min-width: 0; }
  .logo img { max-width: 100%; height: auto; }
  .nav-toggle { order: 2; margin-left: auto; }
  .header-search { order: 4; flex: 1 0 100%; width: auto; margin-left: 0; }
  .header-search input { width: 100%; min-width: 0; }
}

/* The panel column is a fixed 490px, which set a floor under the whole split
   band: the grid could not go below 980 and the photograph half stayed 490
   wide in a 390px window. */
/* 979, not 1000: at exactly 980 -- the tablet canvas -- the source still holds
   the fixed 490px panel, so collapsing it one pixel early was visible on every
   tablet. */
/* 400, not 979: the desktop build now holds a 980 canvas at any window (the
   min-width on body), so a viewport media query at 979 fires while the canvas
   is still 980 and paints this narrow layout 980px wide -- the homepage's
   practice photographs drew 980x611 at a 780 window against the source's
   395x246. The phone build sets `<meta name="viewport" content="width=320">`
   in templates/base.html and the tablet sets 980, so 400 selects the phone
   canvas alone, which is the only one these rules were reaching. */
@media (max-width: 400px) {
  .types-panel-inner,
  .hub-results-inner { width: auto; max-width: 490px; }
}

/* Grid and flex children default to a minimum of their content, so a card with
   99px of side padding held the whole column open. */
@media (max-width: 1200px) {
  .results-layout > * { min-width: 0; }
  .results-feed { min-width: 0; }
}

/* The practice pages carry their type sizes inline, because they are per-page
   measurements taken off the source at desktop widths (see PracticeArea's
   style fields). Those numbers are right for a 1440px window and far too big
   for a phone -- a 66px banner title or a 43px closing heading with one long
   word in it pushes the page sideways.

   Overriding an inline style needs !important, which is why it appears here and
   nowhere else in this stylesheet. It is scoped to phone widths so the measured
   desktop values are untouched. */
@media (max-width: 620px) {
  /* Scoped away from .practice-hook and .practice-secondary-heading: those
     carry recorded per-page sizes now, and this !important was only ever here
     to beat an inline style that no longer exists. The overflow protections
     below still apply to them. */
  /* .hub-hero h1 is scoped out for the same reason and on the same terms: it
     carries a recorded per-page phone size now (30px/40.6 across all three
     hubs), and the clamp resolved to 8vw = 25.6px at 320, with 1.25 leading
     for 32px. The overflow protections in the next block still apply to it.
     .hub-hook and .hub-closing h2 left on the same terms once
     record_hub_phone_rhythm measured them: the clamp's 25.6px/32 ran the hook
     to two lines where the source sets 23/25.2 and keeps it on one, and the
     closing heading to 80px of band where the source sets 14/15.6. */
  .practice-head h1,
  .practice-body > h2:not(.practice-hook):not(.practice-secondary-heading) {
    font-size: clamp(24px, 8vw, 48px) !important;
    line-height: 1.25 !important;
  }
  .practice-head h1,
  .practice-body > h2,
  .hub-hero h1,
  .hub-hook,
  .hub-closing h2 {
    max-width: none !important;
    min-height: 0 !important;
    white-space: normal !important;
  }
  .practice-body,
  .practice-secondary,
  .types-panel-inner { overflow-wrap: anywhere; }

  /* The results banner is 85px and set nowrap so its registered mark cannot
     drop to a second line. At phone widths one word at that size is wider than
     the screen, so here it shrinks and is allowed to wrap. */
  .results-head h1 {
    font-size: clamp(32px, 11vw, 85px);
    line-height: 1.2;
    white-space: normal;
  }
  .results-head { height: auto; padding: 48px 0; }
}

/* A 40px headline with a word like "Crashworthiness" in it cannot fit a small
   phone at that size, and an unbreakable word pushes the page wider. */
@media (max-width: 620px) {
  .result-post h2 { font-size: clamp(24px, 7vw, 40px); line-height: 1.25; min-height: 0; }
  .result-post h2 a { overflow-wrap: break-word; }
}

/* The wide button variant is a fixed 360px minimum, which is wider than a
   small phone once the container's padding is counted. */
@media (max-width: 420px) {
  .hub-btn-wide { min-width: 0; width: 100%; }
}

/* The footer's contact list is a two-column grid whose label column is a fixed
   184px. Below about 340 that plus the values is wider than the screen, and
   because the column is fixed the grid could not give. */
@media (max-width: 420px) {
  .footer-contact { grid-template-columns: auto minmax(0, 1fr); }
}

/* The footer's two buttons are 180px each with a 26px gap -- 386px that will
   not fit a phone. They stack instead. */
@media (max-width: 620px) {
  /* Matching `.footer-card p.footer-card-links`, which sets nowrap and is more
     specific than a bare class -- a plain .footer-card-links override here
     silently lost and the buttons stayed side by side. */
  .footer-card p.footer-card-links { flex-wrap: wrap; gap: var(--s-3); }
  .footer-card p.footer-card-links a { width: 100%; }
}


/* ==========================================================================
   PHONE BUILD

   The source serves phones a separate build, not a reflow of the desktop one.
   It is laid out on a fixed 320 canvas and the phone scales it up to fit, so
   an iPhone SE and a 16 Pro Max get identical pixels -- measured, both 3374px
   tall on /workers-compensation, with the 16 Pro Max simply zooming 1.34x.

   These rules are keyed to `html[data-device="phone"]`, set from the user
   agent in core/middleware.py, rather than to a width. That is deliberate and
   it is what the source does: the mobile build is gated on the user agent, so
   a desktop browser dragged down to 320px still gets the desktop layout on
   hkqlaw.com, and now also here. Width queries would diverge on exactly that
   case, and would fight the tablet canvas at 980.

   Measure against the source with:
     ./bin/python tools/mobile_report.py /path
   which drives both sides with a phone user agent and reports each paired text
   run's running offset plus the pixels gained since the previous one, so a
   gain can be traced to the band that causes it. `--bands` compares the
   full-bleed band sequence, for a gain that falls between two runs.
   ========================================================================== */

/* 20px each side, giving a 280px measure. Measured off the source's body copy,
   which sits at x=20 on every band of the mobile build. */
html[data-device="phone"] .container { padding-inline: 20px; }

/* --- The phone menu ---------------------------------------------------
   Every number here was read off hkqlaw.com at a 320 canvas with an iPhone
   user agent, with the menu open (pages/parity.py PHONE_UA):

     panel        fixed, 320 x viewport, white, over the page
     Log In       118x38 centered, top 11; avatar 26; label 16/22.4 in
                  rgb(196,83,8)
     rule         x 35-272, top 60, 3px solid black
     rows         28px pitch from top 77, x=18, 272 wide
     top level    18/28 weight 700 black; its label 222 wide where a chevron
                  follows it, and the chevron is a 50x28 box at x=240
     children     14/28 weight 400 black, flush at x=18, no indent
     current page rgb(10,45,140) on the child link

   The `.nav-search-row` and `.nav-chevron` markup exists on every build and
   is hidden outside this block: the source shows a Search row and per-item
   chevrons on the phone alone. */
html[data-device="phone"] .nav-search-row,
html[data-device="phone"] .nav-chevron { display: block; }
.nav-search-row,
.nav-chevron { display: none; }

html[data-device="phone"].nav-locked body { overflow: hidden; }

html[data-device="phone"] .site-header.is-nav-open .primary-nav {
  position: fixed;
  top: 0;
  left: 0;
  /* 100vw, not `inset: 0`: the right edge has to reach 320 like the source's
     panel does, and `right: 0` stops at the scrollbar. */
  width: 100vw;
  height: 100vh;
  z-index: 99999;
  display: block;
  background: var(--paper);
  border-bottom: 0;
  overflow-y: auto;
}

/* The rule under Log In. Drawn on the panel rather than as an element so the
   Log In button, which the markup leaves in the header row, needs no wrapper
   of its own. */
html[data-device="phone"] .site-header.is-nav-open .primary-nav::before {
  content: '';
  position: absolute;
  top: 60px;
  left: 35px;
  width: 237px;
  border-top: 3px solid #000;
}

/* The burger stays where it is and becomes the close control, as the source's
   does -- same 37x50 box, above the panel. */
html[data-device="phone"] .site-header.is-nav-open .nav-toggle {
  position: fixed;
  top: 11px;
  right: 13px;
  z-index: 100000;
  width: 37px;
  height: 50px;
  place-content: center;
  place-items: center;
  gap: 0;
  padding: 0;
}
html[data-device="phone"] .site-header.is-nav-open .nav-toggle span {
  grid-area: 1 / 1;
  width: 24px;
}
html[data-device="phone"] .site-header.is-nav-open .nav-toggle span:nth-child(1) {
  transform: rotate(45deg);
}
html[data-device="phone"] .site-header.is-nav-open .nav-toggle span:nth-child(2) {
  opacity: 0;
}
html[data-device="phone"] .site-header.is-nav-open .nav-toggle span:nth-child(3) {
  transform: rotate(-45deg);
}

html[data-device="phone"] .site-header.is-nav-open .nav-list {
  padding: 77px 30px 40px 18px;
  gap: 0;
}
html[data-device="phone"] .site-header.is-nav-open .nav-list > li {
  border-bottom: 0;
  position: relative;
}
html[data-device="phone"] .site-header.is-nav-open .nav-top {
  font-family: var(--body);
  font-size: 18px;
  font-weight: 700;
  line-height: 28px;
  letter-spacing: normal;
  color: #000;
  background: none;
  border: 0;
  border-radius: 0;
  padding: 0;
  width: 100%;
}
/* The label stops short of the chevron's box rather than running under it. */
html[data-device="phone"] .site-header.is-nav-open .has-children > .nav-top {
  width: 222px;
}
html[data-device="phone"] .site-header.is-nav-open .nav-list > li.is-current > .nav-top {
  background: none;
  color: #000;
}

html[data-device="phone"] .site-header.is-nav-open .nav-chevron {
  position: absolute;
  top: 0;
  left: 222px;
  width: 50px;
  height: 28px;
  padding: 0;
  background: none;
  border: 0;
  color: #000;
  cursor: pointer;
}
html[data-device="phone"] .site-header.is-nav-open .nav-chevron svg {
  display: block;
  width: 12px;
  height: 7px;
  margin: 9px 0 0 18px;
}
html[data-device="phone"] .site-header.is-nav-open .has-children.is-open > .nav-chevron svg {
  transform: rotate(180deg);
}

html[data-device="phone"] .site-header.is-nav-open .dropdown {
  position: static;
  padding: 0;
  border: 0;
  background: none;
  width: auto;
  opacity: 1;
  visibility: visible;
  transform: none;
  display: none;
}
html[data-device="phone"] .site-header.is-nav-open .has-children.is-open > .dropdown {
  display: block;
}
html[data-device="phone"] .site-header.is-nav-open .dropdown li { padding: 0; }
html[data-device="phone"] .site-header.is-nav-open .dropdown a {
  font-family: var(--body);
  font-size: 14px;
  font-weight: 400;
  line-height: 28px;
  color: #000;
  background: none;
  border-radius: 0;
  padding: 0;
  white-space: normal;
}
html[data-device="phone"] .site-header.is-nav-open .dropdown li.is-current > a {
  background: none;
  color: rgb(10, 45, 140);
}
/* The source's phone menu stops at two levels: Real Estate Law is a plain row
   there, with the children its desktop dropdown carries left out. */
html[data-device="phone"] .site-header.is-nav-open .dropdown-sub { display: none; }

/* The footer's wide band takes the same inset. `50vw + 460px` resolves to more
   than the canvas here, so it was running edge to edge. */
html[data-device="phone"] .footer-wide { width: auto; padding-inline: 20px; }
html[data-device="phone"] .footer-story .footer-wide { width: auto; }

/* The trail is not in the mobile build at all. The source drops "You Are Here:
   Practice Areas > Personal Injury > Workers' Compensation" rather than
   wrapping it onto three lines, and the 60px it occupied is why every band
   below it sat low. Hidden rather than dropped from the template so that the
   markup stays one document for all three canvases -- the trail is still in
   the HTML for crawlers, which see the desktop build anyway. */
html[data-device="phone"] .crumb { display: none; }

/* The banner is a 188px photo band sitting directly under the 134px header,
   with the title centered in it both ways. Measured on six practice pages: the
   header is 134 on every one of them, the photo starts at y=134 on every one,
   and the title's box center lands within 1.5px of the band's center whether
   it takes one line or two -- /workers-compensation wraps to two and starts at
   188, /corporate-law takes one and starts at 208, and both center on 227.

   Nothing here is the desktop band scaled down. That one is 346px tall with a
   123px top inset and a 490px photo layer that reaches up behind the header;
   at 320 it came out 345px tall, which is most of the 1300px this page was
   running long.

   !important throughout, because _page_hero.html writes padding-top, min-height
   and the photo's top/height as inline styles from the page's recorded
   banner_style. Those are desktop measurements and an inline style beats any
   selector without it. */
html[data-device="phone"] .practice-head {
  padding: 0 !important;
  min-height: 188px !important;
  align-items: center;
}
/* The FAQ detail band paints its navy as a `::before` pinned to 408px, because
   the desktop band is a fixed 408 with the title centred in it. The rule above
   collapses the band to 188 and does not touch that layer, so the slab hangs
   220px past the band and covers the top of the page. Everything under it is
   dark text on dark navy: "Back to FAQs" measures 1.01:1 against WCAG 1.4.3's
   4.5, which is not hard to read, it is invisible.

   Not a style change -- no colour, size or position of any content moves. A
   background layer stops overhanging the box it belongs to, and the result is
   closer to the source, which paints this area white. */
/* /our-story. The desktop page nudges its blocks left by 5px (and the head by
   12) to sit them on the source's 980 grid, and sets 56px and 24px type for
   that width. On a 320 canvas those numbers put the copy off the left edge --
   the lead measured x=-5 in a 320-wide box with no side padding at all, and
   body paragraphs at -4 and -5. The source runs 30px, 19/26.6, and a 280
   measure inset 20 from each edge. */
/* /results. The card pads 40px 28px, which puts its copy at x=49 where the
   source has it at 18, and the narrow-width block sizes the title 24/30 and the
   body 18/27 against the source's 18/25.2 and 13/19.5. The page's own container
   already supplies the inset, so the card adds none. */
/* /team. The card's type is set in em and lands on fractional pixels the
   source never uses -- 14.08/21.12 where it sets 13/18.2, and 15.04/22.56 for
   the contact lines where it sets 15/21. The head is 30.08/36.096 against
   31/43.4 and its subtitle 20/28 against 25/35. */
/* The homepage motto ranges left on the source, with "No one" at x=19; ours
   centred it and put that word at 42. (The 384-wide box this first chased was
   reveal.js mid-flight at scale 1.2, not a layout defect -- measure this page
   after its animations settle.) */
html[data-device="phone"] .home-motto p {
  text-align: left;
  padding-inline: 19px;
  box-sizing: border-box;
}

/* Insight article pages, measured against the live article at 320:

     .insight-layout  padding-inline 14px/38px on top of the container's 20,
                      which put the body at x=34 against the source's 20
     .insight-body p  16/24 against the source's 14/21
     .insight-practice a  a 40px line box, where the source leaves it normal  */
html[data-device="phone"] .insight-layout { padding-inline: 0; }
/* The band opens straight under the header at 320 -- the source's navy runs
   from y=134, which is the header's own bottom edge -- where the desktop rule's
   `margin-top: 52px` left 52px of white above it on every article. */
html[data-device="phone"] .insight-head { margin-top: 0; }
/* Full bleed and 300 tall, not the desktop band's 560 inside a 20px gutter:
   the source's photograph runs x=0..320 and y=386..686 on
   /what-you-need-to-know/personal-injury-insights/passenger-injury-claims and
   the same on distracted-driving-accidents, 13px under the navy band, whose
   own bottom edge is at 373. Ours was 280x560 at x=20 with 45px above it --
   260px too tall on all 170 articles. */
html[data-device="phone"] .insight-hero { padding: 13px 0 0; }
html[data-device="phone"] .insight-hero img { height: 300px; }
html[data-device="phone"] .insight-meta { padding-inline: 0; line-height: 22.4px; }
html[data-device="phone"] .insight-head .container { padding-inline: 14px; }
html[data-device="phone"] .insight-head h1 {
  font-size: 28px !important;
  line-height: 36.4px !important;
}
html[data-device="phone"] .insight-body p {
  font-size: 14px;
  line-height: 21px;
}
/* The sidebar rows run on a 67px pitch at 320, not the desktop's 43. Measured
   on /what-you-need-to-know/personal-injury-insights/passenger-injury-claims:
   the source's boxes are 42 tall and open at y=2459.4, 2526.4, 2591.4, 2658.4,
   2725.4 and 2859.4, and its seven separator rules land at 2511, 2576, 2643,
   2710, 2777, 2844 and 2911 -- 9.6px below each row rather than on top of the
   next one, which is where the desktop draws them. 42 + 9.6 + 1 + 14.4 is 67. */
/* 10px and wrapping, which is what the source sets here -- measured on the live
   phone build of /what-you-need-to-know/personal-injury-insights/
   amputation-injuries, where every row computes 10px with `white-space: normal`
   in a box 160 to 200 wide. The desktop sizes reached this build unopposed: the
   four `.is-lg` rows stayed at 16px with 1.6px of tracking and the rest at 14,
   all of them `nowrap`, and the widest four then ran past their own 42px row.
   The rule below this block warns that a label overflowing this fixed row
   overlaps its neighbour; overflowing it also puts the glyphs outside the box
   that takes the tap, and those same four labels -- Real Estate Law, Estate &
   Trusts, Business Law, Corporate Law -- are the ones a client reviewer
   reported as linking to nothing on her phone. */
html[data-device="phone"] .insight-practice a {
  height: 42px;
  line-height: normal;
  font-size: 10px;
  letter-spacing: normal;
  white-space: normal;
}
/* Worth knowing, and deliberately NOT designed around: the back-to-top control
   is `position: fixed` at x 252..296 on BOTH sites, and these rows run to 285,
   so its 44px box sits over the right 33px of whichever row it is passing. A
   tap there scrolls to the top instead of following the link. Shrinking the
   rows to clear it was tried and reverted -- it moved every label 50 to 80px
   right of where the source starts its own, which is a visible defect traded
   for about 13% of one row's width. The source has the same overlap on its two
   widest rows. */
html[data-device="phone"] .insight-practice li + li a { border-top: 0; }
html[data-device="phone"] .insight-practice li:not(:last-child) {
  padding-bottom: 9.6px;
  border-bottom: 1px solid rgb(168 169 172);
}
html[data-device="phone"] .insight-practice li + li { margin-top: 14.4px; }
/* The rules are inset from the row: 34..286 on the source against the row's own
   31..288. */
html[data-device="phone"] .insight-practice li:not(:last-child) { margin-inline: 3px; }
/* 160x42 at x=81, not the desktop panel's 207x40 -- the same box the footer
   card's two buttons take at 320. */
html[data-device="phone"] .need-help .btn { width: 160px; height: 42px; }
/* 105x30 at 320 as well as at 1440 -- the pager is the same control on both of
   the source's builds. Compared on the article named above, both buttons. */
html[data-device="phone"] .insight-pager a,
html[data-device="phone"] .insight-pager span { width: 105px; height: 30px; }
/* Body headings run a size larger than the source on the phone: measured 24/36
   against its 20/30 on an <h3>. The rest of the body's heading scale is set
   for the desktop measure and wants the same pass. */
html[data-device="phone"] .insight-body > h3 {
  font-size: 20px;
  line-height: 30px;
}

html[data-device="phone"] .team-head h1 {
  font-size: 31px !important;
  line-height: 43.4px !important;
}
html[data-device="phone"] .team-head-sub {
  font-size: 25px;
  line-height: 35px;
}
html[data-device="phone"] .team-card-practice {
  font-size: 13px;
  line-height: 18.2px;
}
html[data-device="phone"] .team-card-contact,
html[data-device="phone"] .team-card-contact a {
  font-size: 15px;
  line-height: 21px;
}
html[data-device="phone"] .team-card-more a { line-height: normal; }

/* The category list is a disclosure on the phone build and a plain sidebar at
   1440, where the source's list opens straight at "Business Results". Both the
   button and the "All Posts" row are therefore phone-only. */
.results-cats-toggle,
.results-cats-close,
.results-cats-foot,
.results-cats-all { display: none; }

/* Measured on the live phone page: the button runs the full 320 canvas at
   y=225, 50px tall, montserrat 16/400 black on white between two 1px rules at
   30% black, with an 18px inset. The panel's rows sit x=21 to 299, 47px each. */
html[data-device="phone"] .results-cats {
  position: relative;
  margin-inline: -18px;
  border: 0;
}
html[data-device="phone"] .results-cats-toggle {
  /* Flex, so the chevron sits at the far end. Centring the row keeps the label
     where `padding: 10px` put it: the source's title box is 22px tall in the
     50px bar at a 14px inset, and (50 - 22) / 2 is the same 14. */
  display: flex;
  align-items: center;
  justify-content: space-between;
  box-sizing: border-box;
  width: 100%;
  height: 50px;
  padding: 10px 18px;
  /* The source shows a pointer over this control; ours left the default arrow. */
  cursor: pointer;
  background: var(--paper);
  border: 0;
  border-top: 1px solid rgb(0 0 0 / 30%);
  border-bottom: 1px solid rgb(0 0 0 / 30%);
  font-family: var(--body);
  font-size: 16px;
  /* 22.4px, which is what the source's label computes; `normal` ran it short. */
  line-height: 22.4px;
  font-weight: 400;
  color: var(--ink);
  text-align: start;
}
/* 19x19 at the bar's far end: the source's sits at x=283 in a 320 canvas, its
   right edge 18 from the screen as the label's left edge is, and vertically
   centred in the 50px bar. Solid black there, not the label's --ink. */
html[data-device="phone"] .results-cats-chevron {
  flex: none;
  width: 19px;
  height: 19px;
  fill: #000;
}
html[data-device="phone"] .results-cats-all { display: list-item; }
html[data-device="phone"] .results-cats a {
  margin-inline: 21px;
  padding: 12px 0;
}

/* The button opens a bottom sheet, not a dropdown: the source anchors a white
   panel to the foot of the viewport, 306px tall at viewport heights 600, 900
   and 1200 alike, and dims the page behind it with solid black at 0.6 opacity.
   .is-collapsible is added by static/js/nav.js, so without script the list and
   its Close row stay in flow as working links. */
html[data-device="phone"] .results-cats.is-collapsible .results-cats-sheet {
  display: flex;
  position: fixed;
  inset: auto 0 auto 0;
  /* Parked a sheet's height below the viewport so opening slides it up. It
     used to toggle `display`, which cannot animate, so the panel appeared in
     one frame where the source takes 300ms. */
  bottom: -306px;
  z-index: 2000;
  flex-direction: column;
  max-height: 306px;
  background: var(--paper);
  visibility: hidden;
  /* 300ms on `bottom`, easing read off the source's own transition with
     document.getAnimations() while the sheet opened. Visibility flips at the
     end of the slide out and the start of the slide in, so the panel is never
     focusable while it is off-screen. */
  transition: bottom 300ms cubic-bezier(0.25, 0.46, 0.45, 0.94),
              visibility 0s linear 300ms;
}
html[data-device="phone"] .results-cats.is-collapsible.is-open .results-cats-sheet {
  bottom: 0;
  visibility: visible;
  transition: bottom 300ms cubic-bezier(0.25, 0.46, 0.45, 0.94),
              visibility 0s;
}
@media (prefers-reduced-motion: reduce) {
  html[data-device="phone"] .results-cats.is-collapsible .results-cats-sheet,
  html[data-device="phone"] .results-cats.is-collapsible.is-open .results-cats-sheet {
    transition: none;
  }
}
/* The scrim is the aside's own hit target, which static/js/nav.js relies on to
   dismiss the sheet when the dimmed page is tapped. */
html[data-device="phone"] .results-cats.is-collapsible.is-open::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 1999;
  background: #000;
  opacity: 0.6;
}
/* The seven rows scroll under the Close row, which is why the source's last
   category sits at y=824 in a sheet whose foot is at 900. */
html[data-device="phone"] .results-cats.is-collapsible .results-cats-sheet ul {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding-top: 8px;
}
/* 320x37 rows: 8px above a 21px line and 8px below, indented 24px. The source
   sets them in its default sans stack rather than the site's Montserrat. */
html[data-device="phone"] .results-cats.is-collapsible .results-cats-sheet a,
html[data-device="phone"] .results-cats-close {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  width: 100%;
  margin-inline: 0;
  padding: 8px 24px;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 14px;
  line-height: 21px;
  color: var(--ink);
  text-decoration: none;
}
/* The source lifts a row under the pointer to 6% black; the current row stays
   at its own 12%. Ours highlighted only the current one, so a hovered row gave
   no feedback at all. */
html[data-device="phone"] .results-cats.is-collapsible .results-cats-sheet a:hover {
  background: rgb(0 0 0 / 6%);
}
html[data-device="phone"] .results-cats.is-collapsible .results-cats-sheet a[aria-current] {
  background: rgb(0 0 0 / 12%);
}
/* 61px: the 37px row plus 12px of white either side, held at the sheet's foot. */
html[data-device="phone"] .results-cats-close {
  gap: 14px;
  padding-block: 20px;
  flex: 0 0 auto;
  background: var(--paper);
  border: 0;
  text-align: start;
}
/* The second copy the source paints under the pager: seven 47px rows in a
   280x281 box, sharing the sidebar's own row styling. It is a plain expanded
   list, not a second disclosure. */
html[data-device="phone"] .results-cats-foot {
  display: block;
  /* The source's own edge, measured on the live phone page: the listing card's
     rgba(232, 230, 230, 0.75), not the flat 216 grey this carried. Its box is
     280 wide centred, not the container's full 284. */
  border: 1px solid rgb(232 230 230 / 75%);
  box-sizing: border-box;
  width: 280px;
  margin-inline: auto;
  margin-top: 20px;
}
/* A row under the pointer takes the source's own tint, which is NOT the 6%
   black the collapsed sheet's rows use -- the two lists are styled apart on
   the source and were measured separately. */
html[data-device="phone"] .results-cats-foot a:hover {
  background: rgb(232 230 230 / 75%);
}
html[data-device="phone"] .results-cats-foot ul { list-style: none; margin: 0; padding: 0; }
html[data-device="phone"] .results-cats-foot li { list-style: none; }
/* Six rows here, not seven: "All Posts" belongs to the disclosure at the top of
   the page and measures 0x0 in the source's copy of this list. */
html[data-device="phone"] .results-cats-foot .results-cats-all { display: none; }
html[data-device="phone"] .results-cats-foot a {
  display: block;
  padding: 12px 21px;
  font-size: 15px;
  line-height: 22.5px;
  color: var(--ink);
  text-decoration: none;
}

/* No card on the phone. The source's desktop post IS a bordered panel and ours
   matches it, but its phone build drops the box entirely: measured on live's
   320 canvas, `article[data-hook="post-list-item"]` is white with
   `border-width: 0` and no ::before/::after rule, its items run 275, 525, 741
   for heights 250, 216, 216 -- butted together with no gap -- and the inner
   `.post-list` carries `padding: 30px 18px 0`. Ours kept the desktop card's
   1px border, its 60/80 vertical padding and a 32px gap, which is the "articles
   are put in squares instead of just having a line between each" a client
   reviewer reported on /results and all six category pages.
   `.results .container` supplies the 18px gutter, so the column still lands at
   284 with the inline padding zeroed. */
html[data-device="phone"] .result-post {
  padding: 30px 0 42px;
  border: 0;
}
html[data-device="phone"] .result-post + .result-post {
  margin-top: 0;
  /* The source rules between every result at 320 -- 284 wide, black at 20%,
     on each item after the first. Reported by the client as "the articles are
     put in squares instead of just having a line between each", and dismissed
     here once after searching a single page over a single y-range and finding
     none. /results/page/2 carries three of them at y=515, 667 and 819. */
  border-top: 1px solid rgb(0 0 0 / 20%);
}
/* The rest of the source's phone item, measured on its second post -- the first
   carries the save-post row and is not the general case. Live: title top 29,
   76 tall; excerpt 10 below it, 77 tall; 24px under the excerpt. Ours was 48 /
   76 / 20 / 59 / 0, which is 14px short overall and reads tighter at every
   join. That is the "articles are more squished than on the live site" half of
   the same report. */
html[data-device="phone"] .result-post h2 { margin-top: 0; }
/* 34, not the desktop 24: the source reserves more above the newest post's
   headline here. Its first post opens its title at 63 against 29 on the rest. */
html[data-device="phone"] .result-post.has-save-slot h2 { margin-top: 34px; }
html[data-device="phone"] .result-body {
  margin-top: 10px;
  /* Three lines reserved, not merely clamped: the source's second and third
     items are both exactly 216 tall though their excerpts differ in length, so
     a short one holds the row open rather than pulling it up. 3 x 19.5. */
  min-height: 58.5px;
}
/* ...but NOT for a result whose body is only the source's hyphen. The source
   reserves the three lines on a real excerpt and collapses on these: its
   /results/page/2 items stand 152px against the 216 of page one, with the
   body 16px tall. Reserving there made every short item 40px too deep. */
html[data-device="phone"] .result-body.is-bare {
  min-height: 0;
}
html[data-device="phone"] .results .container { padding-inline: 18px; }
/* The category feed's second band line. Phone only -- measured at 14px white
   on the live category page; the wide build paints none. */
.results-head-sub { display: none; }
html[data-device="phone"] .results-head-sub {
  display: block;
  /* Left, not centred with the heading above it, and pulled up into that
     heading's line box: the source sets it at x=18 and y=191 where the
     heading's own 49px line runs to 208. */
  text-align: left;
  margin: -16px 0 0;
  font-family: var(--body);
  font-size: 14px;
  line-height: 21px;
  font-weight: 400;
  color: var(--paper);
}

html[data-device="phone"] .results-head h1,
html[data-device="phone"] .results h1 { line-height: 49px !important; }
/* 23 above the title and 19 below, against the 48/48 the narrow-desktop media
   query gives this band: the source opens its title at y=157 under a 134px
   header and closes the band at 225, where ours ran to 279 and carried the
   category control 69px down the page with it. */
html[data-device="phone"] .results-head { padding: 23px 0 19px; }
/* The source opens the category control flush against the banner, where this
   layout's own 14px and the aside's 1px held it 15px lower. */
html[data-device="phone"] .results-layout { padding-top: 0; }
html[data-device="phone"] .results-cats { margin-top: 0; }
/* The index paints an excerpt, not the post: the source clamps its summary to
   three lines with `-webkit-line-clamp: 3` and keeps the whole run in the DOM,
   where ours rendered every paragraph of `intro` and ran one card past the fold.
   Clamping the first paragraph and hiding the rest gives the source's three
   lines, and the copy stays on the page for the reader and for search. */
html[data-device="phone"] .result-body > :not(:first-child) { display: none; }
html[data-device="phone"] .result-body > :first-child {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
}

/* No `!important` on the size here: it beat
   `.results-of-category .result-post h2` regardless of specificity, so category
   listings painted their cards at the index's 18/25.2 where the source sets
   30/42. The same two declarations are restated further down without it. */
html[data-device="phone"] .result-body {
  font-size: 13px;
  line-height: 19.5px;
}

html[data-device="phone"] .story-head,
html[data-device="phone"] .story-photo,
html[data-device="phone"] .story-lead p,
html[data-device="phone"] .story-body { left: 0; }
/* 130, not the desktop 421. The base rule pins the height and nothing here
   replaced it, so the photograph scaled to its own ratio and stood 291px taller
   than the source's -- the whole of this page's band difference. `object-fit:
   cover` is already on the base rule and does the cropping. */
html[data-device="phone"] .story-photo { width: 320px; height: 130px; }
html[data-device="phone"] .story-head h1 { font-size: 30px; }
html[data-device="phone"] .story-lead,
html[data-device="phone"] .story-body { padding-inline: 20px; }
html[data-device="phone"] .story-lead p {
  font-size: 19px;
  line-height: 26.6px;
}
/* The base rule's 47/48 is a desktop measurement and only its inline half was
   replaced here, so this band stood 255px tall against the source's 200. The
   source takes 21 above the copy and 23 below, on a 270px measure. */
html[data-device="phone"] .story-lead { padding: 21px 25px 23px; }

/* The blanket phone rule above pins every hero to 188px with !important, which
   is the practice banner's number; the source gives this page an 89px band with
   its title 23px under the header, 35px rather than the 30 that rule sets. */
html[data-device="phone"] .practice-head.hero-search {
  min-height: 0 !important;
  /* 23 above and 17 below: the title lands at the source's 157 and the
     summary below it at 373. Adding the 3px above without taking it off the
     bottom moved everything under the band down with it. */
  padding-block: 23px 17px !important;
}
html[data-device="phone"] .practice-head.hero-search h1 {
  font-size: 35px !important;
  line-height: 49px !important;
}
html[data-device="phone"] .practice-head.hero-faq::before { height: 100%; }

/* The FAQ detail page's type and insets, measured on the live page at 320:

     h1                33/46.2, where the shared phone rule forces 30/40.6
     .faq-heading      24/28.8 against our 32/38.4
     the page inset    16, not the container's 20                          */
html[data-device="phone"] .practice-head.hero-faq h1 {
  font-size: 33px !important;
  line-height: 46.2px !important;
}
html[data-device="phone"] .faq-heading {
  font-size: 24px;
  line-height: 28.8px;
}
html[data-device="phone"] .faq .container { padding-inline: 16px; }

/* The accordion has no card on the phone. The source draws each question as
   plain text with a thin rule under it and the chevron at the right -- no
   border around it, no white fill -- and pads 20px vertically with nothing
   horizontally, which is what puts the question at x=16 rather than our 33.
   Ours carried the desktop's bordered white card down. */
/* The back link sits at x=20 on the source, 4px in from the page's 16, and its
   line box is `normal` rather than the 28.8 our body rule gives it. Its width
   differs by 11px because Avenir Light is not a face we can ship -- that one is
   the documented substitution, not a defect. */
html[data-device="phone"] .faq-back {
  padding-left: 4px;
  line-height: normal;
}

html[data-device="phone"] .faq-list { gap: 0; }
html[data-device="phone"] .faq-item {
  border: 0;
  border-bottom: 1px solid var(--navy);
  background: none;
}
html[data-device="phone"] .faq-item summary { padding: 20px 0; }
html[data-device="phone"] .faq-answer { padding: 0 0 20px; }
/* 24 under the input here, against the desktop build's 34. */
html[data-device="phone"] .faq-showing { margin-top: 24px; }

/* The insight index's category card. The source stacks it on the phone -- icon
   centred above the copy, not a 126px column beside it -- and sets the name at
   19px rather than the desktop 24. Measured on the live card at 320: card 280
   wide, icon 90x104 at dx 95, which is (280 - 90) / 2, name at dx 11 and 19px
   over 26.6, blurb 14 over 19.6 as ours already is. The 440px block below only
   narrows the icon column to 84 and leaves the two-column shape in place. */
/* The FAQ index's buttons. The 800px block sets 15px and 1px of tracking for a
   tablet; the source paints them at 17 on the phone, and at 15 the label sits
   narrower so the centring moves with it -- "Workers' Comp FAQs" measured 206
   wide at x=67 on the source against 160 at x=80 here. */
/* The picker, measured on the live page at 320. The 800px block's tablet
   values were reaching the phone throughout:

     button   246x54 at x=37, 12/16 padding, 1px tracking
     source   200x42 centred at x=60, 3px padding, 2.55px tracking
     heading  24/33.6 against the source's 19/26.6                        */
/* The FAQ index hero is 35/49 on the source; the shared phone rule forces
   30/40.6 on every .practice-head. */
/* The shared phone rule holds every .practice-head open to 188px and centers
   the title in it, which is right on /contact, /in-the-news, /privacy and
   /attorney-referrals. The source does not do it here: both FAQ indexes run
   20px of band above and below a 98px two-line title, for 138 all in, and the
   188 floor sat the title 22px low. Expressed as padding rather than a height
   so the band follows the title instead of being pinned to a measurement. */
html[data-device="phone"] .practice-head.hero-faq-index {
  min-height: 0 !important;
  padding-block: 20px !important;
}
html[data-device="phone"] .practice-head.hero-faq-index h1 {
  font-size: 35px !important;
  line-height: 49px !important;
}

html[data-device="phone"] .faq-picker-heading {
  font-size: 19px;
  line-height: 26.6px;
}
/* The source's phone button is a fixed 200x42 and sets `white-space: nowrap`
   with an ellipsis, so four of the five labels on /faqs read as "Auto Insurance
   F…". Ours keeps its box and its type but lets the label wrap and the button
   grow, which is the one departure here that a reader gains from. Without the
   `height: auto` the wrapped second line was painted outside the 42px box and
   clipped mid-glyph, which is neither the source's behavior nor legible. */
html[data-device="phone"] .faq-picker-button {
  font-size: 17px;
  letter-spacing: 2.55px;
  width: 200px;
  max-width: none;
  height: auto;
  min-height: 42px;
  padding: 3px 6px;
  margin-inline: auto;
  box-sizing: border-box;
}


/* site.css pins `.faqs > .container` to 986px so /faqs and /commercial-faqs
   land the motto strip at the same y -- a desktop contract between two pages
   nobody views side by side. On the phone it is dead white: 392px of it
   between the category card and the motto on /faqs, and the source has no such
   box at all, so this is ours rather than the source's. The page ends where
   its content ends. */
/* The motto band is not the same component on every page that carries it, which
   is rule 15 of .claude/rules/parity-measurement.md in one object. Measured at
   320 on the live site: /attorney-referrals centres the heading and puts the
   mark at x=271, which is what the shared rule below already does; the FAQ
   indexes LEFT-align the heading at x=20 and put the mark at x=282, on its own
   line against the right edge. Ours centred both on both pages.

   Scoped to `.faqs`, the FAQ index's own wrapper, rather than widening the
   shared rule -- both pages render the same `strip_only` partial, so the class
   is the only thing that tells them apart. */
/* The source's back-to-top control: 44x44, fixed, 24px from the right edge and
   121px up from the bottom, measured at 320x568. Hidden at the top of the page
   and faded in over 0.5s once the visitor has scrolled, which is the source's
   own `transition: visibility, opacity 0.5s`. Phone only, as it is there. */
html[data-device="phone"] .back-to-top {
  position: fixed;
  right: 24px;
  bottom: 121px;
  z-index: 100000;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transition: visibility 0s .5s, opacity .5s;
}
html[data-device="phone"] .back-to-top.is-visible {
  opacity: 1;
  visibility: visible;
  transition: visibility 0s, opacity .5s;
}
/* Gone while the menu is open. The open panel is a full-viewport fixed layer at
   z-index 99999 and this control sits at 100000, so it was the one thing above
   it: the page under the menu was unreachable and this arrow was not, and
   tapping it scrolled a page the reader could not see. `.nav-locked` is set on
   <html> by static/js/nav.js for exactly the span the panel is open. */
html[data-device="phone"].nav-locked .back-to-top {
  opacity: 0;
  visibility: hidden;
}
html[data-device="phone"] .back-to-top svg { display: block; width: 100%; height: 100%; }

html[data-device="phone"] .faqs .motto-strip { text-align: left; }
/* Inline, so the mark sits against the words it marks. The source strands it
   at x=282 on its own line, hard against the right edge and a full line below
   "You." -- which is a wrapping glitch rather than a decision, and rule 11 of
   .claude/rules/parity-measurement.md already says reproducing a source bug is
   not fidelity. The left-aligned heading IS the source's layout and stays. */
html[data-device="phone"] .faqs .motto-heading { display: inline; }
html[data-device="phone"] .faqs .motto-mark {
  display: inline;
  position: static;
  vertical-align: super;
  /* The source's own size; only its stranded position is dropped. */
  font-size: 20px;
  line-height: 28px;
}

/* Measured on the live phone /faqs: the card is 280x371 at x=20, opening 10px
   under the hero band's foot at 272 and closing 46px above the motto strip at
   699. The desktop 61/61 pair put it 51px low. Ours runs taller than 371
   because its labels wrap rather than truncate -- see .faq-picker-button
   below -- so the card's own edges are what match here, not its height. */
html[data-device="phone"] .faqs > .container {
  min-height: 0;
  padding-top: 10px;
  padding-bottom: 46px;
}
/* Inside the card, live: heading at 294 (12 under the card's top edge), first
   button at 340, last button closing 63 above the card's foot. */
html[data-device="phone"] .faq-picker {
  padding-top: 12px;
  padding-bottom: 63px;
}
html[data-device="phone"] .faq-picker-heading { margin-bottom: 19px; }
/* A 52px pitch on a 42px button, so 10 between them, not the desktop 28. */
html[data-device="phone"] .faq-picker-list { gap: 10px; }

/* The card's button. Measured on the live card at 320: the <a> is 120x42,
   centred (x=100 in a 320 viewport), 1px white on a 10px radius, with the
   label at 14px on 1.4px of tracking and its 42px coming from 12px of padding
   round an 18px line rather than from a line-height. Ours was 205 wide, left
   at x=29, 40 tall off `line-height: 38px`, and tracked 0.84. */
html[data-device="phone"] .btn-outline {
  display: block;
  width: 120px;
  max-width: none;
  height: auto;
  /* The source's button is a fixed 120x42 with no padding of its own. Ours
     builds that height from 10px of padding either side of the line box, which
     needs the line box to be 20 -- `normal` was assumed to give that and gives
     18 for the self-hosted Montserrat, so the button came out 40. Stated
     rather than inherited, because it is the one number the 42 depends on. */
  padding-block: 10px;
  line-height: 20px;
  letter-spacing: 1.4px;
  margin-inline: auto;
  box-sizing: border-box;
}

/* The insight index's type, measured on the live page at 320. Each of these is
   a desktop or tablet number reaching the phone:

     .insights-intro    18/30.8 here against the source's 17/23.8
     .insights-latest   22/30.8 against 17/23.8
     .insight-card-title 22 against 21, on every card
     .practice-head h1  40.6 of leading against 42                          */
/* The hero subtitle. The source's paragraph is 240 wide at x=40 and wraps to
   three lines; ours ran the container's full 280 at x=20 and wrapped to two. */
html[data-device="phone"] .practice-head.hero-insights .hero-sub {
  max-width: 240px;
  margin-inline: auto;
}

html[data-device="phone"] .insights-intro {
  font-size: 17px;
  line-height: 23.8px;
}
html[data-device="phone"] .insights-latest {
  font-size: 17px;
  line-height: 23.8px;
}
html[data-device="phone"] .insight-card-title { font-size: 21px; }
/* The stacked article card, measured against its own box on the live phone
   build. The source's card is 320 wide with its content inset 20, and runs a
   flat 10px between blocks with one exception -- 19 above "Read More":

       20  title           130  category      262  "Read More", 160x42 centred
      130  card top +20    166  standfirst    314  thumbnail, 190x98 centred

   The narrow-width rules above are a desktop measurement reflowed, which the
   comment on `.insight-card` says outright, and they put every block low and
   ran the thumbnail 280x137 against the source's 190x98 -- 39px a card, and
   ten cards to a page. */
html[data-device="phone"] .insight-card {
  gap: 10px;
  padding-top: 20px;
  padding-bottom: 20px;
}
html[data-device="phone"] .insight-card-section { margin-bottom: 10px; }
html[data-device="phone"] .insight-card-summary { margin-bottom: 19px; }
/* A 42px box round a 20px label, which is where the source's 19px of clearance
   above the thumbnail comes from. */
html[data-device="phone"] .insight-card-more {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 160px;
  height: 42px;
  margin: 0 auto;
}
html[data-device="phone"] .insight-card-thumb {
  display: block;
  width: 190px;
  max-width: 190px;
  margin-inline: auto;
}
html[data-device="phone"] .insight-card-thumb img { height: 98px; }
html[data-device="phone"] .practice-head.hero-insights h1 { line-height: 42px !important; }

html[data-device="phone"] .insight-section-card {
  grid-template-columns: 1fr;
  min-height: 0;
}
html[data-device="phone"] .insight-section-icon {
  width: 90px;
  justify-self: center;
}
html[data-device="phone"] .insight-section-name {
  font-size: 19px;
  line-height: 26.6px;
  max-width: none;
}
/* The photo is the band itself here, not a taller layer cropped by it. The
   -145px offset exists to line the desktop crop up with the header above it,
   and on the mobile canvas there is nothing to line up with. */
html[data-device="phone"] .practice-head-photo {
  top: 0 !important;
  height: 100% !important;
}
/* Recorded per page, like the desktop banner. 30px/40.6px is the common value
   and not a site constant -- /telecommunications-law sets 25px/33.6px -- so it
   is only the fallback for a page with nothing recorded. !important because
   the phone-width block above sets both with !important to tame the per-page
   inline desktop sizes. */
html[data-device="phone"] .practice-head h1 {
  font-size: var(--ph-h1-size, 30px) !important;
  line-height: var(--ph-h1-lh, 40.6px) !important;
}

/* The mobile header is 134px on every page measured, laid out as two rows:
   wordmark and burger together on the first, the search field across the
   second. Ours was 143 and put the burger on a row of its own, because our
   wordmark renders 274px wide against the source's 246 and left no room beside
   it. Nine pixels does not sound like much, but the header sits above
   everything, so it was a constant offset on every band of every page.

   The arithmetic, from the source: 27 above the wordmark, 18 of wordmark, 25
   of gap, 32 of search field, 32 below -- 134. The wordmark starts at x=13 and
   the search field at x=32, so the two are not on a shared inset and the
   field carries its own. */
html[data-device="phone"] .header-inner {
  padding: 26px 20px 32px 13px;
  gap: 0;
  align-content: flex-start;
}
/* line-height 0 on the anchor: the wordmark is an 18px-tall image inside a
   text-flow box whose line box is taller than it, which floated it 11px down
   inside a row the burger had already fixed at 18. */
/* top: 0, undoing the desktop rule's 11px nudge -- that offset exists because
   the wordmark does not share a baseline with the desktop nav row, and there is
   no nav row here. It is `position: relative`, so the box stayed put and only
   the paint moved, which is why align-self could not correct it. */
html[data-device="phone"] .logo {
  display: block;
  line-height: 0;
  top: 0;
}
html[data-device="phone"] .logo img {
  width: 246px;
  height: auto;
}
/* The burger sets the height of the first row, so its 32px box -- 16 of rule
   plus 8 of padding either side -- was holding that row 14px taller than the
   wordmark beside it and pushing the whole header past 134. The source draws
   the same three bars in 18. */
/* The opened menu. The source's phone nav is not the desktop nav reflowed: it
   is 18px Montserrat Bold on a 28px line, in a 28px row inset 16px, with no
   pill around it. Ours carried the desktop shape down -- Nunito Sans Light at
   16/19 inside a 5px border and 12/8 of padding, which is a 49px row -- so the
   menu read as a different design rather than the same one narrower.

   Measured on the live menu at 320: rows at y=77, 105, 133, 161, 189 and 217,
   so a 28px pitch, each box 28 tall at x=18 with its text starting at x=34.

   The Nunito Sans Light substitution above is a DESKTOP decision, standing in
   for the Avenir Light the desktop nav uses and we cannot license. The phone
   nav is Montserrat Bold on the source, which is a face we ship, so nothing
   needs substituting here. */
/* 24px of inset on the list and a 1px rule under each item. The source insets
   18 and has neither -- its rows sit on an exact 28px pitch, which a border
   would make 29. With the 16px inside the row above, the label then starts at
   x=34 as the source's does. */
html[data-device="phone"] .nav-list { padding-inline: 18px; }
html[data-device="phone"] .nav-list > li { border-bottom: 0; }

html[data-device="phone"] .nav-list > li > .nav-top {
  border: 0;
  border-radius: 0;
  padding: 0 0 0 16px;
  font-family: var(--body);
  font-size: 18px;
  font-weight: 700;
  line-height: 28px;
}

html[data-device="phone"] .nav-toggle {
  width: 22px;
  height: 20px;
  padding: 0;
  gap: 7px;
  align-content: start;
  align-self: flex-start;
  position: relative;
}
/* The glyph is 22x20 and the source's is the same size, but the source's BUTTON
 * is 37x50 -- measured on the live phone build of an insight article, at
 * x=270..307 y=11..61 against ours at x=278..300 y=26..46, the same centre to
 * half a pixel. So the bars are right and only the target is short: 440px2
 * against 1850, under a quarter, and under half the 44x44 minimum of WCAG
 * 2.5.5, hard against the right edge of a 320 canvas.
 *
 * A client reviewer reported the menu as not opening at all on her phone. It
 * opens correctly under a synthetic click, so what she hit was the target size.
 *
 * Absolutely positioned, which keeps it out of flow: the button is a grid, and
 * an in-flow ::before would become a grid item and push the bars down. This
 * grows the hit area around the existing centre and changes no layout. */
html[data-device="phone"] .nav-toggle::before {
  content: "";
  position: absolute;
  inset: -15px -7.5px;
}
html[data-device="phone"] .nav-toggle span {
  width: 22px;
  height: 2px;
  background: rgb(38, 48, 89);
  /* The source rotates the bars into the X over a quarter second rather than
     swapping the glyph: sampled on live, its bars pass through -0.39deg at 0ms
     and -10.4deg at 60ms on the way to 45. Without this ours jumped straight
     to the final transform, which reads as the icon changing rather than
     folding. */
  transition: transform .25s ease-in-out, opacity .25s ease-in-out;
}
@media (prefers-reduced-motion: reduce) {
  html[data-device="phone"] .nav-toggle span { transition: none; }
}

/* The intro band. Its paragraphs already matched the source exactly at 18/27
   -- same widths to the pixel, same heights -- and the entire 119px it was
   running low came from two places above them: an 88px top inset where the
   source uses 19, and a hook set 1.6px larger than the source's, which was
   just enough to wrap it onto a third line.

   24px/28.8px is the source's, and !important for the same reason as the
   banner title: the phone-width block sets it with !important. */
html[data-device="phone"] .practice-body {
  padding-top: var(--ph-body-pad-top, 19px);
  padding-bottom: var(--ph-body-pad-bottom, 33px);
}
/* Type on this canvas is recorded per page, like the desktop scale: the
   source runs body copy at 16px/28.8 on /zoning, 18/27 on /car-accidents and
   14/19.6 on /corporate-law -- thirteen distinct sizes across the family. The
   desktop numbers were being used here, and the error scaled with how much
   copy a page carried: +188 on /zoning, +594 on /banking-and-finance.

   No !important anywhere below. It was needed when these measurements were
   inline `style` attributes; they are custom properties now, so the ordinary
   cascade does the work. */
html[data-device="phone"] .practice-hook {
  font-size: var(--ph-hook-size, 24px);
  line-height: var(--ph-hook-lh, 28.8px);
  /* Recorded per page: the source leaves 10px under the lead-in on
     /employment-and-labor-law, where the 13 this fell back to is one page's
     number carried across the family. */
  margin-bottom: var(--ph-hook-gap-below, 13px);
  max-width: none;
  min-height: 0;
}
html[data-device="phone"] .practice-body p,
html[data-device="phone"] .practice-body li {
  /* The paragraph's own phone value first, then the page's, then its desktop
     value. A page does not use one size on this canvas -- /estate-planning
     maps its desktop 16 -> 16, 18 -> 17 and 20 -> 13 -- so a single page-level
     number left several pages hundreds of pixels short. */
  font-size: var(--ph-p-size, var(--ph-body-size, var(--p-size, 16px)));
  line-height: var(--ph-p-lh, var(--ph-body-lh, var(--p-lh, 28.8px)));
  /* The paragraph's own phone tracking, recorded by record_phone_type. It does
     not fall back through `--p-track`, which is a desktop measurement: /trusts
     tracks this copy 0.9px at 1440 and 0.8 at 320. */
  letter-spacing: var(--ph-p-track, normal);
}
/* The gaps around a stacked block, recorded per block on this canvas. The
   desktop values are mesh coordinates and do not transfer:
   /employment-and-labor-law leaves 51px over its second intro block and 70
   over its second closing block at 1440, where the phone build leaves 10 and
   27. `practice-block-ph-gaps` is on the blocks record_phone_type has measured
   here; the rest keep the desktop rule until they are measured too. */
html[data-device="phone"] .practice-block-ph-gaps {
  margin-top: var(--ph-b-gap-above, 0);
}
html[data-device="phone"] .practice-block-ph-gaps .block-heading {
  margin-bottom: var(--ph-b-gap-below-heading, 12px);
}
/* A block's list carries its own recorded phone type, which the page-level
   rule above was overriding: /employment-and-labor-law sets its five lists at
   16/22.4, 12/16.8, 17/23.8 and 18/25.2 on this canvas and all five painted at
   that page's body 14/19.6. Recorded per block by record_phone_type.pair_items
   and emitted by partials/_practice_block.html. Unscoped, because the closing
   row's blocks sit in .practice-closing-cols rather than .practice-body and
   were taking their DESKTOP item size; the panel's list keeps the rule written
   for it further down, which outranks this one. */
html[data-device="phone"] .block-list li {
  font-size: var(--ph-b-item-size, var(--ph-p-size, var(--ph-body-size, inherit)));
  /* The pitch the source paints, which is not the leading its span declares:
     Wix leaves the <li> at its own size with `line-height: normal`, so
     /employment-and-labor-law's 16px/22.4 items sit in 23px line boxes and its
     12/16.8 items in 18.8px ones -- 55px over that page's two intro lists. */
  line-height: var(--ph-b-item-pitch,
                   var(--ph-b-item-lh, var(--ph-p-lh, var(--ph-body-lh, inherit))));
}
/* A prose block's tracking on this canvas, recorded per block by
   record_phone_type.pair_prose. The source tracks these lines 0.8px on
   /estate-planning and 0.6px on /commercial-litigation; untracked, the six
   Spanish estate-planning paragraphs rewrapped 267px short. Unscoped for the
   same reason as the list rule above: these blocks paint in the closing row as
   well as in the body. */
html[data-device="phone"] .block-prose {
  letter-spacing: var(--ph-b-body-track, normal);
}
/* And the block's own measure, which the source sets per block rather than per
   page: /commercial-litigation runs four of its five closing blocks at 286px
   and the fifth at 280, where .practice-closing-cols gives them all 280. */
html[data-device="phone"] .practice-block {
  width: var(--ph-b-body-width, auto);
  max-width: none;
}
/* The closing row is a desktop mesh: two columns whose blocks are positioned
   by a recorded pitch. The phone build stacks them in one column in y order,
   so both the second track and the pitch have to go -- carrying the pitch
   here added a desktop block-height of empty space under every block. */
html[data-device="phone"] .practice-closing-cols {
  display: flex;
  flex-direction: column;
  column-gap: 0;
  row-gap: 0;
  padding-top: var(--ph-sec-gap-above, 20px);
  padding-bottom: var(--ph-sec-gap-below, 33px);
}
/* The column and slot wrappers exist to carry the desktop mesh's tracks and
   pitch, both of which the rule above drops; collapsing them makes every
   closing block a direct child of the flex column, which is what lets a block
   from the second column sort between two from the first. */
html[data-device="phone"] .practice-closing-col,
html[data-device="phone"] .practice-closing-slot { display: contents; }
/* The stacking order the source uses on this canvas, recorded per block by
   record_phone_type.rank_closing. It is not derivable from the desktop
   columns: /estate-planning flattens right column first and
   /commercial-litigation left first. A page with no recorded rank leaves every
   block at 0 and so keeps document order. */
html[data-device="phone"] .practice-closing-cols .practice-block {
  order: var(--ph-b-order, 0);
}
/* A flex item does not collapse margins with its children, so the trailing
   paragraph's 16px bottom margin -- which used to escape the block -- started
   counting toward its height and ran every /estate-planning closing block 16px
   tall. The gap between blocks is `--ph-b-gap-above` on the one below. */
html[data-device="phone"] .practice-closing-cols .practice-block > :last-child {
  margin-bottom: 0;
}
/* The heading's own recorded phone value first. This is a closing-column
   heading, not a panel one, and standing the panel's number in for it painted
   /tax-assessment's at 18px/21.6 where the source sets 17/30.6. */
html[data-device="phone"] .practice-closing-cols .block-heading {
  font-size: var(--ph-b-heading-size, var(--ph-types-heading-size, 20px));
  line-height: var(--ph-b-heading-lh, var(--ph-types-heading-lh, 24px));
  font-weight: var(--ph-b-heading-weight, var(--b-heading-weight, 700));
}
html[data-device="phone"] .practice-closing-cols .block-prose {
  font-size: var(--ph-p-size, var(--ph-body-size, 16px));
  line-height: var(--ph-p-lh, var(--ph-body-lh, 28.8px));
}
html[data-device="phone"] .practice-secondary {
  padding-top: var(--ph-sec-gap-above, 20px);
  padding-bottom: var(--ph-sec-gap-below, 33px);
}
/* The item, not just the list. The closing band carries `practice-body`, so
   the generic phone rule for `.practice-body li` above sets the item's size
   directly and beats anything inherited from the <ul>. */
html[data-device="phone"] .practice-results,
html[data-device="phone"] .practice-results li {
  font-size: var(--ph-results-size, var(--results-size, inherit));
  line-height: var(--ph-results-lh, var(--results-lh, inherit));
  /* The phone build's own tracking, recorded by record_phone_type. It does not
     fall back through the desktop token: /truck-accidents tracks these lines
     0.8px on desktop and 0.6px at 320. */
  letter-spacing: var(--ph-results-track, normal);
}
html[data-device="phone"] .practice-secondary-heading {
  font-size: var(--ph-sec-size, 24px);
  line-height: var(--ph-sec-lh, 28.8px);
  margin-bottom: var(--ph-sec-gap-below-heading, 10px);
}
html[data-device="phone"] .practice-secondary-cta {
  margin-top: var(--ph-sec-cta-gap, 23px);
  width: auto;
}
html[data-device="phone"] .practice-secondary p {
  font-size: var(--ph-p-size, var(--ph-closing-size, var(--ph-body-size, 16px)));
  line-height: var(--ph-p-lh, var(--ph-closing-lh, var(--ph-body-lh, 28.8px)));
}

/* The split band stacks here. On desktop it is a photograph and a navy panel
   side by side in a fixed-height grid; the source's mobile build puts the navy
   panel first at full width and drops the photograph below it as a strip, so
   the two columns become two rows and the recorded desktop height has to go.

   Everything inside centers, which desktop does not: the heading is 20/24 and
   the list 14/21, both centered, against 33/39.6 and 18/27 ranged left. Those
   are the source's numbers, and they are why the list occupied 322px there and
   270 here. */
html[data-device="phone"] .types-split {
  grid-template-columns: 1fr;
  height: auto;
  padding-top: 0;
  /* The navy belongs to the panel here, not to the split. At two columns the
     split's fill sits behind both halves and the photograph covers its own; at
     one column it stretches behind panel AND photograph, painting a single
     navy band 638px tall where the source paints 357 -- the panel alone. That
     281px was the largest single defect on the phone build, on 34 pages.
     .types-photo carries its own background-color and wash, so it does not
     need the fill underneath it. */
  background: none;
}
/* The panel's own height and inset are recorded: 163px around three items on
   /guardianships, 358 around nine on /car-accidents. Left to the desktop
   padding it ran ~210px tall on every page. */
html[data-device="phone"] .types-panel {
  background: var(--navy-deep);
  order: 1;
  min-height: var(--ph-panel-height, auto);
  padding-top: var(--ph-panel-pad-top, 18px);
  box-sizing: border-box;
}
/* The recorded height is the band's, and the source spends its last 28px on a
   plain --navy strip rather than on the photograph: on /corporate-law the
   picture runs y=2361..2575 and navy 2575..2603, and on /car-accidents
   2251..2503 and 2503..2531. The same 28 on /workers-compensation (229 in 257)
   and /commercial-litigation (252 in 280).

   A border rather than a shorter height, because this band is a cover crop:
   `background-size: cover` resolves against the padding box, so the border both
   paints the strip and stops the extra 28px re-framing the picture. Left as
   height alone, every one of these photographs was cropped tighter than the
   source's -- 320x242 against 320x214 on /corporate-law. */
html[data-device="phone"] .types-photo {
  order: 2;
  height: var(--ph-photo-height, 280px);
  border-bottom: 28px solid var(--navy);
}
/* Alignment is per page, not a property of the canvas: /workers-compensation
   centers its panel and /tax-assessment ranges it left. Hardcoding `center`
   from the first page looked right until the second one was checked. */
html[data-device="phone"] .types-panel-inner {
  width: auto;
  padding-inline: 15px;
  text-align: var(--ph-panel-align, center);
}
/* The block's own recorded value first, then the band's. The panel's heading
   is a block heading wherever `panel_block` fills the band, and standing the
   page-level panel size in for it painted /employment-and-labor-law's at
   18px/21.6 against the source's 16/19.2. */
html[data-device="phone"] .types-panel h2,
html[data-device="phone"] .types-panel .block-heading {
  font-size: var(--ph-b-heading-size, var(--ph-types-heading-size, 20px));
  line-height: var(--ph-b-heading-lh, var(--ph-types-heading-lh, 24px));
  margin-bottom: 17px;
}
/* A block heading outside the panel keeps its own recorded phone value, then
   its desktop one. The two canvases do not agree: /employment-and-labor-law
   sets these at 23px/27.6 on desktop and 18/21.6 here. */
html[data-device="phone"] .block-heading {
  font-size: var(--ph-b-heading-size, var(--b-heading-size, inherit));
  line-height: var(--ph-b-heading-lh, var(--b-heading-lh, inherit));
  font-weight: var(--ph-b-heading-weight, var(--b-heading-weight, 700));
}
/* The panel's list, and only lists inside the panel. A block sitting under the
   intro copy or in the closing row is not panel content and does not take the
   panel's type: /tax-assessment's closing list runs 30.6px leading on this
   canvas and was being painted at the panel's 19.6. Blocks outside the panel
   fall through to the body rule above, which is where they belong. */
html[data-device="phone"] .types-list li,
html[data-device="phone"] .types-panel .block-list li {
  font-size: var(--ph-types-size, 14px);
  line-height: var(--ph-b-item-pitch, var(--ph-types-lh, 21px));
  min-height: 0;
  margin-left: var(--ph-b-item-indent, 0);
}
html[data-device="phone"] .block-list li { min-height: 0; }
/* Markers and their hang are recorded, not assumed. A centered panel shows
   none; /tax-assessment ranges left and keeps its discs with a 22px hang, and
   dropping them lost the bullets from that page's list entirely. */
html[data-device="phone"] .types-list {
  list-style: var(--ph-panel-list-marker, none);
  margin-left: 0;
}
html[data-device="phone"] .types-list li {
  margin-left: var(--ph-panel-list-indent, 0);
}
/* Fourteen pages build this panel from a practice block, which emits
   `.block-list` rather than `.types-list`, so the recorded marker never reached
   them and /real-estate-law painted eight items with no bullets at all. Every
   one of the fourteen records `disc`, and the source ranges these lists left on
   each page measured -- /real-estate-law, /trusts, /bike-accidents and
   /commercial-litigation. */
html[data-device="phone"] .types-panel-inner .block-list {
  list-style: var(--ph-panel-list-marker, none);
  margin-left: 0;
}
html[data-device="phone"] .types-panel-inner .block-list li,
html[data-device="phone"] .types-list-bulleted li {
  margin-left: var(--ph-panel-list-indent, 0);
  text-align: start;
}
/* The list's own column and hang, recorded per block. Wix positions each list
   itself rather than insetting it from the page: /employment-and-labor-law's
   four lists run at margins of 9, 7, 7 and 8.5px with hangs of 23.4, 18.2 and
   22.1, and one shared inset made every item 8 to 10px wider than the source's
   -- enough to lose a wrapped line from three of them. */
html[data-device="phone"] .block-list {
  list-style: var(--ph-list-marker, none);
  margin-left: var(--ph-b-list-margin, 0);
  width: var(--ph-b-list-width, auto);
  box-sizing: border-box;
}
html[data-device="phone"] .block-list li {
  margin-left: var(--ph-b-item-indent, var(--ph-list-indent, 0));
}
html[data-device="phone"] .types-prose {
  font-size: var(--ph-types-size, 14px);
  line-height: var(--ph-types-lh, 19.6px);
}

/* ---------------------------------------------------------------------------
   Homepage, phone canvas.

   Every number below was read off the live mobile build at 320. It is not the
   desktop page reflowed: the type scale is different in every band, and the
   hero puts its blocks in a different order. Reference geometry --

     hero       134-641    motto      693-757    story     757-1111
     billions  1111-1559   wins      1559-1830   practice  1830-1904
     rows      1904-3568   form      3568-4589   call      4589-4957

   Live totals 6276. Bands are not given explicit heights here: they are the
   sum of their content at these sizes, and pinning them is what broke this
   page in the first place.
   --------------------------------------------------------------------------- */

/* Both HKQ-LAW1 lockups take the same 20px inset the rest of the mobile build
   uses -- measured at x=20, 280 wide, in the hero and again in the call band.
   The narrow-width block sets them to 100%, which is right for a desktop
   window dragged narrow but runs them edge to edge on the phone canvas. */
html[data-device="phone"] .home-call-number img {
  width: 280px;
}
/* 227, not 280. The source wraps this one in a 280-wide box and draws the card
   227 wide inside it -- its inner svg measures 227x32, which is exactly our
   file's own 1170x165 viewBox ratio, so the artwork is the same and only the
   scale differs. At 280 ours came out 39 tall and pushed the rest of the hero
   down with it. The call band's lockup really is 280 wide; its file is a
   different shape (1074x123) and matches the source at that size. */
html[data-device="phone"] .home-phone img {
  width: 227px;
}

/* The hero reorders. On desktop it reads lead, phone card, strapline,
   substrap, button, group photo; the mobile build leads with the phone number
   and lifts the Contact Us button above the headline, so the two things a
   visitor on a phone is most likely to want come first. Source order, by
   measured y: card 154, Click to Call 200, lead 236, button 309, strapline
   369, substrap 411, group 491. */
html[data-device="phone"] .home-hero {
  display: flex;
  flex-direction: column;
  padding-top: 20px;
  /* 10 below the contact button, which now occupies the 72 this used to hold
     open on its own. The source runs the band to 641 and opens the motto
     at 693. */
  padding-bottom: 10px;
}
html[data-device="phone"] .home-phone { order: 1; }
html[data-device="phone"] .home-lead { order: 2; }
html[data-device="phone"] .home-cta { order: 3; }
html[data-device="phone"] .home-strapline { order: 4; }
html[data-device="phone"] .home-substrap { order: 5; }
html[data-device="phone"] .home-group { order: 6; }

/* Gaps between the hero's blocks, from the source's own y values:
   card 154, note 200, lead 236, button 309, strapline 369, substrap 411,
   group 491. The desktop card carries a 23px top margin that has to go, or
   everything below it starts 23px low. */
html[data-device="phone"] .home-phone { margin-top: 0; }
/* The overlay is desktop only. On the source's 320 build the card is 32px tall
   and ends at 186, and the label follows it in flow at y=200 -- so the desktop
   absolute placement and 115px width have to be restated away here. */
html[data-device="phone"] .home-phone-note {
  position: static;
  width: auto;
  margin: 11px 0 0;
  font-size: 14px;
  line-height: 25.2px;
}
html[data-device="phone"] .home-lead { font-size: 15px; line-height: 27px; margin: 10px 20px 0; }
html[data-device="phone"] .home-cta { margin: 18px 0 0; }
/* 269x32, not the desktop 374x62 -- 374 is wider than the canvas. Measured off
   the live button on a 320 canvas, where it sits at x=25; this was 280x44. The
   label keeps the desktop 16px/700/1.6px, which the source also does. */
html[data-device="phone"] .home-btn { width: 269px; max-width: 269px; height: 32px; }
/* "Get help now" is a different size from the hero button on the phone, where
   on desktop it is a different size again (241x40). It carries .home-btn for
   the shared type and fill, so it has to undo the line above. */
html[data-device="phone"] .home-btn-light {
  width: 240px;
  max-width: 240px;
  height: 42px;
}
/* The 629px block and its off-center placement are desktop only: on the
   source's 320 build these two lines center on the canvas, so the width has to
   be restated away here as well as the margin. */
html[data-device="phone"] .home-strapline { width: auto; font-size: 13px; line-height: 20.8px; margin: 31px 20px 0; }
/* 21.5px leading, measured: the source runs these two lines in 43px where a
   24px leading gives 48. The 24 was carried by a 0 top margin absorbing the
   gap the source puts above this paragraph; both are now their own number. */
html[data-device="phone"] .home-substrap { width: auto; font-size: 15px; line-height: 21.5px; letter-spacing: normal; margin: 2px 20px 0; }
/* 331 wide against a 320 canvas, sitting at x=-6. The source lets this one
   bleed 6px past each edge rather than fitting it, and body's overflow clip
   keeps that from widening the canvas. */
html[data-device="phone"] .home-group {
  width: 331px;
  max-width: none;
  height: 130px;
  object-fit: cover;
  margin: 34px 0 0 -6px;
}
html[data-device="phone"] .home-group-fade { order: 7; height: 51px; margin-top: -51px; }
/* 120x42 at x=100, against the desktop build's 62x62 circle at the right edge.
   The 20px above and 10 below account for the 72 the hero used to carry as
   padding, so the motto still opens at 693. */
html[data-device="phone"] .home-contact-dot {
  order: 8;
  position: static;
  width: 120px;
  height: 42px;
  margin: 20px auto 0;
}

/* One line at 19px, in a 64px band -- against 40px over three lines. */
html[data-device="phone"] .home-motto { padding-top: 20px; padding-bottom: 20px; }
/* 301 wide and centered, with no inline padding: that is the source's block,
   and the string measures 279 inside it, so it sets one line as the source
   does. It was resolving to a 320px CONTENT box plus 19px of padding either
   side -- 384 in a 320 canvas -- which wrapped it to two and made the band 88
   tall against 64. */
html[data-device="phone"] .home-motto p {
  font-size: 19px;
  line-height: normal;
  text-align: center;
  box-sizing: border-box;
  width: 301px;
  max-width: 100%;
  padding-inline: 0;
  margin-inline: auto;
}

/* Centered, not ranged right. The desktop band sets its copy in a column on
   the right of the photograph and aligns it to that edge; the mobile band runs
   full width and centers -- the source's heading sits at x=87 w=146, dead
   center of the 320 canvas, where ours was pinned to the right margin. */
html[data-device="phone"] .home-story-inner { padding: 20px; text-align: center; }
/* 14px under the heading, against the desktop 38. That 24px difference was the
   whole of this band's excess height, and it carried into every band below. */
html[data-device="phone"] .home-story h2 { font-size: 28px; line-height: normal; margin: 0 0 14px; }
/* 26, the leading the source USES: its eight lines measure 208. The 27 it
   declares is on a block whose spans each carry their own. */
html[data-device="phone"] .home-story p { font-size: 15px; line-height: 26px; }
/* On the anchor, not the paragraph: `.home-story-more a` sets 45px, so a rule
   on the paragraph alone left the mark at 45 and 52px tall against the
   source's 36 and 43. `line-height: normal` for the same reason -- 27px is
   inherited from the band and the source lets the glyph set its own box. */
html[data-device="phone"] .home-story-more a { font-size: 36px; line-height: normal; }
/* 14px under the copy, not 30. `!important` only because the desktop rule
   carries one; it is not a specificity fight worth having twice. */
html[data-device="phone"] .home-story-more { margin-top: 14px !important; }

/* The billions band. Its copy runs the full 320 here where the source insets
   it to x=23, and the lockup sat 57px below the band's top against 20. */
/* Band offsets, from the source: lockup +20, tagline +62, copy +127, button
   +399, band closes at 448. */
html[data-device="phone"] .home-billions { padding-top: 20px; padding-bottom: 9px; }
html[data-device="phone"] .home-billions-mark { width: 280px; margin: 0 20px; }
html[data-device="phone"] .home-tagline { font-size: 16px; line-height: 28.8px; margin-top: 19px; }
/* The rule clears the tagline here rather than underlining it, and runs the
   width of the band's copy instead of the desktop 184. */
html[data-device="phone"] .home-tagline-rule { width: 280px; height: 11px; margin-top: 12px; }
html[data-device="phone"] .home-billions-body {
  font-size: 15px;
  line-height: 27px;
  margin-top: 13px;
  padding-inline: 23px;
}
/* The button sits in a bare <p>, so its own margin is not what spaces it --
   the paragraph's default margins are, and they collapse against the copy
   above. 29px on the paragraph, nothing on the anchor. */
html[data-device="phone"] .home-billions-body { margin-bottom: 0; }
html[data-device="phone"] .home-billions-body + p { margin: 29px 0 0; }

/* The source's mobile carousel has no arrows -- it is dots only, advanced by
   swipe. The two chevrons are a desktop control. */
html[data-device="phone"] .home-wins-arrow { display: none; }
/* No white below the gold. The narrow-width block gives this section 50px of
   padding-bottom, which showed as a white strip between the band and "Our
   Practice Areas."; the source runs the two together. */
html[data-device="phone"] .home-wins { padding-bottom: 0; }
/* The gold band's own spacing, measured off the source band top to bottom:
   label at 24, the rule 14 under it, the amount 9 under that, the detail 12,
   the dots 61, and the band closes 22 below them -- 271 in total against the
   303 these came out at. Every one of the six was a desktop number that no
   phone rule replaced. */
html[data-device="phone"] .home-wins-inner { padding-top: 24px; padding-bottom: 22px; }
html[data-device="phone"] .home-wins-rule { margin-top: 14px; }
html[data-device="phone"] .home-wins-dots { margin-top: 61px; }
html[data-device="phone"] .home-wins-label { font-size: 16px; }
/* The amount takes two lines on the source -- "$25,000,000" over
   "Settlement" -- because its box is far narrower than the band. */
html[data-device="phone"] .home-win-amount {
  font-size: 27px;
  /* 33.5: the source's two lines measure 67, not the 70.2 that 35.1 gives. */
  line-height: 33.5px;
  max-width: 200px;
  /* 9px under the rule, not the desktop 20. */
  margin: 9px auto 0;
}
html[data-device="phone"] .home-win-detail {
  font-size: 13px;
  line-height: normal;
  max-width: 230px;
  /* 12px under the amount, not the desktop 23. */
  margin: 12px auto 0;
}

/* 20 and 20, so the strip is the source's 74 tall. The base rule's 28 and the
   980-and-under block's matching padding-bottom reached this build unopposed
   and made it 88. */
html[data-device="phone"] .home-practice-band { padding-top: 20px; padding-bottom: 20px; }
html[data-device="phone"] .home-practice-band h2 { font-size: 28px; line-height: normal; }

/* The rows reorder too: icon, heading, photograph, button, copy. On desktop
   the copy sits beside the photograph, so it reads icon, heading, copy,
   photo; dropping straight to one column left the button stranded under the
   copy where the source puts it directly under the picture. */
/* 14, so the first block's icon starts 74px below the top of "Our Practice
   Areas." as it does on the source. Measured heading-top to icon-top, because
   the source's heading is an inline span and ours a block, and their bottoms
   are not the same measurement. */
html[data-device="phone"] .home-practice { padding-top: 14px; padding-bottom: 40px; }
/* `gap: 0`, because every child below carries its own measured margin. The
   980-and-under media query sets `gap: 20px` on this row for the narrow desktop
   grid, and the phone margins were measured off the source and written as if it
   were not there -- so all three gaps in the column came out 20px over: 32
   where the source has 12, 26 where it has 10, 53 where it has 33. */
html[data-device="phone"] .home-practice-row {
  display: flex;
  flex-direction: column;
  gap: 0;
  /* 0, 3 and 8: the source opens each row a different distance below the one
     above, as it does everything else in this section. */
  margin-top: var(--row-gap-phone, 0);
}
/* `display: contents` so the icon, heading and copy become direct children of
   the row and can be ordered against the photograph between them. */
html[data-device="phone"] .home-practice-text { display: contents; }
/* 40 wide, not the 35 the img attributes carry for desktop: the source draws
   these larger on the phone. Height follows the artwork, which is how the third
   icon reaches the source's 40x38 from a 35x33 file. */
html[data-device="phone"] .home-practice-icon {
  order: 1;
  /* Per block, like the desktop --icon-gap beside it: the source clears its
     icon by 12, 21 and 34px before the heading. A flat 12 put the second
     heading 21px high and the third 27px high. */
  margin: 0 auto var(--icon-gap-phone, 12px);
  width: 40px;
  height: auto;
}
/* 10px under the heading, which is the source's gap to the photograph. */
html[data-device="phone"] .home-practice-text h3 { order: 2; margin: 0 20px 10px; }
html[data-device="phone"] .home-practice-media { order: 3; position: relative; }
/* 175 tall on the phone, which the source reaches by cropping rather than by
   scaling: at 320 wide these files scale to 199-205 and that height compounds
   down the page. The picture runs 2010 to 2185 on the source, the same 175. */
html[data-device="phone"] .home-practice-media > img {
  /* Width as well as height. The column centers its children, so the media box
     is shrink-to-fit: with only a height set, `width: 100%` resolved against a
     container the image's own aspect ratio had already sized, and all three
     came out 273-281 instead of the canvas's 320. */
  width: 320px;
  height: 175px;
  object-fit: cover;
}
/* 21 left, 19 right on the second and third blocks; the first sits at 18/22,
   below. All three measure 280 either way -- the source is not indenting the
   column, it placed each block by hand. */
html[data-device="phone"] .home-practice-text p { order: 5; margin: 33px 19px 0 21px; }
html[data-device="phone"] .home-practice-row:nth-of-type(1) .home-practice-text p {
  margin-left: 18px;
  margin-right: 22px;
}
/* The button stays over the photograph, as it is on desktop and as the source
   keeps it here -- its label sits at y=2142 inside a picture running 2010 to
   2185. Only the placement changes: the recorded --btn-x/--btn-y are desktop
   coordinates, so it centers and is set against the photograph's bottom edge
   instead. That clearance is per block like every other number in this
   component -- 16, 12 and 32px measured on a 320 canvas, where a flat 19 put
   the first three, seven and thirteen pixels out. */
html[data-device="phone"] .home-practice-btn {
  position: absolute;
  left: 50%;
  top: auto;
  bottom: var(--btn-bot-phone, 19px);
  transform: translateX(-50%);
  /* Per block, and not the desktop --btn-w: the source sizes these three at
     286, 256 and 286 on the phone against 334, 334 and 365 on desktop. A flat
     280 here made all three the same width and all three wrong. */
  width: var(--btn-w-phone);
  max-width: var(--btn-w-phone);
  height: 42px;
  margin: 0;
}

html[data-device="phone"] .home-practice-text h3 {
  font-family: var(--display);
  font-size: 20px;
  line-height: 28px;
}
/* 20.8, measured: ten lines at 208 and twelve at 250 on the source. */
html[data-device="phone"] .home-practice-text p { font-size: 15px; line-height: 20.8px; }

html[data-device="phone"] .home-form { padding-top: 28px; }
html[data-device="phone"] .home-form h2 { font-size: 17px; line-height: normal; }
/* 280, not the desktop 284: the source's rule runs x=17..297 on the 320 canvas
   and the same 7px box carries the same 3px navy border. */
html[data-device="phone"] .home-form-rule { width: 280px; }
/* Measured inside the source's form band: the embed's top sits 167px below the
   band's, and 119 of that is the run from the heading's foot -- the rule, this
   paragraph at 23.5 leading, and the space either side of it. 43 here is what
   makes that run 119; the sub's own margin cannot be read off the source
   separately, because its paragraph is a stack of spans there and one block
   here. What is measured, and what this reproduces, is where the embed lands. */
html[data-device="phone"] .home-form-sub {
  font-size: 17px;
  line-height: 23.5px;
  /* Two lines, breaking after "consultations", as the source sets it. */
  max-width: 230px;
  margin: 43px auto 0;
}
html[data-device="phone"] .home-form .intake-form { margin-block: 16px 0; }
/* 269 wide at x=25, and 788 tall rather than the desktop 1202. */
html[data-device="phone"] .home-form .intake-form iframe {
  width: 269px;
  height: 788px;
  min-height: 788px;
  margin-inline: auto;
}

/* The language selector belongs in the flow here, 86x26 and centered, 15px
   under the form and 91 above the call heading. On desktop it is absolutely
   placed at top:1081px over the blank lower part of the embed, and nothing
   overrode that for the phone -- so it kept a desktop coordinate, landed 1081px
   down the section, and painted across "1-888-HKQ-LAW1" in the band below.
   The 66px of padding on .home-call was the space it should have occupied. */
html[data-device="phone"] .home-form .locale-select {
  position: static;
  /* Block, so the section's padding below is the whole gap. Left inline it
     sits on a baseline and the line box adds two more pixels under it. */
  display: block;
  width: 86px;
  height: 26px;
  margin: 15px auto 0;
}
/* 25px of WHITE below the selector before the navy starts. The 91px between
   the selector and the call heading is split by the band edge -- 25 of it in
   this section and 66 in the one below -- and setting the whole 91 as the navy
   band's padding put the colour change right under the selector. Padding
   rather than a margin on the selector, which would collapse out of the
   section and paint nothing. */
html[data-device="phone"] .home-form { padding-bottom: 25px; }
html[data-device="phone"] .home-call { padding-top: 66px; }
html[data-device="phone"] .home-call h2 { font-size: 20px; line-height: normal; }
html[data-device="phone"] .home-call-phone { font-size: 24px; line-height: 33.6px; margin-top: 20px; }

/* The footer carries its own type scale on the mobile build -- not the desktop
   sizes reflowed, a different set of numbers, all measured off the source:

     story heading   23px / 29.9px   against 36 / 46.8
     story body      15px / 22.5px   against 16 / 24
     "Let's Talk."   27px / 35.1px   against 42 / 52
     contact rows    12px            against 16

   This is the whole footer on every page, so it is the single highest-leverage
   block in the phone build. */
html[data-device="phone"] .footer-card h2 {
  font-size: 23px;
  line-height: 29.9px;
}
html[data-device="phone"] .footer-card p {
  font-size: 15px;
  line-height: 22.5px;
  /* 18 down to the buttons, against the desktop card's 23. */
  margin-bottom: 18px;
}
html[data-device="phone"] .footer-talk h2 {
  font-size: 27px;
  line-height: 35.1px;
}
html[data-device="phone"] .footer-contact,
html[data-device="phone"] .footer-office,
html[data-device="phone"] .footer-row {
  font-size: 12px;
  line-height: 16.8px;
}

/* Footer geometry. The desktop band is 962px of photograph with the card
   inset 174px down and held open to 405; the source's mobile band is 421 all
   in, with the card's copy starting 40px down and running to x=47. Left at
   the desktop numbers this one band was 282px long on every page. */
/* 423px on the source against our 437: 14px of it was in the bottom inset. */
html[data-device="phone"] .footer-story {
  min-height: 0;
  padding-top: 20px;
  /* 27 below the card, which with the card at 374 gives the band its 421. */
  padding-bottom: 27px;
}
/* The navy overlay goes. It is a fixed 702px gradient -- solid at the top,
   clear by 76% -- sized for a 962px desktop band. Over a 421px mobile band it
   never reaches its transparent end, so the photograph behind it was almost
   entirely painted out: ours read as a dark panel with a sliver of picture at
   the bottom edge. The source shows the photograph plainly here, with only
   the white card over it. */
html[data-device="phone"] .footer-story::after { display: none; }
/* The photograph has to fill the band here too -- a narrow-width rule caps both
   layers at 200px, which left the picture covering only the top half of it with
   flat navy under it. That was fixed with `height: 100%`, which reintroduced
   the same symptom from the other direction as soon as the layer moved: the
   band's own height is not enough for a layer that travels, and the shortfall
   grows with the viewport (35px at 320x568, 295 at 390x844, 365 at 430x932).
   The shared rule's `max(100%, 100vh)` covers both cases -- see the derivation
   on `.footer-story-photo` -- so there is nothing to override here. */
html[data-device="phone"] .footer-card {
  min-height: 0;
  width: auto;
  /* 22 under the last button, not 30: with the card's parts at the source's
     sizes that closes its box at the source's 374. */
  padding: 20px 27px 22px;
}
/* The source's mobile talk band is 275 tall, all in. The desktop rule pins this
   band to 437 so that it and the 350px map fill the footer between them; that
   height is not overridden by anything else here, so on the phone it held 192px
   of empty white under the social row -- most of the 176px this footer ran long
   on every page. Height comes from the padding here rather than a second pinned
   number: 22 above the heading, 25 below the social row. */
html[data-device="phone"] .footer-talk {
  height: auto;
  padding-top: 22px;
  padding-bottom: 25px;
}
/* The desktop heading opens the band with a 54px top margin and closes with
   30. The source's mobile band starts it 21px down and runs the contact list
   19px under it. */
html[data-device="phone"] .footer-talk h2 { margin: 0 0 19px; }
/* 240, not 350: the source drops the map to a squarer box on the phone. */
html[data-device="phone"] .footer-map { height: 240px; }
/* The source sets the map off with 10px of the page's white on each side of it
   -- sampled on the live page, which paints white at y=1824 and y=2074 and the
   navy only from 2085. */
html[data-device="phone"] .footer-map { margin-block: 10px; }
/* The card's heading runs straight into its copy -- 2px, where the desktop
   card opens 39. */
html[data-device="phone"] .footer-card h2 { margin-bottom: 0; }
/* 144px buttons, not full width: the source's sit at x=47 and run 144, which
   puts their labels at x=63 and x=61. */
/* The buttons stack here, 42 tall on a 54px pitch. `.footer-card p` above is
   (0,2,2) and out-ranks the (0,2,1) rule that zeroes this element's margin on
   desktop, so the reset has to be repeated rather than inherited. */
html[data-device="phone"] .footer-card p.footer-card-links {
  margin: 0;
  gap: 12px;
}
/* 42, not the desktop 40: same 18px line and 2px borders, 10px of padding
   rather than 9. */
html[data-device="phone"] .footer-card p.footer-card-links a {
  /* 160, not 144. Both sit at x=47, so the 16px went half to each side and put
     the label 8px left of the source's -- "Meet Our Team" centred at 111 here
     against 119 there, with the text itself the same 112px wide. */
  width: 160px;
  padding-block: 10px;
}
/* The source leaves the label's leading alone; 18px on a 14px label is ours. */
html[data-device="phone"] .footer-card p.footer-card-links a > span {
  line-height: normal;
}
/* The credit runs a 261px measure on the source, centred, and ours ran 291 --
   which is a different wrap on the same words. */
html[data-device="phone"] .footer-credit {
  max-width: 261px;
  margin-inline: auto;
}
/* The Spanish labels do not fit the 160px button: "Conozca a nuestro equipo"
   measures 190.69px at 14px/700 Montserrat and "Vea nuestros resultados"
   175.86, against the 130px the button leaves a label (160 less two 2px
   borders, 2px of padding each side, the 4px gap and the 12px chevron). The
   source truncates them with an ellipsis; we widen the button to 215 instead
   -- 190.69 rounded up plus that same 24px of chrome -- which keeps the whole
   label and keeps the button on one line at the source's 42px height.

   The width is the deliberate departure and it is the cheaper one: letting the
   label wrap instead ran both buttons 60 tall and every Spanish page's footer
   story band 35px past the source's 496 (band_diff --phone, /es-us/tax-
   assessment, /es-us/bike-accidents, /es-us/estate-planning, /es-us/
   guardianships all read `worst dh 35px`). The card's content column is 226px
   wide at a 390 viewport, so 215 fits inside it. */
html[data-device="phone"][lang="es-US"] .footer-card p.footer-card-links a {
  width: 215px;
}

/* The contact list's label column is 184px on desktop, measured from a 980
   layout. Here the values start at x=93 against labels at x=20. */
html[data-device="phone"] .footer-contact {
  grid-template-columns: 73px 1fr;
  font-size: 12px;
  line-height: normal;
  /* 58px down to "Kingston Office:", against the 23 the desktop band uses. */
  margin-bottom: 58px;
}
html[data-device="phone"] .site-footer address { font-size: 12px; line-height: 16.8px; }
/* 27px icons on a 36px pitch, starting flush with the text column rather than
   11px left of it. */
/* `flex: none` on both, or the row does not get the 27px below: this list is a
   flex item in a narrower parent, so it shrank to 109px and each `img`, capped
   at `max-width: 100%` by the base rule, followed it down to 20.6. The source's
   row runs x=20..155, which is 4x27 with the 9px gaps. */
html[data-device="phone"] .footer-social { margin-left: 0; gap: 9px; flex: none; }
html[data-device="phone"] .footer-social li { flex: none; }
html[data-device="phone"] .footer-social img { width: 27px; height: 27px; }
/* The icons and the language control share one 27px row, 12px under the
   address, with the control at x=222. The desktop field is 45 tall and sits 4px
   below the icons' center line; both of those are desktop measurements and
   together they held this row 18px taller than the source's. */
/* Clipped, because the language control below overhangs the canvas: the source
   shows 222..320 of it and its own scrollWidth stays 320, so the overhang is
   cut rather than scrolled to. */
html[data-device="phone"] .footer-row { margin-top: 12px; gap: 67px; overflow: hidden; }
/* 111 wide, and `flex: none` so it keeps that: as a shrinkable flex item beside
   the 73px gap it came out 72. The source's control runs x=222..333 on a 320
   canvas -- it overhangs the right edge and is clipped there -- and the 67px
   gap is what puts its left edge at 222 after the icon row's x=20..155. */
html[data-device="phone"] .footer-row .locale-select {
  flex: none;
  width: 111px;
  height: 27px;
  top: 0;
}
/* The source does not carry the logo block into the mobile footer at all --
   its social row is followed straight by the map. Ours was rendering it at
   280x229, which is most of the difference in this band. */
html[data-device="phone"] .footer-logo-block { display: none; }

/* 20 above and 18 below, not 23 both ways. With the two paragraphs already the
   source's 47 and 36, that is the whole of the band's 121. */
html[data-device="phone"] .footer-legal {
  padding-top: 20px;
  padding-bottom: 18px;
  /* Both lines sit in a 280px column at x=20, not edge to edge. */
  padding-inline: 20px;
}
html[data-device="phone"] .footer-copyright { font-size: 13px; line-height: 23.4px; }
/* The credit runs straight off the copyright here; the 10px is a desktop gap. */
html[data-device="phone"] .footer-credit {
  font-size: 10px;
  line-height: 18px;
  margin-top: 0 !important;
}
/* flex-shrink 1, not the 0 the phone-width block sets. `flex-basis: 100%`
   resolves against the container's inner width and margins sit outside it, so
   with shrink disabled the field stayed 287px wide and the 19/13 margins had
   nothing to give: it ran past its own right inset instead of coming in to the
   source's 255. */
html[data-device="phone"] .header-search {
  height: 32px;
  margin: 24px 13px 0 19px;
  padding: 0 0 0 14px;
  gap: 12px;
  flex-shrink: 1;
}

/* The /in-the-news cards. Nothing here was phone-specific: the cards fell
   through to the `max-width: 768px` reflow, which is a narrow desktop card and
   not the build the source serves a phone. Measured on the live page, the
   mobile card is 282 wide and centered, with the photograph flush to its own
   border and only the copy inset:

       card    282x395 at x=19, a 1px border and no padding
       photo   280x169 flush, then 18
       title   240 wide at x=40, 56 tall, then 18
       stand   240 wide at x=40, 14px/22.4, 67 tall, then 10
       button  120x30 centered, 19.25px/26.95 label, then 26 to the card foot

   The second card opens 40 under the first, not the desktop 58. */
html[data-device="phone"] .news-list { margin-inline: 19px; }
html[data-device="phone"] .news-card {
  padding: 0;
  gap: 18px;
}
html[data-device="phone"] .news-card + .news-card { margin-top: 40px; }
/* 1.66:1, not the square the reflow gives it. */
html[data-device="phone"] .news-thumb {
  width: 100%;
  height: 169px;
  aspect-ratio: auto;
}
/* The copy carries the inset the card itself no longer has. */
html[data-device="phone"] .news-card-text { padding: 0 20px 26px; }
html[data-device="phone"] .news-card-text h2 { margin-bottom: 18px; }
/* The 99px floor is a desktop measurement of a block that is three lines here,
   and it was holding every card 32px open past its own copy. */
html[data-device="phone"] .news-standfirst {
  font-size: 14px;
  line-height: 22.4px;
  min-height: 0;
  margin-bottom: 10px;
}
html[data-device="phone"] .news-more { text-align: center; }
html[data-device="phone"] .news-more a { font-size: 19.25px; line-height: 26.95px; }
/* 34px, and the clamp cannot reach it: 3.9vw is 12.5 on a 320 canvas, so it
   bottoms out at its own 32px floor. */
html[data-device="phone"] .news-index h1 { font-size: 34px; }
html[data-device="phone"] .news-index { padding-top: 20px; }

/* The motto strip. On the phone the source breaks it in two -- the heading
   centered on one line, the mark right-aligned under it -- where the desktop
   band sets both on one line at the container's left edge. Measured on
   /attorney-referrals: a 114px band, the heading 27px/37.8 with its run 22px
   in, the mark 33px under that. */
html[data-device="phone"] .motto-strip {
  text-align: center;
  /* 20 above the heading and 18 below it, which with the heading's own 76 is
     the source's 114px band. */
  padding: 20px 20px 18px;
  white-space: normal;
}
/* The strip is absolutely positioned and bottom-anchored so it can sit at the
   foot of the photograph on the pages that have one. The strip-only pages give
   .motto `height: auto` under 768px, which leaves the section zero-high and
   paints the strip back over the end of the body -- on /attorney-referrals it
   covered the last four lines of the closing paragraph. Nothing showed while
   that body carried its desktop bottom padding. Only the strip-only pages are
   put back in flow; where the photograph is there, the strip has to stay over
   it. */
html[data-device="phone"] .motto.strip-only .motto-strip { position: relative; }
html[data-device="phone"] .motto-heading {
  display: block;
  font-size: 27px;
  line-height: 37.8px;
}
html[data-device="phone"] .motto-mark {
  font-family: var(--display);
  font-weight: 700;
}
/* Scoped to this page because the source does not treat the mark the same way
   on every band that carries it. On /attorney-referrals it is positioned
   independently and overlays the heading's second line -- a 33x28 box at
   x=256, inside the heading's own 1299..1375 -- so it adds nothing to the
   band, which measures 114. On /faqs the same mark is a full-width block in
   flow 9px under the heading and the band measures 154. Do not widen this
   selector without measuring the page you are widening it onto. */
html[data-device="phone"] .referrals .motto-mark {
  position: absolute;
  top: 53px;
  right: 31px;
}

/* --- /attorney-referrals at 320 ---
   The whole of this page's body was still at its desktop type: a 26px
   standfirst against the source's 16 and 18px paragraphs against its 14, which
   is where 600 of its 681px came from. The gaps between paragraphs are the
   source's own empty spacer paragraphs carried through in the body HTML, so
   they resize with the paragraphs and are not set here.

   The banner is this page's own, not the shared practice-page photo band: the
   source leaves 20px of white under the header and then paints 138px of navy
   -- sampled on the live page, white to 154, navy to 292, white from 295. The
   shared phone rule pins .practice-head to 188 with !important to tame the
   per-page inline styles, so these have to carry it too. */
html[data-device="phone"] .practice-head.hero-referrals {
  margin-top: 20px;
  min-height: 138px !important;
  padding-top: 16px !important;
  align-items: flex-start;
}
html[data-device="phone"] .practice-head.hero-referrals h1 {
  font-size: 35px !important;
  line-height: 49px !important;
}
html[data-device="phone"] .referrals-body { padding-block: 20px 20px; }
html[data-device="phone"] .referrals-body h3 {
  font-size: 16px;
  line-height: 19.2px;
  margin-bottom: 10px;
}
html[data-device="phone"] .referrals-body p { font-size: 14px; line-height: 21px; }

/* --- /privacy at 320 ---
   The page is one paragraph rule and one heading rule, and both were a pixel
   over the source's: 23px for the opening line and 15px for the body, against
   the 24 and 16 the desktop page measures. A pixel a line over roughly ninety
   lines is the whole of this page's drift, which is why it arrives a few px at
   a time rather than in any one band. The 1.4 line box is already the
   source's. */
/* 30 at the foot: the source closes the document with one 21px zero-width-space
   paragraph, which our extraction drops, and then leaves 9px to the footer. */
html[data-device="phone"] .privacy { padding-block: 20px 30px; }
/* 10 at the foot on /terms: its last paragraph ends at 2624 and the footer
   band opens at 2634. */
html[data-device="phone"] .terms { padding-block: 20px 10px; }

/* --- the practice pages' closing "Our Results" band at 320 ---
   Every value here is per page and recorded by `manage.py record_phone_type`;
   the fallbacks are /car-accidents', the page the block was first measured on.
   Hardcoding that page's numbers across the family set /corporate-law's
   heading 26/31.2 against the source's 24/28.8 and its button 160 wide against
   258, and opened the band 77px under the photograph where the source leaves
   21 -- 111px of that page's phone drift.

   The list indents 22 from the container, putting its text at x=42. */
html[data-device="phone"] .practice-secondary > h2:first-child {
  font-size: var(--ph-sec-size, 26px);
  line-height: var(--ph-sec-lh, 31.2px);
}
html[data-device="phone"] .practice-secondary p {
  font-size: var(--ph-p-size, var(--ph-closing-size, 12px));
  line-height: var(--ph-p-lh, var(--ph-closing-lh, 21.6px));
  /* The paragraph's own recorded tracking first, then the band's, the order
     the font-size above already uses. A band is not one value: /trusts records
     `closing_track: normal` while this standfirst paints 0.75px. */
  letter-spacing: var(--ph-p-track, var(--ph-closing-track, 0.6px));
}
/* The standfirst's measure, which Wix sets per page and does not tie to the
   heading beside it: 293px on /corporate-law and 280 on /car-accidents. At the
   container's own 280 that paragraph took an extra line. Direct children only,
   so a verdict line inside its list item keeps the narrower measure the source
   gives it. */
html[data-device="phone"] .practice-secondary > p {
  width: var(--ph-closing-width, auto);
  max-width: none;
}
html[data-device="phone"] .practice-secondary li,
html[data-device="phone"] .practice-secondary li p {
  font-size: var(--ph-results-size, 12px);
  line-height: var(--ph-results-lh, 21.6px);
  font-weight: 700;
  letter-spacing: var(--ph-results-track, normal);
}
/* The list opens straight off the closing paragraph and closes 10px above the
   button: the source's intro measures the same 280x130 as ours, and its first
   bullet starts where that paragraph ends. The 16px margins are the browser
   default for a ul and were adding a line's worth at each end. */
html[data-device="phone"] .practice-secondary ul {
  padding-left: 22px;
  margin-block: 0;
}

/* The types list runs a 240px measure at x=40, inside a panel whose heading
   takes the full 290. The 50px matters rather than being a detail of
   centering: at 290 "Uninsured or Underinsured Drivers" fits on one line and
   the source takes two, which is the single 21px step left in this page's
   ladder. Scoped to the list so the heading keeps its own width. */
/* --- /contact at 320 ---
   Measured on the live page: an 89px navy banner (not the shared 188px photo
   band), the heading 25/32.5 against the desktop 42/54.6, the form iframe 955
   tall where the desktop embed is 901, and 304px of white under it before the
   photograph. */
html[data-device="phone"] .practice-head.hero-contact {
  min-height: 89px !important;
  padding-top: 20px !important;
  align-items: flex-start;
}
html[data-device="phone"] .practice-head.hero-contact h1 {
  font-size: 35px !important;
  line-height: 49px !important;
}
html[data-device="phone"] .contact-details { padding-block: 20px 10px; }
html[data-device="phone"] .contact-details h2 {
  font-size: 25px;
  line-height: 32.5px;
  margin-bottom: 10px;
}
/* An 84px label column, measured from the labels at x=20 and their values at
   x=104, against the 126 the desktop page reads at its own width. The list
   closes 29px above "Kingston Office:". */
html[data-device="phone"] .contact-list {
  grid-template-columns: 84px auto;
  margin-bottom: 29px;
}
html[data-device="phone"] .contact-form .intake-form iframe {
  min-height: 955px;
  height: 955px;
}
html[data-device="phone"] .contact-form { padding-bottom: 304px; }
/* The source paints only the photograph here, 213 tall, and drops the navy
   strip that the desktop band carries over its bottom edge. /contact is the
   only page that includes this band with its photograph -- the two FAQ indexes
   and /attorney-referrals pass strip_only -- so this is that page's rule and
   not a change to the strip-only ones. */
html[data-device="phone"] .motto:not(.strip-only) { height: 213px; }
html[data-device="phone"] .motto:not(.strip-only) .motto-strip { display: none; }

/* The list's column, recorded per page rather than inset from the panel: Wix
   positions this block itself, so it runs x=27 w=273 on /corporate-law and
   x=68 w=191 on /guardianships. The 25px inset was one page's number on all of
   them, and at 222px wide four of /corporate-law's six items took an extra
   line each -- 62px of that page's drift. The 15px subtracted is
   .types-panel-inner's own padding, which this offset is measured through. */
html[data-device="phone"] .types-panel-inner ul {
  margin-left: calc(var(--ph-panel-list-left, 40px) - 15px);
  width: var(--ph-panel-list-width, 240px);
  padding-inline: 0;
}
/* 14 under the heading, against the 17 the panel inherits. The 23px above the
   button is the source's own -- it opens 46px under the last list item -- so
   it is left alone. */
html[data-device="phone"] .types-panel-inner h2 {
  margin-bottom: var(--ph-b-gap-below-heading, 14px) !important;
}
/* Both buttons take the source's own recorded box, with /car-accidents' 240
   and 160 left as the fallbacks they were hardcoded from -- the source draws
   the panel button 285 wide on /bike-accidents and the closing one 258 on
   /corporate-law. A floor rather than a fixed width, for the reason
   .hub-btn.practice-secondary-cta carries above: our face is wider than the
   source's and pinning its number wraps the label. */
/* The button opens 16px under the list and centers in the panel's content box,
   which `.types-list` cannot provide: its `margin-block: 0` leaves the two
   touching, and the button otherwise sits at the panel's left padding. Centering
   resolves to the source's own x: 15px of padding plus half of the 290px column
   less the button is 40, which is where live draws it on /workers-compensation
   and /car-accidents. /personal-injury is untouched -- its button is in
   `.hub-inner`, not this panel. */
html[data-device="phone"] .types-panel-inner .hub-btn {
  min-width: var(--ph-panel-cta-width, 240px);
  height: var(--ph-panel-cta-height, 42px);
  margin-top: var(--ph-panel-cta-gap, 16px);
  margin-inline: auto;
}
/* `fit-content`, not `auto`. `html[data-device="phone"] .hub-btn` makes this a
   BLOCK-level flex container, so `auto` fills the 280px column: the source
   draws "Contact Us Today" 160px wide against the paragraph's left edge and
   ours spanned the whole measure with the label centered. The min-width floor
   is what keeps a long label from wrapping. */
html[data-device="phone"] .practice-secondary .hub-btn {
  min-width: var(--ph-sec-cta-width, 160px) !important;
  width: fit-content !important;
  height: var(--ph-sec-cta-height, 42px);
  margin-top: var(--ph-sec-cta-gap, 10px) !important;
}
html[data-device="phone"] .legal-doc h1 { font-size: 23px; }
html[data-device="phone"] .legal-doc-body,
html[data-device="phone"] .legal-doc-body h2 { font-size: 15px; }
/* 42, not 45. The gap is two of the source's empty paragraphs, which are 21px
   here rather than the desktop page's 22 -- the same model, re-read at this
   size, not a number chosen to close a difference. */
html[data-device="phone"] .legal-doc-body h2 { margin-top: 42px; }
/* Both legal documents run a 269px measure at x=26, not the 280 at x=20 the
   shared phone container gives every other band. The 11px matters: it is what
   makes the source wrap one line more than us in four places, each showing as
   a clean 21px step. Their bullets indent 27 from that column, against the 29
   the desktop pages use. */
html[data-device="phone"] .legal-doc .container { padding-inline: 26px 25px; }
html[data-device="phone"] .legal-doc-body ul { padding-left: 27px; }

/* The practice-area panel in an article's sidebar, under the enquiry box.
 * Measured on the live article: a 273x397 panel at x=899 in rgb(224, 226, 232)
 * with a 6px radius, its heading 22px/700 in --navy-band 10px inside the top,
 * then eight rows 40px tall on a 45px pitch, each 16px/700 in the same
 * rgb(11, 47, 91) the FAQ buttons use, centered, divided by a 1px
 * rgb(168, 169, 172) rule. */
.insight-practice {
  /* 40px under the enquiry panel: the source's ends at 1493 and this one
   * opens at 1533. */
  margin-top: 40px;
  background: rgb(224 226 232);
  border-radius: 6px;
  /* 10 above the heading and 7 under the last row, which is where the live
   * panel's 397px goes: 10 + 27 heading + 13 + 341 of rows + 7. */
  padding-block: 10px 7px;
  /* The rows are 250 inside the 273 panel, not flush with it: the source runs
   * them 910 to 1160 in a panel spanning 899 to 1172. Flush, the longest
   * labels sit hard against both edges and read as clipped, which is what
   * shows at a narrow window. */
  padding-inline: 11px 12px;
}
.insight-practice-heading {
  margin: 0 0 13px;
  font-size: 22px;
  /* 27px, which is what the live heading measures. Left to inherit, the body's
   * 1.8 put it in a 40px box and the panel 14px over. */
  line-height: 27px;
  font-weight: 700;
  color: var(--navy-band);
  text-align: center;
}
.insight-practice ul { list-style: none; margin: 0; padding: 0; }
.insight-practice li { margin: 0; }
/* 3px, for the 341px of rows the panel's padding is sized against: the source
 * places these absolutely and its own gaps run 5, 5, 0, -5, 5, 5, 5 -- the last
 * of those an overlap -- so a uniform pitch matching its 340px total is the
 * closest honest model. */
.insight-practice li + li { margin-top: 3px; }
/* The rule sits ON the row and inside its 40px box, not between rows: as a
 * border on the <li> it made every row 41 tall against the source's 40. */
.insight-practice li + li a { border-top: 1px solid rgb(168 169 172); }
.insight-practice a {
  display: block;
  box-sizing: border-box;
  height: 40px;
  line-height: 40px;
  text-align: center;
  /* 14px at 1.4px of tracking. Four of the eight rows override this to 16/1.6
   * below; the source sets them individually. */
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 1.4px;
  /* No radius on the row. The separator is drawn as this element's top border,
   * and rounding the corners clipped both ends of every rule -- the source
   * paints them square and full width. The 6px belongs to the panel. */
  /* The row is a fixed 40px, so a label that wraps overlaps its neighbour
   * rather than growing the panel. */
  white-space: nowrap;
  color: #0B2F5B;
  text-decoration: none;
}
.insight-practice a.is-lg { font-size: 16px; letter-spacing: 1.6px; }
.insight-practice a:hover { text-decoration: underline; }

/* "← Previous" / "Next →" at the foot of an article. Measured on the live
 * page: both 105x30 on one row, Previous at the body column's left edge and
 * Next at x=1088. Navy fill with white label, as the source paints them. */
.insight-pager {
  display: flex;
  justify-content: space-between;
  align-items: center;
  /* Inset like the grid above it: the source runs this row 244 to 1193, which
   * is 14 in from the container's left and 17 from its right -- 21px wider on
   * the right than the sidebar, which ends at 1172. */
  padding-inline: 14px 17px;
  /* 23px above and 17px below, measured on the source: its last body line ends
   * 23px over the button and the footer band starts 17px under it. Ours had
   * 111 above and nothing below, which is the white gap that showed. */
  padding-block: 23px 17px;
}
/* 105x30 in rgb(11, 47, 91) -- the same navy the FAQ buttons and the sidebar
 * labels use -- with an 8px radius, a 1px black border and a 16px/700 white
 * label. Every one of those was measured on the live control; ours had square
 * corners, no border, --navy-deep and a 14px label. */
.insight-pager a,
.insight-pager span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 105px;
  height: 30px;
  background: #0B2F5B;
  border: 1px solid #000;
  border-radius: 8px;
  color: var(--paper);
  font-size: var(--size-body);
  font-weight: 700;
  text-decoration: none;
}
.insight-pager a:hover { background: var(--navy); }
/* Kept in place rather than hidden: the source paints both controls on every
 * article, including the first and last of a category. */
.insight-pager .is-disabled { opacity: .45; }
html[data-device="phone"] .header-search input {
  width: 175px;
  height: auto;
  flex: none;
  align-self: flex-start;
  padding: 8px 0;
  font-size: 12.8571px;
  line-height: 18px;
}

/* --- Phone: attorney profile ---------------------------------------------
   One column, and it reorders: portrait, contact, biography, practice areas.
   Measured on /team/allan-m.-kluger at 320.

     hero      134-358   back at 147, name 180, role 222
     portrait  358-820   full bleed, 320x462
     panel     820-898   --shell, contact rows at 834 and 864
     bio       918-      14/21 in a 290 measure
     practice  2382-     heading 21/29.4, items 14/21
     badges              full width, stacked -- not the desktop marquee
     motto               absent on mobile
   ------------------------------------------------------------------------ */
html[data-device="phone"] .attorney-head {
  height: auto;
  padding: 0 0 31px;
  display: flex;
  flex-direction: column;
}
html[data-device="phone"] .attorney-head .container { display: contents; }
html[data-device="phone"] .attorney-back {
  order: 1;
  margin: 13px 0 0 9px;
  letter-spacing: normal;
}
html[data-device="phone"] .attorney-head h1 {
  order: 2;
  font-size: 30px;
  line-height: 42px;
  margin: 9px 20px 0;
}
html[data-device="phone"] .attorney-role {
  order: 3;
  font-size: 26px;
  line-height: 36.4px;
  margin: 0 20px;
}

html[data-device="phone"] .attorney-body {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0;
}
html[data-device="phone"] .attorney-aside,
html[data-device="phone"] .attorney-panel { display: contents; }

html[data-device="phone"] .attorney-photo {
  order: 1;
  width: 320px;
  max-width: none;
  height: 462px;
  margin-inline: -20px;
}
html[data-device="phone"] .attorney-contact {
  order: 2;
  background: var(--shell);
  margin-inline: -20px;
  padding: 14px 0 0 32px;
  gap: 10px;
  font-size: 14px;
  line-height: 19.6px;
  min-height: 78px;
  box-sizing: border-box;
}
html[data-device="phone"] .attorney-icon { width: 19px; height: 19px; margin-right: 14px; }
/* 46x3 at x=20, and it moves: on desktop the rule sits above "Areas of
   Practice", on mobile below it. */
html[data-device="phone"] .attorney-rule {
  order: 5;
  width: 46px;
  height: 3px;
  margin: 11px 0 0;
}

html[data-device="phone"] .attorney-bio {
  order: 3;
  padding: 20px 0 0;
  margin-inline: -5px;
}
html[data-device="phone"] .attorney-bio p { font-size: 14px; line-height: 21px; margin-bottom: 21px; }
html[data-device="phone"] .attorney-bio li { font-size: 14px; line-height: 21px; }

html[data-device="phone"] .attorney-practices-head {
  order: 4;
  font-size: 21px;
  line-height: 29.4px;
  margin-top: 55px;
}
html[data-device="phone"] .attorney-practices {
  order: 6;
  font-size: 14px;
  line-height: 21px;
  margin-top: 15px;
}

/* Full width and stacked, each badge scaled to the canvas. The desktop row
   scrolls; this one does not, so the gallery's arrows go with it. */
html[data-device="phone"] .attorney-badges {
  flex-direction: column;
  align-items: flex-start;
  overflow-x: visible;
  gap: 14px;
  margin: 28px -20px 0;
}
html[data-device="phone"] .attorney-badges img { width: 320px; height: auto; }
html[data-device="phone"] .badge-arrow { display: none; }

html[data-device="phone"] .attorney-motto { display: none; }

/* Phone footer geometry. The talk band carries a fixed 437px desktop height;
   the source's mobile band is 285 and sized by its content. */
html[data-device="phone"] .footer-talk { height: auto; padding: 22px 0 35px; }
html[data-device="phone"] .footer-contact { margin-bottom: 58px; }
html[data-device="phone"] .footer-row { margin-top: 2px; }
html[data-device="phone"] .footer-credit { padding-inline: 15px; margin-top: 7px; }

/* ---------------------------------------------------------------------------
   Results listings, phone canvas.

   Measured against captures/html-phone/results.html, results_page_2.html and
   results_categories_car-accidents.html. Three list pages rather than one,
   because the index and a category do NOT paint the same card: the headline is
   18px/25.2 on the index and 30px/42 on a category, from the same partial.
   Sampling only the index would have set 18px on all six category pages.
   --------------------------------------------------------------------------- */
html[data-device="phone"] .result-post h2 {
  font-size: 18px;
  line-height: 25.2px;
  /* The desktop card reserves a two-line slot; the phone build does not. */
  min-height: 0;
}
html[data-device="phone"] .result-body p {
  font-size: 13px;
  line-height: 19.5px;
}
html[data-device="phone"] .results-of-category .result-post h2 {
  font-size: 30px;
  line-height: 42px;
}
/* The body scales with the headline, not just the headline. Setting only the
   h2 left this at the index's 13px against the source's 18. */
html[data-device="phone"] .results-of-category .result-body p {
  font-size: 18px;
  line-height: 27px;
}
/* 49px, not the 1.28 ratio the desktop rule computes to at this size. */
html[data-device="phone"] .results-head h1 { line-height: 49px; }

/* ---------------------------------------------------------------------------
   Practice hubs, both canvases.

   The three parents of the practice areas -- /personal-injury, /business-law,
   /estate-and-trusts -- were missed when the 34 second-level pages were brought
   to phone parity: different model, different template, so none of the --ph-*
   work reached them. Recorded per page by record_hub_type, and per CARD for
   the grid labels, because Wix sets those individually: /personal-injury runs
   four different label sizes across its 21 cards on the phone canvas.
   --------------------------------------------------------------------------- */
.hub-hero h1 {
  font-size: var(--hub-h1-size, 66px);
  line-height: var(--hub-h1-lh, 89.6px);
}
.hub-intro p {
  font-size: var(--p-size, var(--hub-intro-size, 16px));
  line-height: var(--p-lh, var(--hub-intro-lh, 28.8px));
}
.hub-results-panel h2 {
  font-size: var(--hub-results-size, 48px);
  line-height: var(--hub-results-lh, 57.6px);
}
.hub-grid span {
  font-size: var(--card-size, 20px);
  line-height: var(--card-lh, 28px);
}
/* 184 tall with the title 72px in, measured on the source's phone build. The
   band carried the desktop `height: 346px` and the title the desktop
   `margin-top: 120px`, and the size fell back through --hub-h1-size, the
   desktop value, giving 30px against the source's 29. */
/* Recorded per page: 184 on /personal-injury and /business-law and 187 on
   /estate-and-trusts, whose banner the constant 184 left 3px short. */
html[data-device="phone"] .hub-hero { height: var(--ph-hero-height, 184px); }
/* The clip fills the phone band instead of keeping the desktop crop. The
   source paints a 320x184 still here; ours kept `top: -147px; height: 490px`,
   which is the crop measured on a 346px band, so the phone showed the top 184
   of a 490px frame. Found by style_diff --images, the only gate that looks at
   an image at all -- parity rule 18. */
html[data-device="phone"] .hub-hero-video {
  top: 0;
  height: var(--ph-hero-height, 184px);
}
html[data-device="phone"] .hub-hero h1 {
  font-size: var(--ph-hub-h1-size, 29px);
  line-height: var(--ph-hub-h1-lh, 40.6px);
  /* 71, 72 and 73 across the three hubs, so recorded rather than shared. */
  margin-top: var(--ph-hero-pad-top, 72px);
}
html[data-device="phone"] .hub-intro p {
  font-size: var(--ph-p-size, var(--ph-hub-intro-size, var(--hub-intro-size, 16px)));
  line-height: var(--ph-p-lh, var(--ph-hub-intro-lh, var(--hub-intro-lh, 28.8px)));
}
html[data-device="phone"] .hub-results-panel h2 {
  font-size: var(--ph-hub-results-size, var(--hub-results-size, 23px));
  line-height: var(--ph-hub-results-lh, var(--hub-results-lh, 27.6px));
}
/* The source's hub card on the phone is the desktop card scaled down: a
   160x124 image (the same 225:175 aspect) at x=80, so one centered column,
   repeating every 178px. Ours kept the desktop 225x175, which made each card
   209 tall on a 264 pitch -- 86px per card over 21 cards, and the whole
   1,993px by which our grid band overran the source's on /personal-injury. */
/* The source's phone build shows the cards in a different order from its
   desktop one -- /personal-injury opens with Truck Accidents at 1440 and with
   Medical Malpractice at 320 -- so each card carries its recorded phone
   position. Without it every card but two sat somewhere else than the source's,
   by up to 2,795px. */
html[data-device="phone"] .hub-grid li {
  flex: 0 0 160px;
  width: 160px;
  order: var(--ph-card-order, 0);
}
html[data-device="phone"] .hub-grid img { width: 160px; height: 124px; }

/* 17/23.8 and an 11px lift, measured on the source's card. The fallback used to
   chain through --card-size, the DESKTOP value, so a page carrying no phone
   measurement got 20/25.2 here -- which wraps every two-word label onto a
   second line inside a 160px card and put 50px of label under each image
   against the source's 20. Falling back to the desktop value is how a desktop
   number reaches the phone build unopposed. */
html[data-device="phone"] .hub-grid span {
  font-size: var(--ph-card-size, 17px);
  line-height: var(--ph-card-lh, 23.8px);
  /* 10.0 on all 21 of /personal-injury's cards and all 5 of /business-law's,
     recorded per page anyway because /estate-and-trusts runs 10.2. */
  margin-top: var(--ph-grid-label-gap, 10px);
  /* The source's label is not clamped to the card at all: it sits in the
     page's own 280px content column (the h4 measures x=20 w=280 on the live
     phone build of /personal-injury) and is centered in it, so it overhangs
     the 160px image freely -- "Construction Accidents" paints 209 wide. Only
     "Food Delivery Driver Accidents" exceeds 280 and wraps, which the source
     wraps too. (160 - 280) / 2 centers it on the image. */
  width: 280px;
  margin-inline: -60px;
  text-align: center;
}
/* 252, not the desktop band's 504: the source's phone photograph is exactly
   half the height its desktop one is, and ours kept the desktop number. */
html[data-device="phone"] .hub-results-photo { height: 252px; }

/* ---------------------------------------------------------------------------
   The phone bands' own spacing, recorded per page by record_hub_phone_rhythm
   and read here through --ph-*. One set of numbers cannot serve the three hubs:
   below a card label the source leaves 16.25px on /personal-injury, 31.75 on
   /business-law and 41.25 on /estate-and-trusts, and under the last card 20px,
   380 and 52. Each fallback below is the value the source uses on the hub that
   carries the property, and is only reached by a hub nobody has recorded.
   --------------------------------------------------------------------------- */

/* 20px of content padding, not the 24 --s-4 gives: the source's phone column
   runs x=20 w=280 in the intro band on all three hubs. The insets are recorded
   per band all the same, because they are not one number: /business-law insets
   its intro copy 20 and 12, and /personal-injury's closing band runs 28 and
   12. */
html[data-device="phone"] .hub-inner,
html[data-device="phone"] .hub-grid ul { padding-inline: 20px; }
html[data-device="phone"] .hub-intro .hub-inner {
  padding-inline: var(--ph-intro-pad-left, 20px) var(--ph-intro-pad-right, 20px);
}

html[data-device="phone"] .hub-intro {
  padding-top: var(--ph-intro-pad-top, 20px);
  padding-bottom: var(--ph-intro-pad-bottom, 23px);
}
/* The source does NOT drop this heading on the phone. It splits it into a span
   per word -- "We" / "Will" / "Fight For You." -- so a DOM search for the whole
   string finds nothing and it was recorded as dropped copy. It paints on one
   line at y=336, x=20, and its size is per page: 23px here, 21 on
   /business-law, 25 on /estate-and-trusts. */
html[data-device="phone"] .hub-hook {
  font-size: var(--ph-hub-hook-size, 23px);
  line-height: var(--ph-hub-hook-lh, 25.2px);
  margin-bottom: var(--ph-intro-head-gap, 10px);
}
html[data-device="phone"] .hub-intro p { margin-bottom: var(--ph-intro-body-gap, 17px); }
/* The gap above every phone button is the paragraph's own margin, above.
   160x42, measured on the source's phone build of /personal-injury: the intro
   button is 20..280 and 42 tall, "See Past Cases" 20..180 and 42, "Let Us Help
   You!" 28..188 and 35. The desktop min-width of 186 made the two narrow ones
   26px wide of the source with the label inside them measuring exactly right,
   which is parity rule 17. */
html[data-device="phone"] .hub-btn {
  margin-top: 0;
  min-width: 0;
  width: 160px;
  height: 42px;
  /* Block-level, as the source's <a> is. Left inline-flex it sat on the line
     box of the column it is in, and the strut of that 16px/28.8 block put every
     button 3px below the gap measured above it. */
  display: flex;
  /* 2px, not the desktop 14: the source insets its label by 2 on all three
     buttons (the inner flex box is x=30 in a button at x=28, and x=22 in one at
     20). At 14 there was 115px of room for a 119px label and "Let Us Help
     You!" wrapped inside a 35px button. */
  padding-inline: 2px;
  /* `normal`, which is what the source computes for these labels. */
  line-height: normal;
}
/* 260 and 12px, not 186 and 14: the source shrinks this label to hold "Meet Our
   Personal Injury Attorneys" on one line inside the button. All three hubs run
   a label of that shape here. */
html[data-device="phone"] .hub-intro .hub-btn-wide { width: 260px; font-size: 12px; }
html[data-device="phone"] .hub-closing .hub-btn { width: 160px; height: 35px; }

/* The band's own padding replaces the desktop 68px lead-in, which the intro's
   recorded bottom padding already covers. */
html[data-device="phone"] .hub-results { margin-top: 0; }
html[data-device="phone"] .hub-results-panel {
  padding: var(--ph-results-pad-top, 28px) var(--ph-results-pad-right, 20px)
           var(--ph-results-pad-bottom, 30px) var(--ph-results-pad-left, 20px);
}
html[data-device="phone"] .hub-results-panel h2 { margin-bottom: var(--ph-results-head-gap, 6px); }
html[data-device="phone"] .hub-results-panel p {
  font-size: var(--ph-hub-results-body-size, 12px);
  line-height: var(--ph-hub-results-body-lh, 21.6px);
  margin-bottom: var(--ph-results-body-gap, 13px);
}
/* Panel first, photograph second. The desktop band is a two-column grid with
   the photograph on the left, so stacking it at one column put the photograph
   above the copy; the source's phone build runs the copy first and closes the
   band with the picture. */
html[data-device="phone"] .hub-results-panel { order: 1; }
html[data-device="phone"] .hub-results-photo {
  order: 2;
  /* /business-law paints no photograph in this band on the phone and does at
     1440, so whether it shows is recorded per page. Rendering it there added
     280px of navy to a 259px band. */
  display: var(--ph-results-photo, block);
  /* The source's photograph block is 280 tall around a 252px image, so 28px of
     the band shows below the picture. */
  margin-bottom: 28px;
}

html[data-device="phone"] .hub-grid {
  padding-top: var(--ph-grid-pad-top, 20px);
  padding-bottom: var(--ph-grid-pad-bottom, 20px);
}
/* NOT --card-row-gap: that value is measured on the desktop band. The source's
   gap below a label is hand-set per card and takes two values with no rule
   behind them -- 10 under eight of /personal-injury's cards and 20 under the
   other twelve -- so the recorded number is their mean, which reproduces the
   band's height to within a pixel. */
html[data-device="phone"] .hub-grid ul {
  row-gap: var(--ph-grid-card-gap, 16.25px);
  column-gap: 0;
}

html[data-device="phone"] .hub-closing {
  padding: var(--ph-closing-pad-top, 21px) 0 var(--ph-closing-pad-bottom, 20px);
}
/* Not the intro's 20 either side: the source insets /personal-injury's closing
   column 28 and 12, so its column is x=28 w=280. At 264 wide the motto ran to
   six lines where the source sets five. /business-law insets the same band 20
   and 20, which is why this is recorded rather than shared. */
html[data-device="phone"] .hub-closing .hub-inner {
  padding-inline: var(--ph-closing-pad-left, 28px) var(--ph-closing-pad-right, 12px);
}
html[data-device="phone"] .hub-closing h2 {
  font-size: var(--ph-hub-closing-size, 14px);
  line-height: var(--ph-hub-closing-lh, 15.6px);
  margin-bottom: var(--ph-closing-head-gap, 10px);
}
/* The registered mark leaves the heading's line on the phone and becomes a
   block of its own -- the source paints it 20px/28 in a 32x28 block below the
   heading, centered on the canvas at x=144. Same component, different shape per
   canvas; see parity rule 15. */
html[data-device="phone"] .hub-closing h2 sup {
  display: block;
  font-size: var(--ph-hub-mark-size, 20px);
  line-height: var(--ph-hub-mark-lh, 28px);
  vertical-align: baseline;
  text-align: center;
  margin-top: var(--ph-closing-head-gap, 10px);
  margin-bottom: var(--ph-closing-mark-gap, 10px);
  /* The mark centers on the CANVAS (x=144 of a 32px block, so 160), not on the
     column it sits in, which is inset 28 left and 12 right. 16 off the right
     edge makes the two centers the same. */
  margin-right: 16px;
}
html[data-device="phone"] .hub-closing p {
  font-size: var(--ph-hub-closing-body-size, 12px);
  line-height: var(--ph-hub-closing-body-lh, 21.6px);
  margin-bottom: var(--ph-closing-body-gap, 11px);
}

/* ---------------------------------------------------------------------------
   Case results.

   These reuse .practice-head for their banner, which paints the practice-area
   title -- 66px/89.6 display bold. The source sets this headline as body copy:
   40px/50 montserrat 400 on desktop and 26px/36.4 on the phone build, verified
   on three separate captures. 116 pages carry it.

   !important on the phone rule for the same reason the block it overrides
   carries one: the clamp at max-width 620px is itself !important.
   --------------------------------------------------------------------------- */
.result .practice-head h1 {
  font-family: var(--body);
  font-size: 40px;
  line-height: 50px;
  font-weight: 400;
}
html[data-device="phone"] .result .practice-head h1 {
  font-size: 26px !important;
  line-height: 36.4px !important;
}
/* Body copy on a case result: 16px/24 on the phone build, uniform across the
   six runs on every capture checked. Without this it falls through to the
   practice-area default of 28.8px leading. Desktop already matches at 18/27. */
html[data-device="phone"] .result .practice-body p { line-height: 24px; }
/* The story's lead paragraph, phone build: 19px/26.6 against the desktop
   24/33.6 it was inheriting. The rest of the story's copy already matches. */
html[data-device="phone"] .story-lead p { font-size: 19px; line-height: 26.6px; }

/* ---------------------------------------------------------------------------
   /team head and the case-result headline, phone canvas.

   The head was sized with vw clamps, which cannot land on a source that
   hand-sets pixels: clamp(26px, 9.4vw, 46px) resolves to 30.08px at 320 where
   the source sets 31. Same pattern as the hub hero and the phone banner title.
   --------------------------------------------------------------------------- */
/* 21 between cards, not the desktop 38. Measured off the source's pitch from
   photograph to photograph -- 691, 691, 668, 687, 699 against our 708, 708,
   685, 704, 716, a flat 17 more on every one of twenty-one cards. */
html[data-device="phone"] .team-grid { gap: 21px; }
/* 20 and 20, so the band is the source's 122. The max-width block's 48 reached
   this build and made it 178. */
html[data-device="phone"] .team-head { padding: 20px 0; }
html[data-device="phone"] .team-head h1 { font-size: 31px; line-height: 43.4px; }
html[data-device="phone"] .team-head-sub { font-size: 25px; line-height: 35px; }
/* Scoped per page. This band is shared furniture but its type is not: /team
   sets the link at 22px/30.8 and /staff at 29px/40.6. An unscoped rule here
   fixed /team and broke /staff. */
html[data-device="phone"] .team .page-band a { font-size: 22px; line-height: 30.8px; }
html[data-device="phone"] .staff .page-band a { font-size: 29px; line-height: 40.6px; }

/* /staff's head, which carries its own classes and its own numbers -- 35px/49
   against /team's 31/43.4. */
/* 37.5 and 37.5, so the band is the source's 183 around the 108 of type it
   holds. The max-width block's 60 reached this build and made it 228. */
html[data-device="phone"] .staff-head { padding: 37.5px 0; margin-top: 20px; }
html[data-device="phone"] .staff-head h1 { font-size: 35px; line-height: 49px; }
/* 25, not the 28 the max-width:700px block sets: only the leading was given a
   phone value here, so the size came from the desktop rule beneath it. */
html[data-device="phone"] .staff-head-sub { font-size: 25px; line-height: 35px; }
/* The card's type is its own size on the phone: 22/30.8 for the name and
   13/18.2 for the contact rows, against the desktop 20/28 and 14/19.6. With no
   phone rule the desktop numbers reached this build and every one of the
   twenty-two cards was wrong on both -- the name a point small, the emails a
   point large. Both keep the 1.4 leading the desktop card uses. */
/* 19.5 between cards, not the desktop 38, and 18px of grid above the first
   rather than 41. Measured off the source's card pitch: 534.5 from photograph
   to photograph against a 515 card. The 38 was costing 18.5px on each of
   twenty-two cards -- 407 of this page's 542px band difference. */
html[data-device="phone"] .staff-grid { gap: 19.5px; }
html[data-device="phone"] .staff-grid-wrap { padding-top: 18px; }
/* The card's whole spec, measured off the source's card top to foot: the
   photograph, then 11 to the name, 3 to the role, 28 from the role's text to
   the email, 15 to the phone, and the card closes 24 below it -- 515 in total.
   The name's leading is 27 because the source's name is an inline span whose
   box is content height, not the 30.8 line box a block gives it (rule 1); the
   contact rows are 16 for the same reason. Ours came to 521 with a foot of 1,
   which is two errors cancelling: 21px of role padding too much and 23px of
   card foot too little. */
html[data-device="phone"] .staff-card-name { font-size: 22px; line-height: 27px; margin: 11px 0 0; }
html[data-device="phone"] .staff-card-role { margin: 3px 0 4px; line-height: 22.4px; }
html[data-device="phone"] .staff-card-contact { font-size: 13px; line-height: 16px; gap: 10px; }
html[data-device="phone"] .staff-card { padding-bottom: 22px; }

/* The source ranges this headline left; .practice-head centres its banner
   title, which is right for a practice area and not for a case result. */
.result .practice-head h1 { text-align: start; }

/* ---------------------------------------------------------------------------
   Search results.

   The one page with no source to match -- Wix's search called their backend,
   so there is nothing captured to measure against. Built from the site's own
   tokens so it reads as part of the site rather than reproducing anything.
   --------------------------------------------------------------------------- */
/* The source opens this title flush with the header's foot at the full 85px --
   /contact, which shares this banner, sets it at 299 and 85 and matches. Ours
   carried a 72px lead-in and a clamp that shrank the type to 66. */
/* 7 above and 22 below, which lands the word at 235 and closes the band at
   376 -- the source's own numbers. Both moved when the title's leading was
   corrected from 89.6 to 119: the taller line box pushed the band's foot 29px
   past where it belongs, so the padding had to come back by the same amount. */
.practice-head.hero-search {
  min-height: 0;
  padding-block: 7px 22px;
}
/* 119px, the leading every other hero title carries -- /contact measures 119
   on both sites. Setting the size alone left this one at 89.6, which is the
   30px of navy missing above the word. style_diff --sweep did report it,
   as `line-height live 119px ours 28.8px`, and it was dismissed as a pairing
   artifact because the run it paired was the visually-hidden h1. */
.practice-head.hero-search h1 { font-size: 85px; line-height: 119px; }
/* The source runs this page's column 940 wide against the site's 980, which is
   what puts its copy at x=250 rather than 230. Scoped to the search body so no
   other page's measure moves. */
html:not([data-device="phone"]) .search-body {
  max-width: 940px;
  padding-inline: 0;
}
/* 52px below, which is what the source's results section carries; 96 left an
   extra band of white under the last hit and under the no-results message. */
.search-body { padding-block: 17px 52px; }   /* live section pads 16px above its form on both builds */
/* Nothing to list, so almost no room is kept for it. Measured from the source's
   own no-results page: the gap from its message to the band beneath is 1028px,
   which lands between the 52 the results state carries and 0. */
.search-page.is-empty .search-body { padding-bottom: 17px; }

/* The page's own search field, separate from the header's. The source paints
   it 908x50 at 1440 and 252x41 at 320. */
/* The border belongs to the form, not the input: the source draws a 280px box
   at the container's own edge and sets a borderless 252px field inside it,
   with the 14px magnifier at 33 and the text starting at 47. */
.search-form {
  /* 21px under the field, which is what puts the source's strip at 304. */
  margin: 0 0 21px;
  position: relative;
  display: flex;
  align-items: center;
  border: 1px solid rgb(11 47 91 / .6);
  background: #fff;
  /* The source's field takes a text caret across the whole box, including the
     padding either side of the input. */
  cursor: text;
}
.search-form-icon {
  position: absolute;
  left: 13px;
  top: 50%;
  /* 18px on the source, not the header field's 14. */
  width: 18px;
  height: 18px;
  transform: translateY(-50%);
  color: rgb(4 19 58 / .6);
  pointer-events: none;
}
.search-form-input {
  width: 100%;
  height: 50px;
  /* Clears the magnifier, then the source's own 12px before the text. */
  margin-left: 31px;
  /* Room on the right for the clear button the source paints once a term is
     in the field. */
  padding: 0 40px 0 12px;
  font-family: var(--body);
  /* 20px on the source. The header's own field is 16 and is a different
     component; this one is the page's. */
  font-size: 20px;
  /* The source's own values: navy text, both the placeholder and the border at
     60% so the field reads lighter than the copy around it. */
  color: rgb(4 19 58);
  background: transparent;
  border: 0;
  border-radius: 0;
  appearance: none;
}
/* The source clears the field with an x at its right end, shown only once
   there is something to clear. A link rather than a script: it goes to the
   same page with no query, which is what its own control does. */
.search-form-clear {
  position: absolute;
  /* Flush inside the form's own border, where the source puts it: its right
     edge reads 1189 against a form ending at 1190. */
  right: 1px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  color: rgb(4 19 58 / .6);
  text-decoration: none;
  font-size: 18px;
  line-height: 1;
}
.search-form-clear:hover { color: rgb(4 19 58); }
.search-form-input::placeholder { color: rgb(4 19 58 / .6); opacity: 1; }
/* Same decision as .header-search above, for the same reason: the ring landed
   1px inside the form's own border and read as a second, wrong-colored box,
   where the source shows nothing on focus. The on-brand alternative, if the
   accessibility trade is not wanted, is to thicken .search-form's border on
   :focus-within rather than to restore a ring. */
.search-form-input:focus,
.search-form-input:focus-visible { outline: none; }
.search-form-input::-webkit-search-cancel-button,
.search-form-input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }

/* Tabs scroll sideways when they outrun the column, as the source's do. The
   source clips the last label mid-word at 320; ours wraps to a second row
   instead, per docs/PARITY-AUDIT.md "Text the source cuts off and we do not". */
.search-tabs {
  /* The source's summary opens 37px under the strip's rule, not 20 — measured
     from the rule's own bottom, which is what a reader sees as the gap. */
  margin: 0 0 37px;
  /* The source's rule is its navy at 20%, not the shell grey. */
  border-bottom: 1px solid rgb(11 47 91 / .2);
  position: relative;
}
/* The arrows sit over the ends of the strip, as the source's do, and stay out
   of the flow so revealing one does not shift the tabs. */
/* The source hangs these outside the text column — its arrows sit at x=5 and
   x=283 on a 320 canvas whose column runs 20 to 300. */
.search-tab-step {
  position: absolute;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 52px;
  width: 24px;
  padding: 0;
  background: #fff;
  border: 0;
  color: rgb(4 19 58);
  cursor: pointer;
}
.search-tab-step svg { width: 24px; height: 24px; }
.search-tab-step[data-step="-1"] { left: -15px; }
.search-tab-step[data-step="1"] { right: -7px; }
.search-tab-step[hidden] { display: none; }
/* One row that scrolls sideways, as the source has it, rather than wrapping.
   Nothing is lost to the clip -- the strip scrolls and the chevrons step it --
   so the standing rule about keeping copy the source truncates does not apply
   here. */
.search-tab-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
}
.search-tab-list::-webkit-scrollbar { display: none; }
/* The spacing lives on the ITEM, not the link: the source's own anchor is its
   text box -- 48x24 for "All (25)" -- and its first tab's text opens at x=278
   inside a strip that starts at 250. Ours put 28px of padding on the anchor,
   which made it 109x37 and opened the text flush at 250. */
.search-tab-item { margin: 0; padding: 6.5px 28px; }
.search-tab {
  display: flex;
  align-items: center;
  height: 24px;
  padding: 0;
  font-family: var(--body);
  font-size: 16px;
  line-height: 24px;
  color: rgb(4 19 58);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}
.search-tab:hover { color: var(--navy-deep); }
/* The source marks the active tab with a 3px rule in its orange, not in navy —
   the same rgb(196, 83, 8) its Log In label uses. */
.search-tab.is-active { color: var(--navy-deep); }
/* The rule sits under the whole tab, at the strip's foot, so it belongs to the
   item that carries the padding rather than to the text box inside it. */
.search-tab-item:has(.is-active) { border-bottom: 3px solid rgb(196 83 8); padding-bottom: 3.5px; }
.search-tab:focus-visible { outline: 2px solid var(--navy-deep); outline-offset: -2px; }

.search-group-more {
  display: inline-block;
  margin-top: 22px;
  font-family: var(--body);
  font-size: 16px;
  line-height: 20px;
  color: var(--steel);
}
/* Takes `.results-pager`'s geometry wholesale: the source paints one pager on
   both pages, five controls around a "1/10" readout. */

/* Type through this block is the source's own: 14/17 summary and excerpt,
   16/25 hit title, 20/25 section heading, all weight 400. */
.search-summary {
  font-family: var(--body);
  font-size: 14px;
  line-height: 17px;
  font-weight: 400;
  color: var(--ink);
  margin: 0 0 23px;
}
.search-group + .search-group { margin-top: 34px; }
.search-group-heading {
  display: block;
  font-family: var(--body);
  font-size: 20px;
  line-height: 25px;
  font-weight: 400;
  /* Black, not the site's navy ink -- state_diff read rgb(0, 0, 0) on the
     source's heading against rgb(4, 19, 58) here, in every state. */
  color: #000;
  /* The source underlines both the section heading and every hit title at rest,
     not only on hover. */
  text-decoration: underline;
  margin: 0 0 39px;
}
/* "View All" is a filled button in the source's orange, not a text link. */
.search-group-more {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 132px;
  height: 30px;
  padding: 0 12px;
  background: rgb(196 83 8);
  color: #fff;
  font-family: var(--body);
  font-size: 16px;
  text-decoration: none;
  border-radius: 0;
  transition: background-color .2s;
}
/* The source fades the same orange to 80% alpha rather than darkening it. */
.search-group-more:hover { background: rgb(196 83 8 / .8); }
/* The source marks the searched term inside each excerpt. */
.search-page mark { background: rgb(196 83 8); color: #fff; }
/* "Sort By:" and its native select, offered on a filtered view only. */
.search-sort {
  /* The source sets this on the summary's own line, right-aligned in the
     column: its label reads x=1040 against a summary at x=250, both at y=541. */
  display: flex;
  align-items: center;
  gap: 6px;
  justify-content: flex-end;
  font-family: var(--body);
  font-size: 14px;
  line-height: 17px;
  color: var(--ink);
  /* Pulled back onto the line the summary opens, which follows it in source
     order so the heading stays first for a screen reader. */
  margin: 0 0 -17px;
}
.search-sort select {
  font: inherit;
  color: inherit;
  background: transparent;
  border: 0;
  padding: 0 4px 0 0;
}
.search-hits { list-style: none; margin: 0; padding: 0; }
.search-hit + .search-hit { margin-top: 35px; }
/* One line, clipped: the source paints every hit title at 25px tall however
   long the page's title is, where ours wrapped to three and pushed each hit
   past its 83px pitch. It reaches that with nowrap and an ellipsis rather
   than a clamp, and the two look the same.

   The break point does not match and cannot: Montserrat sets
   "Personal Injury | Hourigan, Kluger, and Quinn | Top Law Firm in Kingston,
   PA" 762px wide at 20px where the source's Avenir Light sets it 669 -- 14%
   narrower -- so a title the source shows whole loses its last word here.
   Tracking was tried and rejected: -0.42px still left it over the 700px
   column and put us out on letter-spacing, which the source computes as
   `normal` and which IS measurable. Avenir is licensed to Wix and not to us;
   see static/css/fonts.css. */
.search-hit-title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
  overflow: hidden;
  font-family: var(--body);
  font-size: 16px;
  line-height: 25px;
  font-weight: 400;
  color: var(--ink);
  text-decoration: underline;
  /* The source's anchor is as wide as its text; ours filled the 700px column. */
  width: fit-content;
  max-width: 100%;
}
.search-hit-excerpt {
  font-size: 14px;
  line-height: 17px;
  margin: 5px 0 0;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}
/* A hit whose page declares an og:image the source ships: the thumbnail sits
   left of the title and excerpt, which share the remaining width. */
/* 32px after the thumbnail, which is what puts the source's text column at
   x=458 against a row opening at 250: 176 of thumbnail and 32 of gap. */
.search-hit.has-thumb { display: flex; align-items: flex-start; gap: 32px; }
/* The rest of the row, not a fixed 700. The source measures 700 only where a
   thumbnail takes the 208px in front of it; a hit with no thumbnail gets the
   whole 908px column, and pinning every row to 700 left a band of white down
   the right of every one of them. */
/* 20px down from the thumbnail's top, which is where the source starts its
   text: its image opens at 737 and its title at 757 on the same row. Ours ran
   both flush, which read as too little space above the title and too much
   under the excerpt. Only where there is a thumbnail to align against. */
.search-hit-body { flex: 1; min-width: 0; }
.search-hit.has-thumb .search-hit-body { padding-top: 20px; }
/* The row itself is 908 inside the 940 container -- the source insets its
   results from the field and the tab strip above them. */
.search-hits { max-width: 908px; }
.search-hit-thumb {
  flex: none;
  width: 105px;
  height: 70px;
  /* `cover`, as the source computes. It serves each thumbnail already cropped
     to the box -- its images are 176x124 natural -- while we ship the full
     portrait, 1365x2048 for one attorney, so `contain` letterboxed them.
     Biased to the top because these are headshots and a centred crop of a
     portrait cuts the face off; the source's own crop was made server-side
     and shows head and shoulders. */
  object-fit: cover;
  object-position: 50% 15%;
}
/* The firm's card is not a photograph to crop into. Centred rather than
   top-biased, and `cover` as the source computes -- our card is 352x248 and
   the box 176x124, the same aspect to four figures, so cover crops nothing
   and the card's own border stays whole. */
.search-hit-thumb.is-card { object-position: 50% 50%; }
/* The source paints a bigger thumbnail once a tab narrows to one section:
   176x124 on /search?type=pages against 105x70 on the All tab, and gives the
   excerpt a third line to go with it. */
.search-page.is-filtered .search-hit-thumb { width: 176px; height: 124px; }
.search-page.is-filtered .search-hit-excerpt { -webkit-line-clamp: 3; }
/* The title grows with the rest of the filtered row on the DESKTOP build only:
   20px there against 16 on the All tab, while the source's phone build keeps
   16 on both tabs. css_static_check cannot see this one -- it tracks pinned
   dimensions, and a font-size is not one. */
.search-page.is-filtered .search-hit-title { font-size: 20px; }
html[data-device="phone"] .search-page.is-filtered .search-hit-title { font-size: 16px; }
/* The source's filtered-view pager, measured on /search?q=hope&type=pages at
   1440: Previous ends at 677, the 32x32 numbers start at 697 and step 40, and
   Next opens at 789 -- so 20px either side of the numbers and 8px between
   them, centred in the column. */
.search-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 40px 0 0;
  font-family: var(--body);
  font-size: 14px;
}
.search-pager-step {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  /* 40px tall, as the source's is; ours was the 20px of its own line box. */
  height: 40px;
  color: var(--ink);
  text-decoration: none;
  line-height: 20px;
  margin: 0 12px;
}
.search-pager-step.is-off { color: rgb(4 19 58 / .4); }
.search-pager-step:hover { text-decoration: underline; }
.search-pager-page {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  color: var(--ink);
  /* 16px on a 16px line box, as the source sets it. Ours inherited the
     pager's 14/25.2 and set the digits a size small. */
  font-size: 16px;
  line-height: 16px;
  text-decoration: none;
}
/* The current page is the orange at 60% with no fill -- measured
   rgba(196, 83, 8, 0.6) on transparent, and the widget's own Design panel
   calls it "Selected text color" rather than a background. */
.search-pager-page.is-current { color: rgb(196 83 8 / .6); text-decoration: underline; }
.search-pager-page:not(.is-current):hover { text-decoration: underline; }
/* The summary and the excerpt are as wide as their own text on the source,
   not the column they sit in -- the case result's dash reads 442 wide on live
   against the 700 ours filled. */
.search-summary,
.search-hit-excerpt { width: fit-content; max-width: 100%; }

.search-empty-help { font-size: 16px; line-height: 25px; margin-top: 28px; }

html[data-device="phone"] .search-body { padding-block: 17px 56px; }
/* The source paints no thumbnail at all on the phone build -- measured hit by
   hit, the only image in its phone results was the demo store's own row. The
   desktop box is restated as auto rather than left to reach this build. */
html[data-device="phone"] .search-hit-thumb,
html[data-device="phone"] .search-page.is-filtered .search-hit-thumb {
  display: none;
  width: auto;
  height: auto;
}
html[data-device="phone"] .search-hit.has-thumb { display: block; }
/* The desktop column is a fixed 700; the phone gives the text the full width. */
html[data-device="phone"] .search-hit-body { width: 100%; }
/* 41px tall here against the desktop 50, with the icon and the text landing on
   the source's own x: the magnifier at 33 and the field at 47 inside a form
   that starts at the container's 20. */
html[data-device="phone"] .search-form { height: 43px; }
/* The phone field is smaller than the desktop one, so both the magnifier and
   the clear control restate their own size rather than inheriting it. */
html[data-device="phone"] .search-form-icon,
html[data-device="phone"] .search-form-clear { width: 14px; height: 14px; }
html[data-device="phone"] .search-form-input {
  flex: 1;
  width: auto;
  max-width: none;
  height: 41px;
  /* Clears the magnifier, then the source's own 12px before the text: the
     field starts at 47 and the placeholder at 59. */
  margin-left: 26px;
  padding-left: 12px;
}
html[data-device="phone"] .search-form-icon { width: 14px; height: 14px; left: 13px; }
html[data-device="phone"] .search-tab-step { height: 33px; width: 24px; }
/* 132x30 on both builds -- the source draws this button the same size at 1440
   and at 320. */
html[data-device="phone"] .search-group-more { height: 30px; }
/* The source's phone pager is its page numbers alone -- 7x20 text, no filled
   box and no Previous/Next, where the desktop paints 32x32 boxes between two
   labels. Restated here rather than left to inherit the desktop numbers. */
html[data-device="phone"] .search-pager-step { display: none; }
html[data-device="phone"] .search-pager-page {
  width: auto;
  height: 20px;
  background: none;
  color: var(--ink);
}
html[data-device="phone"] .search-tab-step svg { width: 24px; height: 24px; }
/* 8.5px each side, which is what puts the source's first label at x=28 inside a
   column that starts at 20. */
html[data-device="phone"] .search-tabs { margin-bottom: 35px; }
html[data-device="phone"] .search-tab { height: 33px; padding: 0 8.5px; font-size: 14px; line-height: 19.992px; }
html[data-device="phone"] .search-summary { margin-bottom: 19px; line-height: 21px; }
html[data-device="phone"] .search-group-heading { margin-bottom: 34px; }
html[data-device="phone"] .search-hit + .search-hit { margin-top: 23px; }

/* Live suggestions under the header search box.

   ONE box, not two. On the source the field row and the results share a single
   280px container -- measured by driving the live dropdown: its shared
   ancestor spans x=1135..1415 and the results panel x=1137..1413, so the panel
   is the box and the field sits inside it. Building the panel as a separate
   dropdown under a separate field gave two boxes with a seam between them.

   Type and colour also measured there: everything is Libre Baskerville at
   weight 400 in --navy-button (#0B2F5B), on --shell. */
.header-search { position: relative; }
/* Two states, as the source has them.

   Typing anything darkens the field to --shell and thickens its border, at the
   resting width. Only once there are suggestions to show does it widen, and
   then to a fixed 280 however much more is typed -- a query with no results
   stays dark and narrow.

   It grows RIGHTWARD: the source's box runs x=1136..1337 at rest and
   x=1137..1413 open, so its left edge is fixed. In this flex row the field is
   near the right end, so widening it alone would push its left edge outward
   instead; the negative right margin absorbs the growth on the right, which is
   the side the reader is not reading from. */
.header-search.has-text {
  background: var(--shell);
  border: 2px solid var(--navy-deep);
  border-radius: 0;
}
.header-search.is-open {
  width: 280px;
  margin-right: -77px;
  box-sizing: border-box;
  padding-inline: 10px;
  border-bottom: 0;
}
.search-suggest {
  position: absolute;
  /* Flush under the field row and the full width of the box they share --
     including its border, which is why the offsets are negative: the panel
     lines up with the form's border box, not its padding box. */
  top: 100%;
  left: -2px;
  right: -2px;
  background: var(--shell);
  border: 2px solid var(--navy-deep);
  border-top: 0;
  z-index: 200;
  text-align: left;
  font-family: var(--display);
  color: var(--navy-button);
}
.search-suggest-scroll { max-height: 62vh; overflow-y: auto; padding: 2px 0 6px; }
.search-suggest-group {
  font-size: 14px;
  line-height: 19.6px;
  font-weight: 400;
  margin: 12px 0 2px;
  padding: 0 8px;
}
.search-suggest-hit {
  display: block;
  padding: 6px 8px;
  text-decoration: none;
  color: inherit;
}
.search-suggest-hit:hover,
.search-suggest-hit.is-active { background: rgb(255 255 255 / 55%); }
.search-suggest-title {
  display: block;
  font-size: 14px;
  line-height: 21px;
  font-weight: 400;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.search-suggest-excerpt {
  display: block;
  font-size: 12.25px;
  line-height: 17.4px;
  opacity: .75;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.search-suggest-all {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 11px 8px;
  border: 0;
  background: none;
  font-family: var(--display);
  font-size: 10.5px;
  line-height: 15.75px;
  color: var(--navy-button);
  cursor: pointer;
  text-align: left;
}
.search-suggest-all:hover { background: rgb(255 255 255 / 55%); }
/* 12, not 14: typing "car" into the live search at 1440 puts a 12x12 magnifier
   at x=1157 beside the "Search all" label at 1181. The 320 build paints no icon
   on that row at all -- its button is the label alone -- so the phone hides it
   rather than shrinking it. */
.search-suggest-all svg { width: 12px; height: 12px; flex: none; }
html[data-device="phone"] .search-suggest-all svg { display: none; }

.header-search input { transition: width .12s ease; }
.header-search.is-open input {
  width: 199px;
  box-sizing: border-box;
  padding-right: 26px;
}
/* 38 wide with a 24px glyph, and it spans the field's own height: typing "car"
   into the live search puts its Clear button at x=1375..1413 y=58..99 at 1440,
   beside an input that runs 1176..1375 y=58..99, and at x=247..285 y=72..100 on
   the 320 canvas. Ours was 26x26 with a 13px glyph -- half the mark, at both
   widths. */
.header-search-clear {
  position: absolute;
  right: -1px;
  top: 20px;
  transform: translateY(-50%);
  display: none;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 41px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--navy-button);
  cursor: pointer;
  z-index: 1;
}
.header-search.is-open .header-search-clear { display: flex; }
.header-search-clear svg { width: 24px; height: 24px; }

/* The phone build opens it edge to edge: the source's panel spans x=0..320 in
   a 320 viewport rather than sitting under the field. */
html[data-device="phone"] .header-search.is-open { width: auto; }
/* 28 tall rather than the desktop field's 41, and 13px in from the row's right
   edge: the source's control is x=247..285 y=72..100 at 320. */
html[data-device="phone"] .header-search-clear { width: 38px; height: 28px; top: 15px; right: 0; }
html[data-device="phone"] .header-search-clear svg { width: 24px; height: 24px; }
/* 175, which is what the flex row already gives it -- the source's open field
   is 174 wide at x=73 and does not change width when the panel opens. */
html[data-device="phone"] .header-search.is-open input { width: 175px; }
html[data-device="phone"] .search-suggest {
  position: fixed;
  left: 0;
  right: 0;
  width: 100vw;
  box-shadow: 0 12px 32px rgb(4 19 58 / 26%);
}
html[data-device="phone"] .search-suggest-scroll { max-height: 60vh; }

/* The browser's own clear control on type="search", removed: we draw the
   source's "Clear search" button and Chrome was painting a second X beside it. */
.header-search input::-webkit-search-cancel-button,
.header-search input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }

/* The field row does not move or take a fill when the panel opens. Typing into
   the live search at 320 leaves the magnifier at x=47 and the input at x=73,
   174 wide, with the row itself transparent; the shell fill and the 14px inset
   this used to carry shifted the whole field 18px left of that. */
html[data-device="phone"] .header-search.is-open {
  background: none;
}
/* The faint completion behind the field. Sits exactly where the input paints
   its text -- the typed part is invisible but occupies its width, so only the
   remainder shows, in the same face at reduced strength. */
/* The completion painted behind the field. `left`, `top`, `height` and
   `line-height` are all set by search-suggest.js from the field's own box, so
   the two share a baseline -- centring the ghost independently put it a pixel
   or two off the text it continues, which reads as two words rather than one.
   Only the colour differs. */
.header-search-ghost {
  position: absolute;
  left: 40px;
  font-family: var(--display);
  font-size: 14px;
  color: rgb(11 47 91 / 42%);
  pointer-events: none;
  white-space: pre;
  z-index: 0;
}
.header-search-ghost i { visibility: hidden; font-style: normal; }
.header-search input { position: relative; z-index: 1; background: none; }
html[data-device="phone"] .header-search-ghost { left: 40px; }

/* --- Small marks the source draws the same size at 320 as at 1440 ---------
 * Each number below was read off the live phone build beside ours on the page
 * named, and matched. They are restated rather than inherited because an
 * inherited desktop pixel dimension is how nine defects reached the 320 canvas
 * on 2026-09-04; tools/css_static_check.py reports one that is not stated
 * here. Every instance on the page was compared, not the first. */
html[data-device="phone"] .header-search-icon { width: 14px; height: 14px; }   /* /contact, x=47 y=79 on both */
html[data-device="phone"] .footer-chevron { width: 12px; height: 12px; }       /* /contact, inside the 160x42 button */
html[data-device="phone"] .team-icon { width: 21px; height: 21px; }            /* /team, all 42 */
html[data-device="phone"] .team-chevron { width: 12px; height: 12px; }         /* /team, all 21 */
html[data-device="phone"] .team-card-practice::after { width: 76px; height: 3px; }  /* /team, live paints 76 wide by a 3px border */
html[data-device="phone"] .staff-icon { width: 21px; height: 21px; }           /* /staff, all 44 */
html[data-device="phone"] .staff-card-role::after { width: 76px; height: 3px; }     /* /staff, same 76x3 rule */
html[data-device="phone"] .share-link { width: 24px; height: 24px; }           /* /auto-accident-faqs, all 4 at x=16,56,96,136 */
html[data-device="phone"] .share-link svg { width: 24px; height: 24px; }
html[data-device="phone"] .faq-search svg { width: 24px; height: 24px; }       /* /auto-accident-faqs, x=284 y=511.6 */
html[data-device="phone"] .faq-item summary::after { width: 12.5px; height: 12.5px; }
html[data-device="phone"] .home-contact-dot svg { width: 29px; height: 29px; }  /* /, x=145.5 on both */
html[data-device="phone"] .home-social img { width: 39px; height: 39px; }      /* /, all 4 on a 49px pitch */
html[data-device="phone"] .home-wins-rule { width: 36px; height: 5px; }        /* /, x=142 on both */
html[data-device="phone"] .home-form-rule { height: 7px; }                     /* /, a 3px border in a 7px box */
html[data-device="phone"] .home-wins-dots ol { height: 9px; }
html[data-device="phone"] .home-wins-dots button { width: 6px; height: 6px; }   /* /, the three inactive dots */
html[data-device="phone"] .home-wins-dots li[aria-current="true"] button { width: 9px; height: 9px; }
html[data-device="phone"] .hub-btn-chevron { width: 12px; height: 12px; }      /* /personal-injury, all 3 */
/* 5px each side, not the desktop 8: the source's dots sit at x=131.5, 150.5,
   166.5 and 182.5 -- a 16px pitch with a 19px slot under the current one -- and
   its whole list measures 67 wide against the 75 that 8px gives. */
html[data-device="phone"] .home-wins-dots li { padding: 0 5px; }

/* ==========================================================================
   THE 980 TABLET CANVAS
   core/device.py serves every tablet the desktop build at a fixed 980, and
   until 2026-09-03 no command in tools/ ever visited that width -- the desktop
   gates run at 1440 and mobile_report sends a phone UA. Both defects below had
   been on the site for as long as the rules that cause them.
   ========================================================================== */
@media (max-width: 980px) {
  /* `.home-story-inner` pads 748 left and 277 right, which is 1,025px inside a
     980 canvas: the text column computed to width 0 and 1,231 tall, one word
     per line, overflowing the canvas from x=1099. The source puts the column at
     x=506 by 427 wide there. */
  html:not([data-device="phone"]) .home-story-inner { padding: 104px 47px 0 506px; }

  /* The header. Measured against the live site at a 980 viewport with an
   * iPad user agent (2026-09-03): it is the DESKTOP header held at 980, not a
   * narrower build, and it does not reflow -- it OVERLAPS. The wordmark sits
   * at x=16 y=78, 274x20, unshrunk. The nav's first item is a 139.6-wide box
   * at x=42 y=52 with its own opaque white fill (every `<li>` does, one per
   * item, contiguous edge to edge), and it paints AFTER the wordmark in
   * source order, so it covers the wordmark from x=42 rightward -- the
   * wordmark is clipped to its own leftmost 26px, not shrunk. Confirmed with
   * `elementFromPoint` at y=88 walking x=0..300: the hit target is the SVG
   * path up to x=40 and the nav item's own DIV (background rgb(255,255,255))
   * from x=50 on.
   *
   * Log In: the button's own box is x=586 y=57, 131x40, but ours sizes to its
   * content (90x26, matching the avatar's own 26px height) rather than
   * carrying that outer box, so it is placed by the avatar's measured
   * position, x=613 y=64. Search: the icon+field group is x=726 y=57,
   * 201x41, close enough to the 203x43 already carried by `.header-search`
   * to use directly.
   *
   * `.header-inner`'s desktop flex row does not fit 980 either -- Rule 15's
   * defect on this page: two narrower @media rules (1230px, 900px) resolve it
   * by wrapping the row onto a legible second line, which is an improvement
   * over the source and not what was asked for here. The client's own words:
   * copy what Wix is doing, overlap and crop included, rather than spend the
   * time on a nicer arrangement before the deadline. So this drops the flex
   * row for every build but the phone's and places each child by
   * its measured position instead, reproducing the collision. */
  html:not([data-device="phone"]) .header-inner {
    position: relative;
    display: block;
    padding: 0;
    min-height: 227px;
  }
  html:not([data-device="phone"]) .logo {
    position: absolute;
    left: 16px;
    top: 78px;
  }
  html:not([data-device="phone"]) .primary-nav {
    position: absolute;
    left: 42px;
    top: 52px;
    margin: 0;
  }
  html:not([data-device="phone"]) .header-search {
    position: absolute;
    left: 726px;
    top: 57px;
    margin-left: 0;
  }
}
