/*
Theme Name: Macchi & Macchi Counsel
Theme URI: https://macchi-law.com/
Author: Trellist
Description: A multi-page WordPress theme for Macchi & Macchi, LLC, a Norwood, MA land use, real estate, and estate planning firm founded in 1965. Custom post types for Practice Areas and Attorneys, a contact form, and structured data for local SEO. Styled to the firm brand guide: PMS 295 blue with Cool Gray 1, Palatino wordmark, Times New Roman throughout.
Version: 2.6.8
Requires at least: 6.6
Requires PHP: 7.4
Text Domain: macchi-law
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

DESIGN TOKENS
=============
Palette and typography are taken from the Macchi & Macchi brand guide.

Color:
  --brick      #365072  PRIMARY brand blue (PMS 295) - buttons, headings, accents
  --brick-deep #27405E  hover/pressed blue
  --brand-gray #D9D8D6  SECONDARY brand gray (Cool Gray 1) - rules, bands, accents
  --ink        #2B333C  primary text
  --ink-soft   #5A6169  secondary text
  --parchment  #FFFFFF  page background
  --parchment-deep #F1F0EE  banded section background (tint of the brand gray)
  --slate      #2D4463  alternate dark band
  --error      #8A2F1F  functional error red (independent of the brand)

NOTE ON TOKEN NAMES: --brick/--brass/--slate and the .section-- / has- 
class names are retained from the v1 design language for backward
compatibility with block content already imported into the database.
They are token names, not color descriptions; the values above are
authoritative. Rebranding is a one-block edit here plus theme.json values.

Type:
  Logo: "Palatino" (logo text only)  |  Everything else: "Times New Roman"
  No webfonts are loaded; both are system fonts.

Layout:
  Max content width 1180px, 2px radii.
*/

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

html {
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

body {
  margin: 0;
  padding: 0;
}

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

figure {
  margin: 0;
}

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

a {
  color: inherit;
  text-decoration: none;
}

button {
  font: inherit;
  cursor: pointer;
}

input,
textarea,
select {
  font: inherit;
  color: inherit;
}

table {
  border-collapse: collapse;
  width: 100%;
}

/* ---------- Tokens ----------
   Palette and type are taken from the Macchi & Macchi brand guide.

     Primary   Blue  #365072  (PMS 295)
     Secondary Gray  #D9D8D6  (Cool Gray 1)

   The brand supplies exactly two colours, so the neutrals below are derived
   from them rather than invented: text greys are desaturated toward the blue,
   and section bands are tints of the brand grey.

   TOKEN NAMES are deliberately unchanged from v1 (--brick / --brass / --slate)
   because .section--brick and has-brick-* class names already exist in block
   content stored in the database. They are token names, not colour
   descriptions. Rebranding again means editing only this block plus the
   matching palette in theme.json. */
:root {
  /* Brand */
  --brand-blue: #365072;
  --brand-gray: #d9d8d6;

  /* Text. Desaturated toward the brand blue rather than pure black. */
  --ink: #2b333c;
  --ink-soft: #5a6169;

  /* Surfaces */
  --parchment: #ffffff;
  --parchment-deep: #f1f0ee;

  /* Primary blue. --brick is the brand primary; --brick-deep is its
     hover/pressed state. */
  --brick: #365072;
  --brick-deep: #27405e;

  /* Formerly gold. Remapped to the brand grey so no off-brand colour survives
     anywhere in the stylesheets that still reference these names. */
  --brass: #d9d8d6;
  --brass-text: #5a6169;
  --brass-light: #d9d8d6;

  /* Alternate dark band, a slightly deeper blue than the primary so the two
     dark sections are distinguishable when stacked. */
  --slate: #2d4463;
  --slate-pale: #e9ebee;

  --line: rgba(43, 51, 60, 0.16);
  /* Interactive control borders must reach 3:1 per WCAG 1.4.11. --line is a
     decorative hairline and is not sufficient for form fields. */
  --line-strong: #6f767e;
  /* Functional error red, independent of the brand primary. */
  --error: #8a2f1f;
  --white: #ffffff;

  /* Two-tone focus ring: dark core plus light halo, so one of the two always
     clears 3:1 whichever brand surface it lands on. */
  --focus-core: #1d2a3a;
  --focus-halo: #ffffff;

  --header-height: 84px;

  /* Brand guide typography, followed literally:
       Palatino          -> LOGO TEXT ONLY
       Times New Roman   -> all body copy, which includes headings
     Both are system fonts on Windows and macOS, so the theme loads no webfont
     at all now (the previous Fraunces + Public Sans Google Fonts request is
     gone, which also removes a third-party request from every page load). */
  --font-logo: Palatino, "Palatino Linotype", "Book Antiqua", "URW Palladio L", Georgia, serif;
  --font-display: "Times New Roman", Times, "Liberation Serif", Georgia, serif;
  --font-body: "Times New Roman", Times, "Liberation Serif", Georgia, serif;
  --font-ui: "Times New Roman", Times, "Liberation Serif", Georgia, serif;

  --container: 1180px;
  --gutter: clamp(22px, 6vw, 28px);
  --radius: 2px;
  --radius-sm: 1px;
}

/* ---------- Environment guards ----------
   Field evidence from a live install: environment CSS constrained BODY itself
   with !important (not just body's children), which made every plain-rule
   defense irrelevant because #macchi-site's width:100% resolves against a
   700px body.

   The counter is a cascade layer. For !important declarations the cascade
   order inverts: rules inside an @layer beat unlayered !important rules
   regardless of specificity or load order. An injected
   `body { max-width: 700px !important }` from any plugin or global stylesheet
   loses to the layer below, no matter when it loads.

   html margin-TOP is deliberately untouched: WordPress core uses
   `html { margin-top: 32px !important }` for the admin bar.

   A runtime backstop in main.js additionally forces these as inline
   important styles and reports any offending stylesheet to the console. */
@layer macchi-guard {
  html {
    width: 100% !important;
    max-width: none !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
  }

  body {
    width: 100% !important;
    max-width: none !important;
    margin: 0 !important;
  }

  #macchi-site {
    width: 100% !important;
    max-width: none !important;
    margin: 0 !important;
  }
}

