/* ============================================================================
   Legacy brand cleanup — the ONLY C9 stylesheet that is not scoped to .c9.

   The 672 blog posts and 50 archives are not ported; they render through Divi
   and will keep doing so. But they still carry HOST's old caution yellow, which
   is precisely the colour Kyle asked to retire from the brand — so a visitor who
   lands on a post from search sees the old identity beside the new one.

   This is deliberately narrow: it retires the yellow and restyles the forms.
   It does not attempt to redesign those pages.
   ========================================================================== */

/* --- Gravity Forms, sitewide -----------------------------------------------
   The submit button is HOST's old #FFDE00 on every form on every post. The C9
   form styling was scoped to .c9 and so never reached them, which is why the
   brand's loudest retired colour survived on the highest-traffic template. */
.gform_wrapper .gform_footer input[type="submit"],
.gform_wrapper .gform_button,
.gform_wrapper input[type="submit"] {
  font-family: "Inter Variable", system-ui, sans-serif !important;
  font-weight: 700 !important;
  font-size: 15px !important;
  color: #020819 !important;
  background: #E3B200 !important;      /* C9 gold, not #FFDE00 */
  border: 0 !important;
  border-radius: 5px !important;
  padding: 13px 26px !important;
  text-transform: none !important;
  transition: background .15s, transform .12s;
}
.gform_wrapper .gform_footer input[type="submit"]:hover,
.gform_wrapper .gform_button:hover,
.gform_wrapper input[type="submit"]:hover {
  background: #F0C114 !important;
  transform: translateY(-1px);
}

/* Inputs get the same treatment so a form does not read as two eras at once. */
.gform_wrapper input[type="text"],
.gform_wrapper input[type="email"],
.gform_wrapper input[type="tel"],
.gform_wrapper input[type="number"],
.gform_wrapper select,
.gform_wrapper textarea {
  font-family: "Inter Variable", system-ui, sans-serif;
  font-size: 16px;                     /* 16px or iOS zooms on focus */
  border: 1px solid rgba(11, 43, 84, .14);
  border-radius: 5px;
  padding: 12px 14px;
}
.gform_wrapper input:focus,
.gform_wrapper select:focus,
.gform_wrapper textarea:focus {
  outline: none;
  border-color: #0B2B54;
  box-shadow: 0 0 0 3px rgba(11, 43, 84, .10);
}

/* --- retired yellows --------------------------------------------------------
   #FFDE00, #FFD902 and #FED900 are the three legacy yellows in use, written
   inline into post content by the editor. Attribute selectors are the only way
   to reach an inline style without editing 672 posts, and they are precise: they
   match that exact declaration and nothing else.

   Text on the old yellow was black, and C9's gold is darker, so the foreground
   is forced to the ink colour to keep contrast. */
[style*="#FFDE00"], [style*="#ffde00"],
[style*="#FFD902"], [style*="#ffd902"],
[style*="#FED900"], [style*="#fed900"],
[style*="rgb(255, 222, 0)"], [style*="rgb(255, 217, 2)"], [style*="rgb(254, 217, 0)"] {
  background-color: #E3B200 !important;
  color: #020819 !important;
}

