/*
Theme Name:  PI Base v2
Theme URI:   https://promotingimage.com
Author:      Promoting Image
Version:     2.0.109
Description: PI Base agency starter theme for personal injury law firms. v2.0.108 — hide the sidebar entirely on Spanish contact pages. The /es/contacto/ page carries the full intake form in its body (same way the English contact page does) and a rail with another CTA next to it reads as duplicate conversion furniture. single-pi_espanol.php now checks the post slug and skips the <aside> on 'contacto' and 'contactenos' (both slugs ever used for this page). The .content-grid:not(:has(.sidebar)) CSS rule already handled the single-column fallback, so the main column expands to full width without any extra CSS. Every other Spanish service page still shows the shared Spanish CTA rail from 2.0.107. v2.0.107 — two Spanish fixes rolled together. (1) sidebar-cta.php is now LANGUAGE-AWARE: pi_is_spanish() switches every string, the CTA target (/es/contacto/), the practice-list card, and the "View all" link to Spanish — no second file. single-pi_espanol.php retires its 650px GHL form sidebar and calls the shared rail, same as the English service pages did in 2.0.99. The pa_form_embed per-page escape hatch still renders above the shared rail when set. (2) /es/contactenos/ was HARDCODED across the Spanish header, footer, single-pi_espanol, archive-pi_espanol and now the sidebar rail — but the actual Spanish contact page is at /es/contacto/, so every Spanish Contáctenos button 404'd. All references swapped to /es/contacto/ across the theme. v2.0.106 — EYEBROW CONSISTENCY on service pages. The newer category pages (Dog Bite Lawyer, Wrongful Death, Workplace Accidents, Workers' Compensation, E-Bike Accidents, Class Action) had no banner_eyebrow set, and because they also had no practice_area_slug ACF term, the eyebrow row was empty — same banner part as the older pages, just missing the field. page-banner.php now auto-fills "Practice Area" for any page whose ancestors include the personal-injury-overview hub, and "Overview" for the hub itself. A page with its own banner_eyebrow still wins; this only fills the blank, so no existing page changes. v2.0.105 — two attorney-page fixes. (1) ATTORNEYS ARCHIVE WAS SHOWING A PORTRAIT: page-banner.php's has_post_thumbnail() picked up the first attorney's featured image on /attorneys/, cropping a cropped portrait across the whole hero. Navy is now forced on every archive (is_post_type_archive, is_archive && !is_singular), same way it is on single pi_attorney profiles. (2) PROFILE BANNER STILL TOO TALL: 2.0.103 tightened padding to 32px but the practice-page scale and the --pi-space tokens still read as too much navy around a short block of content. The attorney profile now uses explicit 16/24px padding, 10/6/14px rhythm on breadcrumb/eyebrow/title gaps, and a 30-44px title; !important ends the cascade race against the general .pi-page-banner block. text-transform:none is noted here but the all-caps rendering of a name is a POST TITLE entered in all caps in the admin — rename it in title case to fix. v2.0.104 — breadcrumb and banner consistency across the whole site. Three templates — archive-pi_attorney.php, archive.php (blog archive) and single.php (blog post) — had their own hand-rolled hero markup from before the shared page-banner existed. They rendered breadcrumbs at 11px with inline colours (every other inside page uses the shared .pi-page-banner__breadcrumb at --pi-text-xs), and the two archives ran esc_html() on get_the_archive_title(), which returns "Archives: <span class=\"post-type-archive-title\">Attorneys</span>" — so the literal <span> tags appeared in the trail. All three templates now call the shared page-banner part via $pi_banner_defaults with eyebrow/title/breadcrumb, so the trail text comes from ONE source and the sizing matches every other page. v2.0.103 — compact banner on attorney profiles. With the banner always plain navy and no sub copy, the full practice-page scale (80px cushions, 72px title) left the name floating in navy and a header-to-breadcrumb gap that read as a mistake. Attorney profiles now get tighter banner padding (32px rhythm) and a 34-54px name, scoped by body class in hero.css; every other banner is untouched. v2.0.102 — two attorney fixes. (1) HOMEPAGE TEAM CARDS: the section renders inside the pi-attorneys ACF BLOCK on the homepage, and in a block's render context get_field() without a post ID reads the BLOCK's fields, not the attorney being looped — so attorney_photo always came back empty there and the cards were silently surviving on featured images; the moment a featured image was removed, that card went placeholder on the homepage while the attorneys page (which passes the ID explicitly) stayed fine. All three get_field calls in template-parts/sections/attorneys.php now pass get_the_ID(). (2) ATTORNEY PROFILE RAIL: the 650px GHL form is out of the profile sidebar, same decision as the service pages — the intake form lives on the contact page. Profiles now use the shared sidebar-cta rail (compact CTA + practice list), with a small direct-email line beneath it when the attorney has an email set. v2.0.101 — ATTORNEY PROFILES: one image field, always-navy banner. The attorney edit screen offered two image fields ("Banner Background Image" in the Page Banner box and "Profile Photo" in Attorney Details) with nothing saying which fed what, and tonight a headshot landed in the banner field — photo in the banner, navy placeholder on the team cards. Three changes close the trap: (1) the Page Banner field group no longer appears on pi_attorney, so Profile Photo is the ONLY image field an attorney has (banner eyebrow/title fall back to the template defaults they already rendered from); (2) page-banner.php forces plain navy on attorney profiles in CODE, so a banner_image or featured image still saved in the database can't sneak back into the banner; (3) single-pi_attorney.php's duplicate-avoidance test ($banner_uses_featured) is retired — the banner never shows the featured image now, so hiding it from the profile body would be hiding it everywhere. Editor rule going forward: headshot goes in Profile Photo, nothing else needed. v2.0.100 — three changes, all client direction 11 Oct. (1) BANNER IMAGE INHERITANCE: page-banner.php gains a fourth cascade step — a page with no banner_image and no featured image of its own borrows the NEAREST ANCESTOR'S featured image before falling to navy. One photo on a hub now banners its whole section; "Plain Navy Banner" still opts any page out and a page's own image still wins, so nothing already styled changes. (2) THE RAIMONDO FAMILY band copy retired site-wide: the client does not want family framing. Kicker is now "Your Long Island Lawyers", text drops "Three generations of legal excellence" — changed in attorneys.php, template-attorneys.php, archive-pi_attorney.php here and in all six managed team bands via Site Core 1.7.2. (3) The kicker's dark-on-dark: .pi-team-band__kicker (bare class) was outranked by .main-col p / .entry-content p (class+element), so the gold rule lost and the kicker rendered body-grey on navy — the same specificity trap as the card deck. Selector is now .pi-team-band p.pi-team-band__kicker, matching the weight the __text line already had (which is why the text was never wrong). v2.0.99 — ONE RAIL ON EVERY SERVICE PAGE, NO FORM IN IT. Client direction 11 Oct: some service pages had the 650px GoHighLevel form sidebar, some had nothing, and the intake form is meant for the contact page only. NEW template-parts/sections/sidebar-cta.php renders the rail everywhere: a compact navy CTA card speaking the same line as the nav panel ("Injured? Speak to a Lawyer Today." / free case review button to the contact page / phone / live-chat pointer), plus a related-pages card that fills itself from the page tree — a hub lists its children, a sub-page lists its sisters, with SEO noise ("Long Island", "Attorney") trimmed off label ends and Medical Malpractice excluded from sibling lists to match the menu decision (the family still lists on the Med Mal pages themselves). template-practice-area.php drops its form card AND its hardcoded areas list (which still promoted Medical Malpractice and pre-reorg URLs); pa_form_embed stays as a per-page escape hatch. page.php now opts every descendant of the Practice Areas overview into the rail automatically, so the four new category pages match the hubs without anyone touching a checkbox; "Show sidebar form" still opts outside pages in, but it now gets the CTA rail, not the form. STICKY, FIXED PROPERLY: both sidebar grids set align-items:start, which sized the aside to its own content and left position:sticky nowhere to travel — the aside now stretches to the row height so the short card actually follows the reader down the article, and .sidebar-sticky's top offset finally includes --pi-notice-height so the rail doesn't tuck under the LATEST UPDATE bar. v2.0.98 — the homepage Workplace Accidents card points at the real page again: the four category pages Mike requested on 5 Oct (Workplace Accidents, Workers' Compensation, E-Bike Accidents, Class Action) are now written and published via Site Core 1.7.0, so the /contact-us/ holding pattern from 2.0.89 ends. v2.0.97 — team band bottom padding for the composited photo (which no longer bleeds to the band edge); otherwise identical to 2.0.96 (notice bar). v2.0.96 — NEW site-wide notice bar (inc/notice-bar.php): the LATEST UPDATE banner linking the Suffolk County red-light camera settlement page existed only on the live Elementor site and would have vanished at cutover. Renders as the first child of the fixed header; every top-offset calc now adds --pi-notice-height (0 by default, 44px while body carries .pi-notice-on, set server-side so layout is correct without JavaScript); dismiss stores a key derived from the notice itself, so a future different notice reappears on its own. Copy is the approved 28 Sep banner copy — do not re-word it to imply an eligibility check; the firm cannot determine eligibility, only Kroll can. Configure or disable via the notice_* keys in config/theme-config.php. v2.0.95 — nav panel rollover fix: the boxed-link :hover selector outranked the CTA card's base rule (the pseudo-class adds specificity), so hovering the Free Consultation button stripped its gold background and left navy text on navy. The CTA card is now excluded from the boxed-link rules and the button's hover restates background and color in full — gold stays gold, links roll to gold, nothing rolls to navy-on-navy. v2.0.94 — the mega menu is REPLACED after client review against other injury firms. (1) NAV PANEL: any top-level item with 6+ direct children gets an anchored three-column panel — services flowing down two columns of boxed links, and a CTA column (“Injured? Speak to a lawyer today.” + free consultation + phone + a line pointing at the live chat bottom-right). Under 6 children (About) stays a plain dropdown; chevrons on all parents. The full-bleed panel is gone — it spanned beneath the whole bar, so leaving the About dropdown mid-scroll handed the hover to Practice Areas; an anchored panel only exists under its own item, which removes that bug by construction. Third-level menu items are hidden from the desktop panel: depth now lives on the hub pages as card decks. Mobile slider untouched. (2) blocks/pi-verdicts.php: a type-filtered strip no longer ALSO requires verdict_featured — that double condition meant hub pages showed nothing until someone flagged verdicts — and its View All link pointed at /verdicts-settlements/, which does not exist; now /verdicts/. v2.0.93 — supersedes the 2.0.92 build sent the same morning (never uploaded): the mega panel is now FULL-BLEED — it spans the whole navy bar like the reference design, with the columns capped at 1240px and centred by a padding formula so links never stretch on ultrawides — and a tall group (8+ links) now FLOWS into the next panel column at full box width instead of splitting into two skinny sub-columns that broke words in half (Airline/Helicopte-r). overflow-wrap relaxed from anywhere to break-word for the same reason. v2.0.92 — (1) MEGA MENU, desktop only. The Practice Areas tree is three levels deep; as stacked flyouts it had no arrows and hid 23 pages behind a second precise hover. Any top-level item whose submenu contains a third level now opens a full-width panel: second-level items become gold smallcaps column headers, their children render as boxed links laid flat, a group of 8+ splits into two sub-columns, childless second-level items render as boxed links rather than stranded headers, and a CTA card (Free Consultation + phone, from piData) flows to the end. Chevrons on every top-level parent. main.js classifies from the live menu markup (pi-has-mega / pi-mega__leaf / pi-mega__tall), so Appearance -> Menus drives the panel and no code knows the menu's contents; without JavaScript nothing is added and the 2.0.91 dropdown behaviour remains. The whole block sits inside min-width:1025px - below that the desktop nav is display:none and the slider menu takes over, so mobile is untouched by construction. Flat dropdowns (About) stay dropdowns, plus the chevron. (2) Content components for the About Us and Retaining the Firm rebuilds, on the pi-cards foundation: .pi-card--person portrait cards, .pi-video-callout (navy band whose play button carries data-video-id and opens the existing footer lightbox via initVideoModal - no new JS), and .pi-team-band (the transparent group PNG on navy, where it was cut to sit). v2.0.91 — two changes. (1) THE CARD DECK SELECTOR. 2.0.90's .pi-cards rules targeted the outer group div, but this is a classic theme with no theme.json, so WordPress renders group blocks with the LEGACY markup and injects a wp-block-group__inner-container between .pi-cards and the cards. display:grid on .pi-cards therefore laid out exactly ONE grid item and the sixteen cards stacked inside it in normal flow. Theme CSS, a plugin stylesheet and inline styles were each correct and each applied to the wrong element, which is why several different fixes all looked like nothing happening. The deck now targets the inner wrapper, falling back to .pi-cards where no wrapper exists, with !important because the authored markup still carries an inline display:grid on the outer div. Diagnose this class of fault from the RENDERED html: the saved post_content was correct throughout. (2) --pi-prose-max 900px to 1200px at the client's direction: at 900px inside a 1500px container these pages read as under-filled and the deck could only fit two columns. This widens every .pi-measure body, .faq-inner, .cta-inner, .content-narrow and single-column .main-col, so paragraphs of pure prose now run nearer 120 characters and want to be shorter than they were. v2.0.90 — NEW .pi-cards card deck plus a "Card grid (3 across)" block pattern. The practice-area grid on Practice Areas was a wp:columns block, which is a fixed row of N: sixteen tiles meant four rows of four, every label wrapped mid-word, and adding a seventeenth area means re-cutting the rows by hand — that is exactly how seven tiles ended up crammed in one row in Site Core 1.3.0. .pi-cards is ONE group on a CSS grid, so the browser decides the rows: three across on desktop, two at 1024px, one at 640px, and a leftover card on the last row keeps its own width instead of stretching full-page the way an orphan wp:column does. The card matches pi-steps and pi-status — white, a hairline #eaecf0 stroke, 6px radius — so it reads as the same system rather than a second card style; hover borrows pi-area-card's gold top rule so the light and dark decks feel related. Headings drop to 21px because article-size type in a narrow tile is what forced the two-line labels. The whole card is the click target via an ::after overlay on the heading link, not just the five words of the heading. Mirrored into editor.css so the deck looks the same in Gutenberg. v2.0.89 — the home page practice-area card "Workplace Accidents" pointed at a page that exists but is a DRAFT, so it returned 404 to every logged-out visitor while looking fine to an administrator. It now points at /contact-us/, like the matching tiles on the Practice Areas page; restore the real URL the day that page is published. v2.0.88 — hero banner, second pass. The attorneys PNG is an absolutely positioned layer pinned to the bottom edge, so its WIDTH is the only thing controlling its height: it was too small, which is why the group sat low with dead navy above their heads. Photo is now 58 percent (capped 880px), min-height is 840px so the taller image is not clipped by the section overflow, and the headline column is derived with calc from the photo width plus a 72px gap, so widening the photo moves the text right instead of letting the two overlap. Headline tops out at 66px to hold one line in the narrower column. All four values are CSS variables at the top of hero.css — --pi-hero-photo-w, --pi-hero-photo-max, --pi-hero-gap, --pi-hero-min-h — so the proportions can be dialled without touching any rule. NOTE: if dead space remains above their heads after this, it is transparent padding baked into the PNG, which scales with the image; that needs the asset cropped, not more CSS. v2.0.87 — hero banner composition. The attorneys photo was pinned to the SECTION left edge and capped at 780px, while the headline sat at the right of the centred 1500px band. Below ~1450px the two happen to meet; above it the photo stops growing while the band keeps sliding right, so a navy gap opens and widens with the viewport — about 330px on a 2000px display, which is what read as the photo shooting left and the text shooting right. The photo is now anchored to the content band rather than the viewport, so both halves sit in the same centred box at any width. The headline was also capped at 640px while the type scaled to 86px, which forced a four-line H1 on exactly the wide screens with room to spare; the column is 760px and the type tops out at 70px so "Long Island's Trusted" sets on one line. v2.0.86 — Mike Raimondo's review comments, 5 Oct 2026. (1) The homepage practice-area grid swaps Medical Malpractice for Workplace Accidents; he asked for the same area to come out of Case Results too, so this is a deliberate shift of emphasis rather than a tidy-up. (2) The intro checklist drops the hard figure '$10,000,000+ Recovered' for 'Millions Recovered'. (3) founding_year is 1990 — he confirmed the date that was left blank in 2.0.85 pending an answer. 2026 minus 1990 is 36, so 'nearly 40 years' and 'Fighting for you since 1990' now agree; the homepage's own saved block value is corrected by the Site Core sweep, which a theme default cannot reach. v2.0.85 — client copy changes from Michael Raimondo, plus the review widget. (1) "Long Island's Most Trusted" is gone everywhere: the hero H1 is now "Long Island's Trusted / Personal Injury Lawyers" and the hero sub is Michael's replacement copy. David Raimondo did not want a superlative claim about the firm. (2) Every "over 30 years" in THEME code is now "nearly 40 years" — footer tagline, both intro variants, the attorney section and bio, the attorneys archive and template, the Spanish footer and Spanish archive (rewritten as fixed Spanish, "por casi 40 anos", since interpolating years_experience there produced "por mas de Nearly 40 anos"). years_experience is now the display string 'Nearly 40'; pi-hero-banner's sub was rebuilt because 'for over ' . years_experience . ' years' had become 'for over Nearly 40 years'. NOTE: 41 PAGES AND POSTS carry the claim in their own CONTENT and are NOT touched by this theme — they need a separate content sweep. (3) FIX: the homepage intro read $cfg['founded_year'] while the config key is 'founding_year', so it always printed the hardcoded 1994 fallback no matter what was set — while the config said 1993 and the firm now says nearly 40 years, implying the late 1980s. Three answers on one site. The key is fixed and the year is BLANK pending confirmation from the firm: the line renders "Fighting for You" with no date rather than a fourth guess. Set the year in Site Settings and "Since <year>" returns. (4) The hero block now consults Site Settings for its H1, em line and sub before its hardcoded fallback; it previously read only its own ACF field, so the "Hero H1" setting did nothing on the homepage and the headline could only be changed in PHP. (5) NEW pattern 'Homepage — Suffolk red-light settlement note' carrying Michael's copy verbatim, including the word "proposed" (the settlement is pending court approval). Its CSS is deliberately UNSCOPED: every other .pi-callout rule sits under .entry-content, and front-page.php is a bare the_content() passthrough with no such wrapper, so a pattern on the homepage would otherwise render unstyled. (6) NEW inc/review-comments.php — the Promoting Image pi.js comment widget for client review. data-page and data-title are deliberately omitted so the script reads the real pathname and title per request; hardcoding data-page="/" as the Island Dental snippet does would file every page's comments under one key. Desktop only, enforced three ways: wp_is_mobile() server-side, navigator.userAgentData.mobile (true on Chrome for Android EVEN IN DESKTOP-SITE MODE, which is the only signal that survives that mode and the fix for the Pixel case), and (hover:hover) and (pointer:fine) with a 1024px floor. Refuses to render on longislandaccident.com whatever the setting, so launch cannot leave a public comment layer on the firm's site; the pi.js file carries its Firebase config and admin key in plain text. Toggle in Site Settings, set after the array_filter merge in helpers because that filter strips a deliberate false. v2.0.84 — ONE form, everywhere, no placeholders left. (1) blocks/pi-hero.php: the homepage hero card's "Get Your Free Consultation" form was six inputs, a select and a Submit button that were not inside a <form> and were not wired to anything — on the firm's highest-traffic page, every lead it collected was silently lost. Now the real GoHighLevel embed. (2) single-pi_town.php: pi_town_ghl_form() no longer prints "Editors only: add a GoHighLevel Form ID" when the per-town field is empty. The firm has one form; asking an editor to paste its ID into 31 Service Area entries guaranteed an empty sidebar on every town page. Resolution is now town_ghl_form -> Site Settings ghl_form_id -> hardcoded default, the same order the shared partial uses. (3) single-pi_town.php: the loader guard was a function-static flag that only knew about its own embeds, so a town page rendering both the town form and the shared partial loaded form_embed.js twice and raced two initialisers over the same iframes. Both now guard on the PI_GHL_SCRIPT_PRINTED constant. (4) templates/template-settlement.php: the news band's editor-only "GHL form goes here" note is replaced by the form itself — visitors saw an empty column, editors saw a to-do nobody actioned. (5) Gravity Forms branches removed from the hero block, the practice-area sidebar and the Spanish sidebar. All three tested a hardcoded form ID 1 against a plugin that is not installed, so they never fired — but installing Gravity Forms later would have swapped whatever form happened to be #1 into those sidebars site-wide. The pa_form_embed / settlement_form_embed ACF fields stay as per-page escape hatches. (6) content.css: .pi-ghl-form resets border, margin and background so the embed adds no seam inside the card that wraps it, and declares color-scheme: light — a cross-origin iframe with no declaration inherits the VIEWER's dark-mode preference, which turned the form's fields charcoal inside a white card. v2.0.80 — (1) NEW /patterns/ directory: seven block patterns registered automatically by WordPress, built from core blocks carrying the content classes content.css already defines (pi-status, pi-callout, pi-steps, pi-faq-item). The CSS for these shipped in 2.0.67 and 2.0.70 but nothing produced markup that used it, so editors had no way to reach them. The town pattern deliberately covers the long-form body ONLY — single-pi_town.php already renders the steps, practice grid, FAQ and CTA, so a second copy in the_content() would render twice. (2) inc/patterns.php registers the "PI Base" pattern category and hides core's bundled library so the firm's layouts are not buried under a few hundred wordpress.org ones. (3) FIX: .verdict-amount was still set in Playfair. The 2.0.79 change to lining/tabular sans figures was applied to .pi-verdict-card__amount, but .verdict-amount is the class template-verdicts.php (Case Results), template-practice-area.php and template-parts/sections/verdicts.php actually output — so the fix never reached those pages. Now matched. (4) editor.css maps the content-card styles onto .editor-styles-wrapper; content.css scopes them under .entry-content, which does not exist in the canvas, so patterns previewed unstyled. v2.0.58 — (1) Breadcrumbs: the current-page crumb can now be set independently of the H1 via $pi_banner_defaults['breadcrumb']. Previously both read the ACF banner_title field, so a marketing headline like "$57.5 Million Red-Light Camera Settlement" was forced into the navigation trail. Default behaviour is UNCHANGED — crumb still falls back to banner_title — so town/attorney/verdict/practice pages render exactly as before; only template-settlement.php opts in. (2) page-banner.php no longer assigns get_queried_object() to $post; load_template() globalizes $post, so archive templates were having the global clobbered with a WP_Term/WP_Post_Type. (3) New 'pi_render_silo_enabled' filter lets a template suppress the town silo; the settlement page opts out (filter, not display:none, so the links are absent from the DOM rather than hidden). (4) Settlement template: removed 144px of stacked dead whitespace between the cream signup section and the article body. Includes 2.0.50 schema changes that 2.0.48 claimed but never actually wrote to disk: the firm node now declares @type ["LegalService","LocalBusiness"] (one node claiming both types, rather than two competing nodes saying it twice), and adds the recommended `image` property. The 2.0.48 edit script threw before writing the file, and the parity check grepped for words that also appeared in its own comments — so it reported green against a file it had not changed. Verification now parses the actual array keys with comments stripped. Includes 2.0.49 (duplicate form heading removed), 2.0.47 (HTML entities decoded before entering JSON-LD), 2.0.42 (schema dedupe guard).
Requires at least: 6.4
Requires PHP: 8.0
License: GPL v2 or later
Text Domain: pi-base
*/

/* Real styles live in /assets/css/ as split files. */