/* Unlayered duplicates for anything old enough to lack @layer support. */
html body {
  width: 100% !important;
  max-width: none !important;
  margin: 0 !important;
}

html body > #macchi-site,
#macchi-site {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100% !important;
  max-width: none !important;
  margin: 0 !important;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--parchment);
  overflow-x: clip;
}

/* If the canvas ever shows through, it shows parchment, never white. */
html {
  background: var(--parchment);
}

#macchi-site > main {
  flex: 1 0 auto;
  width: 100%;
  max-width: none;
}

#macchi-site > .site-header,
#macchi-site > .site-footer {
  width: 100%;
  max-width: none;
}

/* ---------- Base ---------- */
body {
  background: var(--parchment);
  color: var(--ink);
  font-family: var(--font-body);
  /*
   * Times New Roman has a markedly smaller x-height than the Public Sans it
   * replaced, so matching the old 17px made every line look thin and shrunken.
   * 1.15rem (~18.4px) restores the apparent size the design was drawn at.
   * rem, not px, so the reader's browser font-size preference still applies.
   */
  font-size: 1.15rem;
  line-height: 1.7;
  /*
   * No -webkit-font-smoothing: antialiased here. It thins glyph stems, which is
   * survivable for a sans but leaves a serif looking washed out and fragile.
   * Default (subpixel) rendering keeps the Times stems solid.
   */
  text-rendering: optimizeLegibility;
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  color: var(--brick);
  line-height: 1.18;
  margin: 0 0 0.5em;
  font-weight: 700;
  letter-spacing: -0.005em;
}

h1 {
  font-size: clamp(2.5rem, 4.4vw, 3.9rem);
  font-weight: 700;
  letter-spacing: -0.015em;
}

h2 {
  font-size: clamp(1.9rem, 3.2vw, 2.5rem);
  font-weight: 700;
}

h3 {
  font-size: 1.34rem;
  font-weight: 700;
}

h4 {
  font-size: 1.05rem;
  font-weight: 600;
}

p {
  margin: 0 0 1.2em;
}

p:last-child {
  margin-bottom: 0;
}

strong {
  font-weight: 700;
}

em,
.italic {
  font-style: italic;
}

/* Links inside prose */
.entry-content a,
.prose a {
  color: var(--brick);
  text-decoration: underline;
  text-decoration-color: var(--brass-light);
  text-underline-offset: 3px;
  text-decoration-thickness: 1.5px;
}