/* Divi's own button styling on unported templates. */
.et_pb_button {
  background-color: #E3B200 !important;
  border-color: #E3B200 !important;
  color: #020819 !important;
}
.et_pb_button:hover { background-color: #F0C114 !important; }

/* --- the child theme's own hard-coded yellows -------------------------------
   Divi-child/style.css and scss/child-theme.css write #ffde00 directly into a
   dozen rules. Those files are the client's, not ours — tools/deploy_child_theme
   does not sync them and editing them would be overwritten by any future theme
   work — so the colour is retired here instead, selector for selector.

   Listed explicitly rather than blanket-overridden so it stays obvious what is
   being changed and why, and so a rule we have not seen keeps its own styling
   rather than being silently recoloured. */
h2.pageTitle::before, h3.pageTitle::before,
h2.pageTitle:before,  h3.pageTitle:before,
.services-title:before,
.check-bullets ul li:before,
.circle-bullets ul li:before { background-color: #E3B200 !important; }

.check-bullets ul li:before,
.circle-bullets ul li:before { color: #E3B200 !important; background: none !important; }

.services-submit-button,
.s-yellow-slide {
  background-color: #E3B200 !important;
  color: #020819 !important;
  border-radius: 5px !important;
  text-transform: none !important;
}
.services-submit-button:hover, .s-yellow-slide:hover { background-color: #F0C114 !important; }

/* --- the footer, on a phone, on a blog post ---------------------------------
   The child theme carries `.single.single-post h4 { font-size: 22px !important }`
   under a max-width:550px query. It is meant for the post body, but the C9
   footer is inside the post page too, so SERVICES / RESOURCES / FIRM rendered at
   22px there and 11px everywhere else — the same shared footer, twice the size,
   on one template at one breakpoint. It survived every sweep because the footer
   looks deliberate at any size and nothing overflowed.

   `!important` can only be beaten by `!important`, and c9.css is generated so
   the rule cannot move there. Scoped to the three footer headings — the only
   h4s inside .c9 — so post-body h4s keep the client's mobile sizing. */
@media (max-width: 550px) {
  body.single-post .c9 .foot-col h4 { font-size: 11px !important; }
}

/* --- the Salesforce web-to-lead forms ---------------------------------------
   14 ported pages embed a raw Salesforce form in page content rather than a
   Gravity Form: about-us, custom-tax-matrix, doola, stripe, trs, resources,
   tax-help-desk, sales-tax-audit-defense, voluntary-disclosure-agreement,
   economic-nexus-clarified, free-sales-tax-software-review, home-page-new and
   both host-managed-service pages.

   Every rule above is keyed to .gform_wrapper, so none of it reaches these:
   they were rendering in Divi's Open Sans with square grey inputs directly
   below C9 prose set in Inter. Same treatment, keyed to the form's action so it
   cannot touch anything else on the page. */
.c9 form[action*="webto.salesforce.com"] input[type="text"],
.c9 form[action*="webto.salesforce.com"] input[type="email"],
.c9 form[action*="webto.salesforce.com"] input[type="tel"],
.c9 form[action*="webto.salesforce.com"] select,
.c9 form[action*="webto.salesforce.com"] textarea {
  font-family: "Inter Variable", system-ui, sans-serif;
  font-size: 16px;                     /* 16px or iOS zooms on focus */
  border: 1px solid rgba(11, 43, 84, .14);
  border-radius: 5px;
  padding: 12px 14px;
  width: 100%;
}
.c9 form[action*="webto.salesforce.com"] input:focus,
.c9 form[action*="webto.salesforce.com"] select:focus,
.c9 form[action*="webto.salesforce.com"] textarea:focus {
  outline: none;
  border-color: #0B2B54;
  box-shadow: 0 0 0 3px rgba(11, 43, 84, .10);
}
.c9 form[action*="webto.salesforce.com"] .services-submit-button {
  font-family: "Inter Variable", system-ui, sans-serif;
  font-size: 16px !important;
  font-weight: 600;
  padding: 13px 22px !important;
}

/* The checkbox sat hard against its label with no gap — 13px of default browser
   control against 15px of Inter.

   Spacing lives on the control, not on a wrapper: the two pages disagree about
   the markup. doola wraps each row in .service-cbox-wrapper, custom-tax-matrix
   hangs the inputs straight off the <form>, so a rule keyed to the wrapper
   styled one page and silently missed the other. A margin on the input itself
   reaches both. */
.c9 form[action*="webto.salesforce.com"] input[type="checkbox"] {
  width: 16px;
  height: 16px;
  margin: 0 9px 0 0;
  vertical-align: -3px;
  accent-color: #E3B200;
}
.c9 form[action*="webto.salesforce.com"] .service-cbox-wrapper { margin-bottom: 5px; }
.c9 form[action*="webto.salesforce.com"] .services-label { line-height: 1.5; }

/* The reCAPTCHA box sat flush on the Submit button, 0px between them, on every
   Salesforce form (Noel, 29 Sep 2026: "the spam protect ... and the submit
   button are too close"). On staging the box is the note below; on production
   the 78px widget sits in the same place, so the space is kept on both. */
.c9 form[action*="webto.salesforce.com"] .g-recaptcha { margin: 16px 0 20px; }

/* .services-title carries a 50x3px gold accent bar pinned at top: 44px, which
   assumes the heading is one line. "SERVICES (CHECK ALL THAT APPLY):" wraps on
   a 390px viewport, so the bar landed across the second line and read as a
   stray underline struck through the word APPLY. Anchor it to the bottom of
   the heading instead of a fixed offset from the top. */
.c9 .services-title::before { top: auto; bottom: -4px; }

/* …and the bar needs somewhere to sit. Anchored to the bottom of the heading it
   landed on the first checkbox row, which follows immediately. */
.c9 form[action*="webto.salesforce.com"] .services-title,
.c9 .c9-prose .services-title { margin-bottom: 18px; }

.s-black-slide { color: #E3B200 !important; }

/* Gutenberg block headings the editor gave a yellow field, and Divi's search
   submit. Both need !important — the source rules carry it, so a plain
   declaration loses however specific the selector is. */
h1.wp-block-heading, h2.wp-block-heading,
h3.wp-block-heading, h4.wp-block-heading {
  background-color: transparent !important;
  color: #0B2B54 !important;
}
/* html body … — Divi prints its dynamic CSS inline in <head> AFTER enqueued
   stylesheets, so at equal specificity and importance the inline block wins.
   The extra ancestors buy the specificity back. */
html body .et_pb_searchsubmit,
html body input.et_pb_searchsubmit,
html body #page-container .et_pb_searchsubmit {
  background-color: #E3B200 !important;
  border-color: #E3B200 !important;
  color: #020819 !important;
}

/* ============================================================================
   C9 typography for the long tail — posts, archives, search, 404.

   672 posts and 50 archives are not ported and will keep rendering through
   Divi. They already wear the C9 header and footer, so the content between them
   reading as 2017 Divi — different typeface, bright blue links, Divi's heading
   scale — is the most visible inconsistency left on the site.

   Scoped to the body classes for those templates ONLY. The 77 unported Divi
   PAGES are deliberately untouched: several are ad landing pages whose layouts
   depend on Divi's own type metrics, and restyling them blind would break them.
   ========================================================================== */
/* The case studies are a `project`, not a `post`, and every rule below was
   scoped to single-post — so the two pages HOST uses to sell (VSCO, Nautique
   Parts) still rendered in Divi's 2017 defaults: #7a7a7a body text and #4687d1
   links. Measured rather than eyeballed: 4.29:1 for the body copy and 3.72:1 for
   the links, both under AA, on the only two pages on the site that were failing.
   The same selectors now cover single-project. */
body.single-post #main-content,
body.single-project #main-content,
body.archive #main-content,
body.blog #main-content,
body.search #main-content,
body.error404 #main-content {
  font-family: "Inter Variable", system-ui, sans-serif;
  color: #4A5670;
}

body.single-post #main-content h1,
body.single-project #main-content h1, body.archive #main-content h1,
body.blog #main-content h1, body.search #main-content h1, body.error404 #main-content h1,
body.single-post #main-content h2,
body.single-project #main-content h2, body.archive #main-content h2,
body.blog #main-content h2, body.search #main-content h2, body.error404 #main-content h2,
body.single-post #main-content h3,
body.single-project #main-content h3, body.archive #main-content h3,
body.blog #main-content h3, body.search #main-content h3, body.error404 #main-content h3,
body.single-post #main-content h4,
body.single-project #main-content h4, body.archive #main-content h4,
body.blog #main-content h4, body.search #main-content h4 {
  font-family: "Inter Variable", system-ui, sans-serif;
  color: #0B2B54;
  letter-spacing: -.02em;
  padding-bottom: 0;
}
body.single-post #main-content h1,
body.single-project #main-content h1, body.archive #main-content h1, body.blog #main-content h1 {
  font-weight: 800; font-size: clamp(30px, 3.4vw, 40px); line-height: 1.1;
}
body.single-post #main-content h2,
body.single-project #main-content h2, body.archive #main-content h2, body.blog #main-content h2 {
  font-weight: 800; font-size: clamp(23px, 2.4vw, 29px); line-height: 1.2; margin-top: 1.6em;
}
body.single-post #main-content h3,
body.single-project #main-content h3, body.archive #main-content h3, body.blog #main-content h3 {
  font-weight: 700; font-size: 20px; line-height: 1.3; margin-top: 1.4em;
}