.entry-content a:hover,
.prose a:hover {
  color: var(--brick-deep);
  text-decoration-color: var(--brick);
}

/* ---------- Accessibility ---------- */
/* Uses clip-path, NOT the legacy `clip`. WordPress core ships its own
   .screen-reader-text:focus rule that resets width/height/clip-path, but it does
   not reset legacy `clip`. A `clip: rect(1px,1px,1px,1px)` here therefore survived
   focus and painted the skip link as a zero-width sliver even though it was
   focused and occupying 171x49px of layout. Verified with a screenshot. */
.screen-reader-text {
  position: absolute !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
  padding: 0;
  margin: -1px;
}

/* Anything visually-hidden becomes fully visible when focused. Covers the skip
   link and any other .screen-reader-text on a focusable element. */
.screen-reader-text:focus,
.screen-reader-text:focus-within {
  clip: auto;
  clip-path: none;
  width: auto;
  height: auto;
  margin: 0;
  overflow: visible;
  white-space: normal;
}

.skip-link {
  position: absolute;
  left: 0;
  top: -60px;
  background: var(--ink);
  color: var(--white);
  padding: 0.9em 1.4em;
  z-index: 10000;
  transition: top 0.15s ease;
  font-size: 0.9rem;
  letter-spacing: 0.02em;
}

/* `a.skip-link:focus` (0,2,1) deliberately outspecifies WordPress core's own
   `.screen-reader-text:focus` (0,2,0), which otherwise repaints the focused skip
   link in core's default grey (#ddd on #444) instead of the theme's navy. */
a.skip-link:focus {
  top: 0;
  clip: auto;
  clip-path: none;
  width: auto;
  height: auto;
  margin: 0;
  overflow: visible;
  background: var(--ink);
  color: var(--white);
  padding: 0.9em 1.4em;
  font-size: 0.9rem;
  text-decoration: none;
  border-radius: 0 0 var(--radius) 0;
}

/* main receives focus from the skip link but should not draw a ring itself. */
main:focus {
  outline: none;
  box-shadow: none;
}

/* Two-tone focus ring: dark outline + light halo via box-shadow. Guarantees a
   visible indicator on parchment, white, ink, slate, and brick alike. */
:focus-visible {
  outline: 3px solid var(--focus-core);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px var(--focus-halo);
  border-radius: var(--radius);
}

/* On dark sections the roles swap so the bright ring sits against the dark. */
.section--brick :focus-visible,
.section--slate :focus-visible,
.site-footer :focus-visible,
.cta-banner :focus-visible {
  outline-color: var(--focus-halo);
  box-shadow: 0 0 0 5px var(--focus-core);
}

/* Anchor targets clear the sticky header instead of hiding behind it.
   Scoped to headings, sections and landmarks rather than the previous bare
   [id], which applied a scroll offset to every single element carrying an id. */
:target,
h1[id],
h2[id],
h3[id],
h4[id],
h5[id],
h6[id],
section[id],
article[id],
main[id],
div[id].section,
[id].wp-block-heading {
  scroll-margin-top: calc(var(--header-height) + var(--wp-admin--admin-bar--height, 0px) + 16px);
}

/* Long URLs, case citations, and email addresses must not force h-scroll. */
body {
  overflow-wrap: break-word;
}

/* ---------- Layout utilities ---------- */
/* The page gutter lives in a custom property so component rules can reuse it
   instead of re-declaring (or accidentally zeroing) it. Scales down a little on
   narrow phones, where a fixed 28px eats too much of a 360px screen. */
.container {
  max-width: var(--container);
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}

.container--narrow {
  max-width: 820px;
}

section {
  position: relative;
}

.section {
  padding: clamp(56px, 8vw, 108px) 0;
}

.section--tight {
  padding: clamp(40px, 5vw, 64px) 0;
}

.section--brick {
  background: var(--brick);
  color: var(--white);
}

.section--slate {
  background: var(--slate);
  color: var(--white);
}

.section--deep {
  background: var(--parchment-deep);
}

.section--brick h2,
.section--slate h2,
.section--brick h3,
.section--slate h3 {
  color: var(--white);
}

.grid {
  display: grid;
  gap: 32px;
}

.grid--3 {
  grid-template-columns: repeat(3, 1fr);
}

.grid--2 {
  grid-template-columns: repeat(2, 1fr);
}

@media (max-width: 900px) {
  .grid--3 {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 640px) {
  .grid--3,
  .grid--2 {
    grid-template-columns: 1fr;
  }
}

/* ---------- Eyebrow / recording-stamp label ---------- */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-body);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brick);
  margin-bottom: 14px;
}

.section--brick .eyebrow,
.section--slate .eyebrow {
  color: var(--brass-light);
}

.eyebrow::before {
  content: "";
  width: 26px;
  height: 1px;
  background: currentColor;
  display: inline-block;
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0.01em;
  padding: 14px 26px;
  border: 1.5px solid transparent;
  border-radius: var(--radius);
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease, transform 0.1s ease;
  white-space: nowrap;
}

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

.btn-primary {
  background: var(--brick);
  color: var(--white);
  border-color: var(--brick);
}

.btn-primary:hover {
  background: var(--brick-deep);
  border-color: var(--brick-deep);
  color: var(--white);
}

.btn-ghost {
  background: transparent;
  color: var(--white);
  border-color: rgba(255, 255, 255, 0.5);
}

.btn-ghost:hover {
  background: rgba(255, 255, 255, 0.12);
  border-color: var(--white);
}

.btn-outline {
  background: transparent;
  color: var(--ink);
  border-color: var(--ink);
}

.btn-outline:hover {
  background: var(--ink);
  color: var(--white);
}

.btn-sm {
  padding: 11px 18px;
  font-size: 0.85rem;
}

/* WCAG 2.5.5 Target Size: interactive controls stay at least 44px tall. */
.btn,
.pdf-chip,
.pa-pill {
  min-height: 44px;
}

.btn svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

/* ---------- Misc ---------- */
.hr-line {
  border: none;
  border-top: 1px solid var(--line);
  margin: 2.4em 0;
}

.lede {
  font-size: 1.2rem;
  color: var(--ink-soft);
  max-width: 62ch;
}

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

.mx-auto {
  margin-left: auto;
  margin-right: auto;
}

/* ---------- Breadcrumbs (ordered list) ---------- */
.breadcrumbs__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  list-style: none;
  margin: 0;
  padding: 0;
}

.breadcrumbs__list li {
  display: inline-flex;
  align-items: center;
}

/* Decorative separator, generated rather than sitting in the markup. */
.breadcrumbs__list li + li::before {
  content: "/";
  margin: 0 8px;
  opacity: 0.5;
}

/* ---------- Post / archive / search entries ---------- */
.entry-meta {
  font-size: 0.85rem;
  color: var(--ink-soft);
  letter-spacing: 0.02em;
}

.archive-entry {
  padding-bottom: 40px;
  margin-bottom: 40px;
  border-bottom: 1px solid var(--line);
}

.archive-entry:last-of-type {
  border-bottom: none;
}

.archive-entry h2 {
  font-size: 1.5rem;
  margin-bottom: 6px;
}

.archive-description {
  color: var(--ink-soft);
  max-width: 62ch;
}

.post-nav {
  display: flex;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  margin-top: 48px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  font-weight: 600;
}

.post-nav a {
  color: var(--brick);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.search-form-wrap {
  margin-top: 22px;
  max-width: 460px;
}

.search-form-wrap input[type="search"] {
  width: 100%;
  padding: 12px 14px;
  min-height: 44px;
  border: 1.5px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--white);
}

.search-form-wrap .search-submit {
  margin-top: 10px;
  padding: 12px 22px;
  min-height: 44px;
  background: var(--brick);
  color: var(--white);
  border: 1.5px solid var(--brick);
  border-radius: var(--radius);
  font-weight: 700;
}

.page-links {
  margin-top: 28px;
  font-weight: 600;
}

.section__lede-centered {
  max-width: 56ch;
  margin: 0 auto 28px;
  color: var(--slate-pale);
}

/* ---------- Sidebar / credential headings ----------
   These are h2/h3 for document structure (the old h4s skipped two levels down
   from the page h1) but keep the compact visual scale the design expects. */
.credentials-block__heading,
.pa-sidebar__heading,
.related-attorneys h3 {
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 600;
  line-height: 1.25;
  margin: 0 0 16px;
  color: var(--ink);
}