body.single-post #main-content p,
body.single-project #main-content p,
body.archive #main-content p,
body.blog #main-content p,
body.search #main-content p {
  font-size: 17px;
  line-height: 1.72;
  color: #4A5670;
}

/* Divi's link blue is the last un-branded colour on these templates. C9 uses a
   gold underline rather than a colour change — on a page of navy headings a
   coloured link competes, while an underline reads as a link at any size. */
body.single-post #main-content a:not(.et_pb_button):not(.btn),
body.single-project #main-content a:not(.et_pb_button):not(.btn),
body.archive #main-content a:not(.et_pb_button):not(.btn),
body.blog #main-content a:not(.et_pb_button):not(.btn),
body.search #main-content a:not(.et_pb_button):not(.btn) {
  color: #0B2B54;
  text-decoration: none;
  box-shadow: inset 0 -1px 0 0 #E3B200;
  transition: box-shadow .15s, color .15s;
}
body.single-post #main-content a:not(.et_pb_button):not(.btn):hover,
body.single-project #main-content a:not(.et_pb_button):not(.btn):hover,
body.archive #main-content a:not(.et_pb_button):not(.btn):hover,
body.blog #main-content a:not(.et_pb_button):not(.btn):hover,
body.search #main-content a:not(.et_pb_button):not(.btn):hover {
  color: #826700;
  box-shadow: inset 0 -2px 0 0 #E3B200;
}
/* Headings that are links should not carry the underline twice. */
body.single-post #main-content h1 a,
body.single-project #main-content h1 a, body.single-post #main-content h2 a,
body.single-project #main-content h2 a,
body.archive #main-content h2 a, body.blog #main-content h2 a,
body.archive #main-content h1 a, body.blog #main-content h1 a { box-shadow: none; }

/* Lists get the C9 gold dash rather than a browser bullet.
   Not inside a table cell: this is body-copy spacing — a 26px indent, .5em
   between items, 17px/1.72 — and in a four-column rate table it is most of the
   row height. Excluded here rather than out-specified in the table rule, which
   took two rounds and still lost: this selector carries an ID and two classes
   and nothing reasonable beats it. */
body.single-post #main-content .entry-content ul:not(.c9-tablewrap ul) > li,
body.single-project #main-content .entry-content ul:not(.c9-tablewrap ul) > li,
body.single-post #main-content .et_pb_text ul:not(.c9-tablewrap ul) > li ,
body.single-project #main-content .et_pb_text ul:not(.c9-tablewrap ul) > li {
  position: relative; list-style: none; padding-left: 26px;
  font-size: 17px; line-height: 1.72; margin-top: .5em;
}
body.single-post #main-content .entry-content ul,
body.single-project #main-content .entry-content ul,
body.single-post #main-content .et_pb_text ul ,
body.single-project #main-content .et_pb_text ul { padding-left: 0; }
body.single-post #main-content .entry-content ul:not(.c9-tablewrap ul) > li::before,
body.single-project #main-content .entry-content ul:not(.c9-tablewrap ul) > li::before,
body.single-post #main-content .et_pb_text ul:not(.c9-tablewrap ul) > li::before ,
body.single-project #main-content .et_pb_text ul:not(.c9-tablewrap ul) > li::before {
  content: ""; position: absolute; left: 2px; top: .72em;
  width: 7px; height: 2px; background: #E3B200;
}