.credentials-block__heading:not(:first-child) {
  margin-top: 26px;
}

/* ---------- Whole-card links ----------
   One link per card, stretched to cover it. Keeps the accessible name equal to
   the title while making the full card a click target. */
.pa-card,
.attorney-card {
  position: relative;
}

.pa-card__link::after,
.attorney-card__link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

/* Any genuinely interactive child must sit above the stretched overlay. */
.pa-card a:not(.pa-card__link),
.attorney-card a:not(.attorney-card__link) {
  position: relative;
  z-index: 2;
}

/* The stretched link's own focus ring would be invisible (the <a> box is just
   the text), so the ring is drawn on the card instead. */
.pa-card:has(.pa-card__link:focus-visible),
.attorney-card:has(.attorney-card__link:focus-visible) {
  outline: 3px solid var(--focus-core);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px var(--focus-halo);
}

.avatar-placeholder__icon {
  width: 56px;
  height: 56px;
  display: block;
  margin: 0 auto 14px;
}

/* ---------- Small layout utilities ----------
   These replace the inline style="" attributes that were scattered across the
   templates, so spacing and colour stay in one place and stay rebrandable. */
.mt-sm {
  margin-top: 22px;
}

.mt-md {
  margin-top: 36px;
}

.mt-lg {
  margin-top: 40px;
}

.muted {
  color: var(--ink-soft);
}

.lede-sm {
  color: var(--ink-soft);
  font-size: 1.05rem;
}

.cluster-center {
  display: flex;
  gap: 14px;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 28px;
}

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

.grid--align-center {
  align-items: center;
}

.site-footer__seal {
  margin-top: 22px;
}

.site-footer__heading--spaced {
  margin-top: 26px;
}

.hero__art {
  color: var(--slate);
}

.hero__art-inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--brick);
}

.form-notice__list {
  margin: 0;
  padding-left: 18px;
  list-style: disc;
}

.form-notice__intro {
  margin-bottom: 8px;
}

.field__optional {
  font-weight: 400;
  color: var(--ink-soft);
}

.form-fineprint {
  font-size: 0.82rem;
  color: var(--ink-soft);
  margin-top: 14px;
}

.cta-copy-centered {
  max-width: 56ch;
  margin: 0 auto 28px;
  color: rgba(254, 253, 250, 0.85);
}

/* ---------- Scroll reveal: failsafe by construction ----------
   Content is visible by default. These hide-for-animation rules apply only
   under html.js-reveal, a class main.js adds strictly AFTER its
   IntersectionObserver is attached. If the script is blocked, mangled by an
   optimizer, or throws, nothing is ever hidden. A previous version hid
   [data-reveal] unconditionally, which made most of the homepage invisible
   whenever JavaScript failed; that inversion is deliberately gone. */
html.js-reveal [data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}

html.js-reveal [data-reveal].is-revealed {
  opacity: 1;
  transform: translateY(0);
}

/* ---------- Brand wordmark ----------
   The four lockups from the brand guide. Set in Palatino per the guide, which
   reserves that face for logo text only.

   One deliberate deviation, for accessibility: the guide's secondary grey
   (#D9D8D6, Cool Gray 1) measures 1.3:1 against white and cannot legally carry
   text. It is used here for the rule and the keyline — where it is decorative —
   while the strapline uses a grey derived from it that clears AA. The blue and
   the grey are otherwise exactly as specified. */
.macchi-logo {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 5px;
  line-height: 1.05;
  text-align: left;
}

.macchi-logo__name {
  font-family: var(--font-logo);
  font-variant: small-caps;
  font-weight: 400;
  /* Fluid, so the wordmark and the menu button stay on one row once the page
     gutter is accounted for. At a fixed 1.62rem the two together exceeded a
     360px screen and the header wrapped onto two lines. */
  font-size: clamp(1.06rem, 4.4vw, 1.62rem);
  letter-spacing: 0.045em;
  color: var(--brick);
  white-space: nowrap;
}

.macchi-logo__rule {
  display: block;
  width: 100%;
  height: 1px;
  background: var(--brand-gray);
}

.macchi-logo__strap {
  font-family: var(--font-logo);
  font-variant: small-caps;
  font-size: clamp(0.58rem, 1.9vw, 0.72rem);
  letter-spacing: clamp(0.14em, 0.6vw, 0.22em);
  color: var(--ink-soft);
  white-space: nowrap;
}