/* Sidebar widget titles pick up the mono micro-label register. */
body.single-post #main-content .widgettitle,
body.single-post #main-content h4.widgettitle,
body.archive #main-content .widgettitle {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 11px; font-weight: 600; letter-spacing: .16em;
  text-transform: uppercase; color: #826700;
}

/* ============================================================================
   Blog listings — the Divi blog module, wherever it appears.

   Targeting body classes was not enough: /blog/ is a PAGE with a Theme Builder
   layout, so its body classes are `page page-id-1900`, never `blog`. It kept
   Open Sans at 14px while the posts and category archives had already moved to
   Inter. Styling the module instead covers the blog page, the archives, and any
   other listing built with it.
   ========================================================================== */
.et_pb_post {
  padding-bottom: 34px;
  margin-bottom: 34px;
  border-bottom: 1px solid rgba(11, 43, 84, .14);
}
.et_pb_post:last-of-type { border-bottom: 0; }

.et_pb_post .entry-title,
.et_pb_post h2.entry-title,
.et_pb_post_title .entry-title {
  /* Colour set here rather than via a body-class rule. The listing page's own
     <h1 class="entry-title"> sits inside .et_pb_post_title, and Divi's default
     .entry-title colour kept winning over `body.page-id-1900 #main-content h1`
     — the font-size applied while the colour did not, which is the tell that a
     more specific rule owns that one property. */
  color: #0B2B54;
  font-family: "Inter Variable", system-ui, sans-serif !important;
  font-size: 23px;
  font-weight: 800;
  line-height: 1.25;
  letter-spacing: -.02em;
  margin: 0 0 10px;
  padding-bottom: 0;
}
.et_pb_post .entry-title a {
  color: #0B2B54 !important;
  text-decoration: none;
  box-shadow: none !important;
}
.et_pb_post .entry-title a:hover { color: #826700 !important; }

/* Date and categories become the mono micro-label register, so the card has a
   clear hierarchy: label, headline, summary. */
.et_pb_post .post-meta,
.et_pb_post .post-meta a {
  font-family: "IBM Plex Mono", ui-monospace, monospace !important;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #826700 !important;
  box-shadow: none !important;
}
.et_pb_post .post-meta { margin-bottom: 12px; }
.et_pb_post .post-meta a:hover { color: #0B2B54 !important; }

.et_pb_post .post-content,
.et_pb_post .post-content p {
  font-family: "Inter Variable", system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.65;
  color: #4A5670;
}

.et_pb_post .entry-featured-image-url,
.et_pb_post img { border-radius: 6px; }

/* Divi's "read more" and the archive pagination. */
.et_pb_post .more-link,
.pagination a, .wp-pagenavi a, .wp-pagenavi span.current {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 11px; font-weight: 600; letter-spacing: .14em;
  text-transform: uppercase; color: #826700 !important;
  box-shadow: none !important;
}

/* The listing page's own title — "Blog" rendered at body size with no hierarchy.
   `html body …` because Divi prints per-module colour rules inline in <head>,
   AFTER enqueued stylesheets; at equal specificity the inline block wins and the
   heading stayed black while the size took effect. */
html body.page-id-1900 #main-content h1,
html body.archive #main-content .page-title,
html body.search #main-content .page-title,
body.page-id-1900 #main-content h1,
body.archive #main-content .page-title,
body.search #main-content .page-title {
  font-family: "Inter Variable", system-ui, sans-serif;
  font-size: clamp(30px, 3.4vw, 40px);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -.025em;
  color: #0B2B54;
  margin-bottom: 26px;
}

/* Divi's search field in the listing. */
/* `.et_pb_s` is here because Divi ships TWO search markups and this rule only
   ever matched one. The classic widget renders .et_pb_searchform; the Search
   MODULE renders .et_pb_search > input.et_pb_s, and that is what the blog page
   uses — so its border stayed #FFD902, one of the retired yellows, 941px wide
   and directly under the page title.

   It survived the sitewide yellow retirement because that pass targets inline
   style attributes, and this colour comes from a Divi SHORTCODE attribute
   (button_color="#FFD902") which Divi compiles into its own generated
   stylesheet. Nothing matching on [style*="#FFD902"] can ever see it. The
   colour itself is fixed at source — the module now carries --c9-gold — and
   this rule is what keeps the INPUT's border a hairline instead of inheriting
   the button's colour.

   `html body` is on that selector for specificity, not decoration. Divi
   compiles the module's colour into
     .et_pb_search_0 input.et_pb_s { border-color:… !important }
   which scores (0,2,1) — exactly what `.et_pb_search input.et_pb_s` scores —
   and its generated sheet loads after this one, so an identical-specificity
   rule loses on source order alone. Two element selectors are enough to win. */
.et_pb_searchform input[type="text"],
.et_pb_searchform input[type="search"],
html body .et_pb_search input.et_pb_s,
#main-content input[type="search"] {
  font-family: "Inter Variable", system-ui, sans-serif;
  font-size: 16px;
  border: 1px solid rgba(11, 43, 84, .14) !important;
  border-radius: 5px 0 0 5px;
  padding: 12px 14px;
  background: #fff;
}

/* The blog listing's own H1 is black because someone set it that way in Divi's
   Post Title MODULE, which emits
     .et_pb_post_title_0 .et_pb_title_container h1.entry-title { color:#000 !important }
   into its unified stylesheet. Nothing short of beating that exact selector will
   move it — three earlier attempts changed the font size and left the colour
   untouched, which is the signature of an !important rule owning one property.

   Matching by class rather than the _0 index so it survives the module being
   reordered, and adding `html body` to clear its specificity. The proper fix is
   to change the module setting in Theme Builder; this holds until someone does. */
html body .et_pb_post_title .et_pb_title_container h1.entry-title,
html body .et_pb_post_title .et_pb_title_container h2.entry-title {
  color: #0B2B54 !important;
}

/* ---------------------------------------------------------------------------
   Single posts: the dead right-hand column.

   The body template is a 2/3 + 1/3 Divi row. On a typical article the left
   column runs 9,768px and the sidebar stops at 1,906px, so roughly 7,800px of
   the page — most of it — is a blank third of the screen. It reads as a broken
   layout, and it happens on all 672 posts.

   Sticky fixes it and earns its keep: the consultation form rides the whole
   article instead of scrolling out of reach in the first screen.

   The row is display:block with floated columns, NOT flex. That is fine and in
   fact necessary: a sticky element is constrained by its containing block, and
   here that is the row (9,928px), so the sidebar can travel the full article.
   Do not "tidy" this into a flex row — align-self would then cap the travel at
   the column's own height and the sticky would do nothing.

   Capped to the viewport because the sidebar (1,906px) is taller than most
   screens; without max-height its lower half would pin off-screen and Archives
   and Categories would be permanently unreachable.
   --------------------------------------------------------------------------- */
@media (min-width: 981px) {
  /* Divi puts `overflow-x:hidden; overflow-y:auto` on #page-container to contain
     its animations. That makes #page-container a scroll container, so it — not
     the window — becomes the sticky element's nearest scrolling ancestor. Since
     it is exactly as tall as its content it never scrolls, and the sticky simply
     never engages: position computes to `sticky` and the element still scrolls
     away, which is a maddening thing to debug.

     `clip` still clips horizontally but does NOT create a scroll container, so
     sticky resolves against the window again. Pairing it with `visible` on the
     other axis is deliberate and legal: `visible` only degrades to `auto` when
     its partner is hidden/scroll/auto, not when the partner is `clip`. */
  body.single-post #page-container {
    overflow-x: clip;
    overflow-y: visible;
  }

  body.single-post .et_pb_row_0_tb_body .et_pb_column_1_3 {
    position: sticky;
    top: 95px;                        /* 75px fixed header + 20px breathing room */
    max-height: calc(100vh - 115px);
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: rgba(11, 43, 84, .25) transparent;
  }
  body.single-post .et_pb_row_0_tb_body .et_pb_column_1_3::-webkit-scrollbar {
    width: 6px;
  }
  body.single-post .et_pb_row_0_tb_body .et_pb_column_1_3::-webkit-scrollbar-thumb {
    background: rgba(11, 43, 84, .25);
    border-radius: 3px;
  }
  body.single-post .et_pb_row_0_tb_body .et_pb_column_1_3::-webkit-scrollbar-track {
    background: transparent;
  }
}

/* ---------------------------------------------------------------------------
   reCAPTCHA on staging.

   The site key is registered to handsoffsalestax.com, so on this host Google
   renders a red "ERROR for site owner: Invalid domain for site key" box inside
   every form — the sidebar form on all 672 posts, plus the contact and service
   pages. It is an environment problem, not a design one, but during a review it
   reads as broken work.

   So on staging ONLY the dead widget is swapped for a plain note saying what is
   actually true. The field is not removed and nothing is faked: the form still
   will not submit until the staging domain is added to the reCAPTCHA key, which
   is Kyle's to do. The `.c9-staging` class is set from the hostname in
   c9_staging_body_class(), so production is untouched and shows the real widget.

   The Salesforce web-to-lead forms embed the widget themselves as a bare
   `<div class="g-recaptcha">` — no Gravity Forms markup anywhere near it — so
   the selectors below missed them and Google's red error box was still sitting
   in the middle of 11 ported pages, custom-tax-matrix and about-us among them.
   Both shapes are covered now. */
body.c9-staging .gfield--type-captcha .ginput_recaptcha > div,
body.c9-staging .gfield--type-captcha .ginput_recaptcha iframe,
body.c9-staging .g-recaptcha > div,
body.c9-staging .g-recaptcha iframe {
  display: none !important;
}

body.c9-staging .gfield--type-captcha .ginput_recaptcha,
body.c9-staging .g-recaptcha {
  min-height: 0;
  padding: 12px 14px;
  border: 1px dashed rgba(11, 43, 84, .28);
  border-radius: 6px;
  background: rgba(11, 43, 84, .03);
}

body.c9-staging .gfield--type-captcha .ginput_recaptcha::after,
body.c9-staging .g-recaptcha::after {
  content: "Spam protection is active on the live domain. It is switched off here on staging.";
  display: block;
  font-family: "Inter Variable", system-ui, sans-serif;
  font-size: 13px;
  line-height: 1.45;
  color: rgba(11, 43, 84, .62);
}