/* Blue & white, for the brand blue or any dark ground. */
.macchi-logo--on-dark .macchi-logo__name {
  color: var(--white);
}

.macchi-logo--on-dark .macchi-logo__strap {
  color: var(--brand-gray);
}

.macchi-logo--on-dark .macchi-logo__rule {
  background: rgba(217, 216, 214, 0.55);
}

/* The guide's bordered lockup: grey keyline when the logo sits on a dark
   background that needs the edge defined. */
.macchi-logo--bordered {
  border: 1px solid var(--brand-gray);
  padding: 12px 18px;
}

.macchi-logo--bordered .macchi-logo__name {
  color: var(--white);
}

.macchi-logo--bordered .macchi-logo__strap {
  color: var(--brand-gray);
}

/* Single colour, inherits from its context. */
.macchi-logo--mono .macchi-logo__name,
.macchi-logo--mono .macchi-logo__strap {
  color: currentColor;
}

.macchi-logo--mono .macchi-logo__rule {
  background: currentColor;
  opacity: 0.4;
}

/* ---------- Bundled brand photography ---------- */
.bundled-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ---------- Brand photography placements ---------- */

/* Hero: the firm's own Norwood zoning map. */
.hero__map {
  width: 100%;
  height: auto;
  border: 1px solid var(--brand-gray);
  border-radius: var(--radius);
}

.hero__art-caption {
  margin-top: 12px;
  font-size: 0.82rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  text-align: center;
}

/* Generic framed image used on the About and Firm History pages. */
.media-frame {
  margin: 0;
  border: 1px solid var(--brand-gray);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--parchment-deep);
}

.media-frame img {
  width: 100%;
  height: auto;
  display: block;
}

.media-frame--wide {
  margin-bottom: 48px;
  max-height: 420px;
}

.media-frame--wide img {
  height: 100%;
  object-fit: cover;
}

/* ---------- Photography treatment ----------
   The firm's photographs come from several sources at different sizes, colour
   temperatures and noise levels. Left raw they read as mismatched stock. A
   restrained brand wash — a blue tint plus a slight desaturation — pulls them
   into one family and takes the edge off the JPEG noise in the smaller
   originals. This follows the brand guide's own treatment: the banner on its
   opening page is tinted the same way. */
.photo-treat {
  position: relative;
  overflow: hidden;
  background: var(--parchment-deep);
}

.photo-treat img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  filter: saturate(0.82) contrast(1.04);
  transition: transform 0.5s ease, filter 0.3s ease;
}

.photo-treat::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    170deg,
    rgba(54, 80, 114, 0.16) 0%,
    rgba(54, 80, 114, 0.06) 45%,
    rgba(43, 51, 60, 0.22) 100%
  );
  pointer-events: none;
}

/* Practice-area card photography. Bleeds to the card edges; the card supplies
   the horizontal padding, so only the sides are pulled out. */
.pa-card__media {
  margin: 0 -30px 22px;
  aspect-ratio: 16 / 9;
  border-bottom: 1px solid var(--brand-gray);
}

.pa-card:hover .pa-card__media img {
  transform: scale(1.04);
  filter: saturate(0.95) contrast(1.02);
}

@media (prefers-reduced-motion: reduce) {
  .photo-treat img,
  .pa-card:hover .pa-card__media img {
    transition: none;
    transform: none;
  }
}

/* Martindale-Hubbell AV Preeminent badge. */
.avrating__badge {
  width: 150px;
  height: auto;
  flex-shrink: 0;
}

.not-found-wrap__mark {
  display: flex;
  justify-content: center;
  margin-bottom: 24px;
}

/* WCAG 2.2 SC 2.5.8: the hero's inline phone link measured 23px tall. */
.hero__contact-line a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}

/* ---------- Hero composition ----------
   The map column was vertically centred against a much taller text column,
   which left it floating in dead space. Giving it a portrait-ish crop lets it
   carry its side of the grid. */
.hero__art {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.hero__map {
  aspect-ratio: 5 / 4;
  object-fit: cover;
  object-position: center 42%;
}

@media (max-width: 900px) {
  .hero__map {
    aspect-ratio: 16 / 9;
  }
}