/* ---------------------------------------------------------------------------
   One consultation form per post, not two.

   The body template carries the form twice: once in the sidebar (Gravity form
   14) and again in a full-width band below the article (form 1). They share a
   heading and five of six fields — the band asks for "Work Email", the sidebar
   for "Email Address" — so it reads as a mistake rather than a second chance.

   Making the sidebar sticky exposed it: the sidebar's Submit button now comes to
   rest about 140px above the band's identical heading.

   Neither form is deleted; one is hidden per viewport, whichever is in the wrong
   place there:

     desktop — the sticky sidebar form is on screen for the whole article, so the
               band adds nothing. Hide the band.
     mobile  — the sidebar stacks below a 15,800px article and lands in the
               middle of Recent Posts / Archives / Categories. The band is a
               designed full-width closer and belongs there. Hide the sidebar's.

   If Kyle would rather keep both, deleting this block restores them.
   --------------------------------------------------------------------------- */
@media (min-width: 981px) {
  body.single-post .et_pb_section_1_tb_body { display: none; }
}

@media (max-width: 980px) {
  /* The form's own widget, and the widget immediately before it — its heading.
     Matched by what they contain rather than by :nth-child, so reordering the
     sidebar in the widget screen cannot silently hide the wrong two blocks. */
  /* .et_pb_widget, not .widget — Divi's own class. The sidebar module itself
     also carries .et_pb_widget, hence the child combinator. */
  /* .hbspt-form since 16 Oct 2026, when both forms became HubSpot's Contact
     Us (Kyle); .gform_wrapper kept in case the sidebar goes back. */
  body.single-post .post-sidebar > .et_pb_widget:has(.gform_wrapper, .hbspt-form),
  body.single-post .post-sidebar > .et_pb_widget:has(+ .et_pb_widget :is(.gform_wrapper, .hbspt-form)) {
    display: none;
  }
}

/* The registration guides' own form, HubSpot's Service Interest -
   Registrations since 19 Oct 2026 (Kyle). In four of the five it sits in a
   grey Divi row with 50px of padding each side, which on a phone left the
   frame 212px wide: fields 132px, the reCAPTCHA badge cut off, the button on
   two lines. HubSpot pads the inside of its frame, so the row gives up its
   own. Divi writes the row's padding with !important. Only the form's own
   row: a bare :has(.c9-hs-form) also matches the Theme Builder row around
   the whole post. */
@media (max-width: 767px) {
  body.single-post .et_pb_row:has(> .et_pb_column > .et_pb_module > div > .c9-hs-form) {
    padding-left: 0 !important;
    padding-right: 0 !important;
  }
}

/* Illinois carries its form inside the article's text, on white, where it
   read as a stray block indented 40px from the text above. The other four
   guides set it in a grey panel (their own Divi section, #F5F5F5); this gives
   Illinois the same panel. HubSpot's frame is transparent, so the grey shows
   behind the fields there too. */
body.single-post .et_pb_text .c9-hs-form {
  margin-top: 24px;
  padding: 16px 0 40px;
  background: #f5f5f5;
}

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

   Divi ships no search.php, so search falls through to index.php and its
   classic #left-area / #sidebar layout — a template nobody had looked at,
   reachable from the search box on /blog/ and from the 404 page.

   It arrived with no heading, a 1170px container while the rest of the site
   runs 1024, and featured images at 861px wide against 305px everywhere else.
   The .et_pb_post type styles above already applied; only the frame was wrong.
   --------------------------------------------------------------------------- */
/* Desktop only. Zeroing the container padding at every width left mobile flush
   against both edges — Divi's own mobile gutter lives on this element. */
@media (min-width: 981px) {
  body.search #main-content .container {
    max-width: 1024px;
    width: auto;
    padding-left: 0;
    padding-right: 0;
  }
  body.search #left-area { padding-right: 48px; }
}

/* The heading printed by c9_search_results_heading(). */
.c9-search-head {
  margin: 0 0 40px;
  padding-bottom: 26px;
  border-bottom: 1px solid rgba(11, 43, 84, .14);
}
.c9-search-eyebrow,
.c9-search-count {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #826700;
  margin: 0;
}
body.search #main-content .c9-search-head h1 {
  font-size: clamp(30px, 3.4vw, 40px);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -.025em;
  color: #0B2B54;
  margin: 8px 0 10px;
}
.c9-search-count { color: #4A5670; letter-spacing: .06em; text-transform: none; font-size: 13px; }

/* Match the blog listing: image right at 305px, text left. Divi floats it there
   on /blog/ via the Blog module's own CSS, which index.php never gets. */
@media (min-width: 981px) {
  body.search .et_pb_post { overflow: hidden; }   /* contain the float */
  body.search .et_pb_post .entry-featured-image-url {
    float: right;
    width: 305px;
    margin: 0 0 18px 34px;
  }
}
body.search .et_pb_post .entry-featured-image-url img {
  display: block;
  width: 100%;
  height: auto;
}

/* Divi's no-results block, on search only. It emits a second <h1> on a page
   that now already has one, and its copy ("use the navigation above to locate
   the post") is the same line that made the old 404 useless. c9-404-style
   links are printed in its place — see c9_search_heading_markup(). */
body.search .entry:has(> .not-found-title) { display: none; }

.c9-search-empty { margin-top: 4px; }
body.search #main-content .c9-search-empty h2 {
  font-size: 23px;
  font-weight: 800;
  color: #0B2B54;
  margin: 0 0 16px;
}
/* #left-area is needed to beat Divi's `#left-area ul { list-style-type: disc }`
   — an ID selector, which a plain class rule loses to however many classes it
   carries. The first attempt used `.c9-search-empty .c9-404-links` and the
   bullets stayed. */
body.search #left-area .c9-search-empty .c9-404-links {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 12px 32px;
}
body.search #left-area .c9-search-empty .c9-404-links li {
  list-style: none;
  margin: 0;
  padding: 0;
}
body.search #left-area .c9-search-empty .c9-404-links li::before { content: none; }

/* ---------------------------------------------------------------------------
   Wide tables in post content.

   Ten of the 92 posts with a table had one wider than a 390px viewport with
   nothing around it that scrolled — 630px on the 2024 holidays rate table, a
   third of it unreachable. The page did not overflow, so an overflow sweep
   called those pages clean.

   `overflow-x: auto` on a wrapper, not `display: block` on the table, which
   reassigns the rows to anonymous boxes and changes how column widths resolve.
   --------------------------------------------------------------------------- */
.c9-tablewrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
}
.c9-tablewrap > table { margin: 0; }

/* Tall, wide tables are given a floor width and allowed to overflow the wrapper,
   which is what makes the wrapper's overflow-x mean anything. Without it a
   53x7 table compresses to 373px on a phone and grows to 58,184px tall instead
   — the wrapper never scrolled because nothing ever overflowed it.

   --c9-tmin is set per table by c9_scrollable_tables(), at 150px a column, and
   only for tables of 10+ rows and 4+ columns. See the note there for why both
   bounds exist: narrow tables get taller if you force their columns, and short
   wide ones just gain a scrollbar. */
.c9-tablewrap--wide > table { min-width: var(--c9-tmin, 0); }

/* A floor under each column as well as the table. The table minimum alone lets
   the browser starve one column to feed another: on the nexus chart the state
   column got 67px and "Alabama (AL)" broke to "Ala / bam / a / (AL)", four lines
   for two words, and every row in the table is as tall as its tallest cell.

   90px, measured rather than picked. It is not "more is better" — at 110px the
   page grows again and at 130px it is worse than having no floor at all,
   because widening the short columns takes the width back off the description
   column that actually needed it:

       none   page 10,407   row 114px   state column  67px
       90px   page  9,585   row  71px   state column  97px
       110px  page 10,224   row  92px
       130px  page 11,219   row 114px

   Safe only because --wide already means 4+ columns. The same rule applied to
   the 2-column tables makes them taller — see c9_scrollable_tables(). */
.c9-tablewrap--wide th,
.c9-tablewrap--wide td { min-width: 90px; }

/* On a wide screen, let a wide table out of the prose measure.

   `.c9-prose` is capped at 680px because that is a readable line length for
   body copy. A 53x7 data table is not body copy, and on a 1280px screen the
   chart was being clipped at 778px with 500px of empty page beside it — the
   columns sliced mid-word, next to the room to show them.

   clamp() so it can only ever help: never narrower than the prose column, never
   wider than the table actually needs, and never wider than the window. A
   4-column table whose minimum is 600px stays exactly where it was. */
@media (min-width: 1100px) {
  /* max-width has to go with it: the base .c9-tablewrap rule caps at 100% of
     the 680px prose column, which beat the width on its own and left this rule
     doing nothing at all. */
  .c9 .c9-tablewrap--wide {
    width: clamp(680px, var(--c9-tmin, 680px), calc(100vw - 160px));
    max-width: none;
  }
}

/* Data-table typography, not prose typography.

   The 2024 holidays table is 30 rows and was 13,451px tall on desktop, 16,112px
   on mobile, on a 21,191px page. Nothing was setting a height: one column holds
   a long description, it gets ~225px of a four-column 100%-wide table, and at
   the prose 17px/1.72 that wraps to thirteen lines — so every row in the table
   is as tall as the longest cell in it.

   And `vertical-align: middle` is what made it look broken rather than merely
   long: "Alabama" floats in the middle of a 400px cell, hundreds of pixels away
   from the sentence it belongs to. Aligning to the top puts every cell in a row
   on the same first line. */
html body .c9-tablewrap table,
html body .c9-tablewrap td,
html body .c9-tablewrap th,
html body .c9-tablewrap p,
html body .c9-tablewrap li { font-size: 15px; line-height: 1.45; }

html body .c9-tablewrap th,
html body .c9-tablewrap td { vertical-align: top; }

/* Lists inside cells. Divi sets `li` font-size explicitly, so it does not
   inherit from the cell — the first version of this shrank the table text and
   left the lists at 17px/29px, and the rows did not move by a single pixel.
   Its list spacing is built for body copy: 10px/23px on the ul, 8.5/15 on each
   li, and a 26px indent for a custom bullet. Inside a four-column table that is
   most of the row height. */
html body .c9-tablewrap ul,
html body .c9-tablewrap ol { margin: 0; padding: 0 0 0 18px; }
html body .c9-tablewrap li { margin: 0 0 4px; padding-left: 0; }
html body .c9-tablewrap li::before { display: none; }
html body .c9-tablewrap p { margin: 0 0 .5em; }
html body .c9-tablewrap p:last-child,
html body .c9-tablewrap li:last-child { margin-bottom: 0; }

/* A hairline that only appears when there is actually something to scroll to,
   so a table that fits shows no affordance it does not need. */
.c9-tablewrap {
  background:
    linear-gradient(to right, var(--c9-paper, #FBFAF7) 30%, rgba(251,250,247,0)),
    linear-gradient(to right, rgba(251,250,247,0), var(--c9-paper, #FBFAF7) 70%) 100% 0,
    radial-gradient(farthest-side at 0 50%, rgba(11,43,84,.16), rgba(11,43,84,0)),
    radial-gradient(farthest-side at 100% 50%, rgba(11,43,84,.16), rgba(11,43,84,0)) 100% 0;
  background-repeat: no-repeat;
  background-size: 40px 100%, 40px 100%, 14px 100%, 14px 100%;
  background-attachment: local, local, scroll, scroll;
}

/* Divi Table Maker's check marks on the partner comparison table.

   Eleven of them, coloured #FFD902 — one of the retired yellows — by CSS the
   PLUGIN generates from its own shortcode attribute (`col_icon_color`) into a
   per-instance selector, `div.dvmd_table_maker_item_1 .dvmd_tm_icon`. Not an
   inline style, not our stylesheet, and not in any Divi layout: the sitewide
   yellow retirement could not have seen it, and neither could a scan of Theme
   Builder templates.

   The class is doubled for specificity rather than reaching for the instance
   number, which changes per table. `html body .dvmd_tm_icon` alone loses: the
   plugin's selector carries two classes and ours would carry one. */
html body .dvmd_tm_icon.dvmd_tm_icon,
html body .dvmd_tm_cdata .dvmd_tm_icon.dvmd_tm_icon { color: #E3B200; }

/* The crosses are not an accent.

   The table's whole job is "HOST does this, software does not", and both marks
   were drawn in the same gold — so at a glance the two columns read as equally
   positive and the comparison argues against itself. The tick keeps the accent;
   the cross drops to the muted ink the rest of the page uses for secondary
   text. Colour is not carrying the meaning either way: the glyphs differ. */
html body .dvmd_tm_icon.ei-close_alt,
html body .dvmd_tm_cdata .dvmd_tm_icon.ei-close_alt { color: rgba(11, 43, 84, .32); }

/* Divi's post navigation keeps its 2017 blue.

   The "← previous / next →" links under a post and under a case study are a Divi
   module whose GENERATED css is
     .et_pb_posts_nav.et_pb_post_nav_0 span a { color:#4687d1!important }
   — two classes and two elements, with !important, emitted after ours. Measured
   at 3.72:1 on white, under AA, and the last blue link on the site.

   Two things were wrong in the first attempt and both are worth naming: the
   class is `et_pb_postS_nav`, not `et_pb_post_nav`, so half the selector matched
   nothing; and matching !important with !important at EQUAL specificity loses on
   source order. The class is repeated to carry a third class and win outright. */
body.single-post .et_pb_posts_nav.et_pb_posts_nav span a,
body.single-project .et_pb_posts_nav.et_pb_posts_nav span a {
  color: #0B2B54 !important;
  box-shadow: inset 0 -1px 0 0 #E3B200;
  text-decoration: none;
}
body.single-post .et_pb_posts_nav.et_pb_posts_nav span a:hover,
body.single-project .et_pb_posts_nav.et_pb_posts_nav span a:hover {
  color: #826700 !important;
  box-shadow: inset 0 -2px 0 0 #E3B200;
}

/* One table header row, written inline as white on #7a7a7a.

   `saas-sales-tax` sets `background-color:#7a7a7a; color:#ffffff` on the header
   <tr> in the post content — 4.29:1, under AA at 15px. One post out of 672, so
   this is not a pattern to restyle; it is one row to make legible.

   Darkening the grey rather than changing the text keeps the design intent — a
   grey header bar — and takes it to 6.4:1. Scoped to the inline value so it
   cannot touch anything else, and !important because an inline style on the row
   is what it has to beat. */
.c9-tablewrap tr[style*="#7a7a7a"],
.c9-tablewrap tr[style*="rgb(122, 122, 122)"] { background-color: #5C5C5C !important; }

/* The blog, search and archive listings sat on pure white while every C9 page
   body is the warm paper — the one cold template family left (13 Aug QA). */
body.blog #main-content,
body.search #main-content,
body.archive #main-content { background: var(--c9-paper, #FBFAF7); }

/* The blog index itself is NOT body.blog: it is a Divi-built page
   (page-id-1900) whose listing section paints itself white through Divi's
   generated CSS, so the rule above never reached it — the computed background
   read transparent and the white came from .et_pb_section_2. Both the body
   and the sections take the paper; the C9 header/footer layouts carry their
   own backgrounds and are unaffected. */
body.page-id-1900,
body.page-id-1900 .et_pb_section { background-color: var(--c9-paper, #FBFAF7); }

/* On stacked mobile layouts the archive pagination sat ~10px off the
   sidebar's "Request a Consultation" heading and read as part of the form. */
@media (max-width: 980px) {
  body.blog .pagination,
  body.search .pagination,
  body.archive .pagination { margin-bottom: 44px; }
}

/* Divi's blog search module sits outside the .c9 scope, so the sitewide gold
   :focus-visible outline never reached it — its input and SEARCH button were
   the only two keyboard stops on the site with no focus indicator
   (13 Aug interaction QA). */
input.et_pb_s:focus-visible,
input.et_pb_searchsubmit:focus-visible {
  outline: 2px solid #826700;
  outline-offset: 2px;
}
