/*
 * Dogwood Animal Rescue — homepage polish (Phase 1 + Phase 2)
 * Paste alongside the existing hero/pets embeds; load this AFTER
 * dogwood-hero.css on the homepage only (it targets the specific widgets
 * that live below the hero there).
 *
 * Per the homepage refresh plan, Phase 2 was meant to require editing the
 * raw HTML inside several widgets. It turned out not to: About/Support/
 * Donation/video/newsletter/partners all share one wrapper element (see
 * section 2's comment), which CSS Grid + `order` can restructure into the
 * intended 3-up card row without touching any widget's own markup. So
 * this whole file, Phase 1 and 2 both, stayed CSS-only -- no WordPress
 * content edits needed for anything covered here. Everything below
 * targets the LIVE page's real markup/classes/hrefs as inspected
 * 2026-08-30 -- see preview/home/index.html for a reproduction of that
 * markup used to build and screenshot these rules before they ever
 * touched WordPress.
 *
 * Reconciled brand tokens (see README.md's "Brand / design tokens"
 * section) -- self-contained here rather than depending on dogwood-hero.css
 * having loaded first.
 */
@import url("https://fonts.googleapis.com/css2?family=Dancing+Script:wght@600;700&family=EB+Garamond:wght@600;700&display=swap");
/* Dancing Script added 2026-08-30 for .dwh-newsletter-title -- also
   loaded by dogwood-hero.css already, but this file is meant to stand on
   its own (see file header), so it isn't assumed to be there first. */

:root {
  --dwh-teal-dark: #0a5b79;
  --dwh-teal-medium: #0085a8;
  --dwh-teal-tint: #eef6f8; /* very light wash for alternating section backgrounds */
  --dwh-gold: #e8a33d;
  --dwh-gold-text: #4a3108; /* dark enough on gold for 4.5:1 contrast, matches hero's --dw-hero-accent-text approach */
  --dwh-radius-pill: 999px;
  /* moved here from being locally scoped inside .dwh-stats-strip--dark
     2026-08-30, so .dwh-video-card (added same day, see that rule) can
     share the exact same darkest-teal instead of hardcoding its own
     copy of the value. */
  --dwh-teal-deepest: #052e39;
}

/* ---------------------------------------------------------------------
   1. The orphaned "DONATE" button block.
   It's a raw Gutenberg button (not a widget), inline-styled directly on
   the page, so it can't be given a stable class without a content edit.
   Targeted here by its unique href + block structure instead -- there is
   exactly one .wp-block-buttons on the homepage whose link points at
   /donate/, confirmed against the live DOM (the Support Us!/Make A
   Donation buttons are a different plugin's markup, .su-button, not
   wp-block-button). :has() lets this stay a pure CSS fix, no markup edit.
   ------------------------------------------------------------------- */
.entry-content .wp-block-buttons:has(> .wp-block-button > a.wp-block-button__link[href="https://dogwoodanimalrescue.org/donate/"]) {
  margin: 0.5rem 0 2rem;
}

.entry-content .wp-block-buttons:has(> .wp-block-button > a.wp-block-button__link[href="https://dogwoodanimalrescue.org/donate/"])
  > .wp-block-button > a.wp-block-button__link {
  /* !important beats the element's own inline style="background-color:...;
     border-radius:..." attribute -- inline styles otherwise outrank any
     external stylesheet regardless of selector specificity. Same reason
     dogwood-hero.css fights the theme's CSS with !important in a few
     spots; documented there as the deliberate exception, not a habit. */
  background-color: var(--dwh-gold) !important;
  color: var(--dwh-gold-text) !important;
  border: none !important;
  border-radius: var(--dwh-radius-pill) !important;
  padding: 0.9rem 2.75rem !important;
  font-family: "Poppins", "Open Sans", Helvetica, Arial, sans-serif;
  font-weight: 800;
  font-size: 1.05rem;
  letter-spacing: 0.02em;
  box-shadow: 0 6px 16px rgba(10, 91, 121, 0.18);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.entry-content .wp-block-buttons:has(> .wp-block-button > a.wp-block-button__link[href="https://dogwoodanimalrescue.org/donate/"])
  > .wp-block-button > a.wp-block-button__link:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 20px rgba(10, 91, 121, 0.24);
}

/* ---------------------------------------------------------------------
   2. (Phase 2) About Dogwood / Support Us! / Make a Donation as a 3-up
   icon card row, replacing Phase 1's alternating full-bleed tint bands
   (which only made sense back when these read as three stacked, unrelated
   sections -- grouping them as cards is the better fit now).

   All seven widgets below the hero -- About(custom_html-27), the intro
   video(block-5), Support Us(custom_html-37), Make A Donation
   (custom_html-38), the newsletter(bloomwidget-12), and the partners
   heading+slider(block-15, block-11) -- turned out to share ONE
   .organic-block-widget-area wrapper, confirmed against the live DOM on
   /home-hero-test/ 2026-08-30, in that exact DOM order. Rather than
   requiring a WordPress content edit to physically regroup them, this
   uses CSS Grid on that shared wrapper with `order` to visually pull the
   three text widgets into an adjacent 3-column row while the video/
   newsletter/partners widgets each span the full row in their original
   relative order below it -- so this stays a pure CSS change, no editing
   inside any widget's HTML.

   ACCESSIBILITY TRADE-OFF, read before extending this: `order` changes
   visual position only, not DOM/tab order. A screen-reader or keyboard
   user still encounters these in DOM order -- About, then the video
   iframe, then Support Us, then Make A Donation -- not the visual
   About/Support/Donation-then-video order sighted users see. The
   practical impact is small here (one link per card, then the video's own
   self-contained iframe), but it is a real mismatch. If that's ever worth
   fixing properly, the real fix is dragging the video block to after
   "Make a Donation" in the WordPress editor (a native block reorder, ~10
   seconds, no code) so DOM order matches visual order and this whole
   order:/grid-column: setup on non-card widgets becomes unnecessary. */
.entry-content > .organic-block-widget-area {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
  align-items: stretch;
  padding: 2.5rem 0;
}

#custom_html-27,
#custom_html-37,
#custom_html-38 {
  /* light blue, not white -- on this page the surrounding background is
     also white/near-white, so a white card had no visible edge against
     it (only the box-shadow hinted at a boundary). Requested 2026-08-30. */
  background: #bcd6e6;
  border: 1px solid var(--dwh-teal-tint);
  border-radius: 14px;
  box-shadow: 0 4px 14px rgba(10, 91, 121, 0.08);
  padding: 2rem 1.5rem 1.75rem;
  text-align: center;
}

#custom_html-27 { order: 1; }
#custom_html-37 { order: 2; }
#custom_html-38 { order: 3; }

/* the widgets' own inline style="width:80%" assumed a full-width stacked
   section; inside a 1/3-width card that shrinks the text column further
   than intended, so it's overridden back to the full card width here. */
#custom_html-27 .textwidget > div,
#custom_html-37 .textwidget > div,
#custom_html-38 .textwidget > div {
  width: 100% !important;
}

/* Icons: CSS background-image data-URIs on a ::before, not <img> tags --
   keeps this a pure CSS change with no new markup. rgb() colors (not hex)
   so the SVG needs no #-escaping in the data URI. */
#custom_html-27 h2::before,
#custom_html-37 h2::before,
#custom_html-38 h2::before {
  content: "";
  display: block;
  width: 44px;
  height: 44px;
  margin: 0 auto 0.75rem;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
}

#custom_html-27 h2::before {
  /* house/rescue icon, brand teal */
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='rgb(10,91,121)'%3E%3Cpath%20d='M12%203%202%2012h3v8h6v-5h2v5h6v-8h3z'/%3E%3C/svg%3E");
}

#custom_html-37 h2::before {
  /* heart/community icon, brand teal */
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='rgb(10,91,121)'%3E%3Cpath%20d='M12%2021s-7.5-4.6-10-9.3C.6%208.4%202.4%205%206%205c2%200%203.4%201.1%204%202.4C10.6%206.1%2012%205%2014%205c3.6%200%205.4%203.4%204%206.7C19.5%2016.4%2012%2021%2012%2021z'/%3E%3C/svg%3E");
}

#custom_html-38 h2::before {
  /* gift icon, gold -- the one card that's the direct-donation CTA */
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='rgb(232,163,61)'%3E%3Crect%20x='3'%20y='9'%20width='18'%20height='11'%20rx='1'/%3E%3Crect%20x='3'%20y='6'%20width='18'%20height='4'%20rx='1'/%3E%3Crect%20x='11'%20y='2'%20width='2'%20height='18'/%3E%3C/svg%3E");
}

/* the four non-card widgets in the same shared wrapper: span the full
   row and keep their original relative order (video, then newsletter,
   then partners heading, then partners slider) below the card row --
   pushed to order 5-8 to leave order:4 for the stats strip (section 7
   below), which sits between the card row and the video. */
#block-5 { grid-column: 1 / -1; order: 5; }
#bloomwidget-12 { grid-column: 1 / -1; order: 6; }
#block-15 { grid-column: 1 / -1; order: 7; }
#block-11 { grid-column: 1 / -1; order: 8; }

/* ---------------------------------------------------------------------
   3. Button normalization: the Shortcodes Ultimate su-buttons ("About
   Dogwood", "Support Us!", "Please Make A Donation") already use a teal
   very close to the hero's brand teal (#0a5879 vs. --dwh-teal-dark
   #0a5b79 -- coincidence worth treating as confirmation, not something to
   change the color of). What's inconsistent is shape: 5px corners vs. the
   hero/DONATE pill language. Bringing just the shape in line, not the
   color, keeps these reading as secondary actions next to DONATE's gold.

   display/text-decoration added 2026-08-30: originally these came for
   free from the Shortcodes Ultimate plugin's own stylesheet, which only
   loads when it detects actual [su_button] shortcode text in the page.
   embed-home-full.html pastes the shortcode's RENDERED output instead
   (the widget's original content, not the shortcode itself), so that
   stylesheet never loads and the buttons fell back to bare underlined
   inline links, missing exactly these two properties. Setting them here
   directly means this no longer depends on that plugin's CSS at all. */
.entry-content .su-button.su-button-style-default {
  display: inline-block !important;
  text-decoration: none !important;
  border-radius: var(--dwh-radius-pill) !important;
  padding: 0.15rem 0.4rem !important;
  transition: transform 0.15s ease;
  /* Requested 2026-09-01: "Please Make A Donation" was wrapping to two
     lines on mobile. Shortened the label itself (see embed-home-full.html
     -- now just "Make A Donation") AND added this as a hard guarantee
     regardless of label length or viewport width, rather than relying on
     wrapping happening to not trigger at whatever width was tested. */
  white-space: nowrap;
}

/* Same fix as .dwh-donate-cta above and for the same reason: these
   buttons' white text comes from an inline style="color:#FFFFFF" with no
   !important, so the theme's likely a:visited !important rule (see the
   .dwh-donate-cta comment) would silently turn them grey too once
   clicked, even though DONATE was the only one actually reported. */
.entry-content .su-button.su-button-style-default:visited,
.entry-content .su-button.su-button-style-default:hover,
.entry-content .su-button.su-button-style-default:visited:hover {
  color: #fff !important;
}

.entry-content .su-button.su-button-style-default:hover {
  transform: translateY(-1px);
}

.entry-content .su-button.su-button-style-default span {
  border-radius: var(--dwh-radius-pill) !important;
  padding: 2px 20px !important;
}

/* ---------------------------------------------------------------------
   4. Community-partners heading font. Originally paired with a Smart
   Slider sizing rule (#n2-ss-24-align img) too -- that rule is REMOVED as
   of 2026-09-01, superseded by section 11's hand-built grid, which
   replaced the [smartslider3 slider="24"] shortcode entirely (see that
   section's comment). This heading rule survives unchanged since the
   generated grid markup (scripts/partners/build_partners_html.py) still
   emits the same h2.wp-block-heading structure for the title.
   ------------------------------------------------------------------- */
/* "Dogwood Animal Rescue Community Partners" heading -- EB Garamond,
   requested 2026-08-30 alongside every other heading on the page except
   "The Dogwood Dish". No dedicated class on this one (it's a raw
   Gutenberg heading block pasted directly on the page, see
   embed-home-full.html), so scoped via .entry-content + its own
   wp-block-heading class instead -- specific enough to not risk matching
   some other heading elsewhere, not tied to a class this project doesn't
   control the meaning of. */
.entry-content h2.wp-block-heading {
  font-family: "EB Garamond", Georgia, serif !important;
  /* 600, matching .dwh-stats-title's 2026-09-01 change -- see that rule's
     comment. */
  font-weight: 600 !important;
}

/* ---------------------------------------------------------------------
   5. (Phase 2) Frame the intro video instead of it sitting bare edge-to-
   edge. Targets the video plugin's own stable wrapper (.arve, from
   "Advanced Responsive Video Embedder") rather than the widget div, so
   it's not fighting that plugin's own aspect-ratio/sizing logic -- just
   adding a card frame around it.
   ------------------------------------------------------------------- */
#block-5 .arve {
  max-width: 800px;
  margin: 0 auto;
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 8px 24px rgba(10, 91, 121, 0.16);
}

/* ---------------------------------------------------------------------
   6. (Phase 2) "The Dogwood Dish" newsletter signup as a contained
   gradient highlight band, mirroring the hero's gradient. Styled on the
   OUTER widget wrapper only -- the Bloom plugin bakes its own !important
   rules onto the form's inner elements (.et_bloom_form_content etc, see
   dogwood-home.css's design notes / README), so this deliberately doesn't
   fight those. The result is a gradient band with Bloom's own white form
   card floating inside it, not a re-theme of Bloom's internals.
   ------------------------------------------------------------------- */
#bloomwidget-12 {
  background: linear-gradient(135deg, var(--dwh-teal-dark), var(--dwh-teal-medium));
  border-radius: 14px;
  padding: 2.5rem 1.5rem;
}

#bloomwidget-12 .widget-title {
  color: #fff;
  text-align: center;
}

/* ---------------------------------------------------------------------
   7. (Phase 3) Impact stats strip. Unlike everything above, this is real
   new content (numbers, not decoration), so it can't be a CSS-generated
   pseudo-element the way the card icons were -- it needs an actual new
   Custom HTML widget pasted in. Moved 2026-08-30 from "between the DONATE
   button and the card row" to "between the card row and the video" -- it
   now lives INSIDE the same shared .organic-block-widget-area grid as the
   cards/video/newsletter/partners (see section 2), as a full-width grid
   item at order:4 (between the cards at order 1-3 and the video pushed to
   order:5). Exactly where the new widget physically lands in that shared
   area doesn't matter -- grid-column/order below place it visually
   regardless of DOM position, same trick as the rest of section 2. See
   embed-home-stats.html for the exact markup and source numbers.

   IMPORTANT: grid-column/order only have an effect on a DIRECT child of
   the grid container. .dwh-stats-strip itself is nested one level deeper
   (widget wrapper > .textwidget > .dwh-stats-strip), same as every other
   widget's content here -- for the card/video/etc. widgets that's fine
   because their wrapper has a known, stable ID (#custom_html-27 etc.) to
   target directly. This new widget's WordPress-assigned wrapper ID isn't
   known ahead of time, so :has() finds it generically instead, via the
   .widget class every one of these wrappers shares. This also means it
   doesn't matter where in the shared widget area the new widget actually
   gets added -- this rule finds it wherever it lands. */
.organic-block-widget-area > .widget:has(.dwh-stats-strip) {
  grid-column: 1 / -1;
  order: 4;
}

.dwh-stats-strip {
  /* No longer display:grid directly -- .dwh-stats-title and
     .dwh-stats-source (moved INSIDE this card 2026-08-30, see that rule's
     comment) need to stack above/below the 3-number grid, so the grid
     itself moved to .dwh-stats-grid, one level in. Padding bumped up
     2026-08-30 (was 2rem 1rem) -- the source link at the old, tighter
     padding read as cramped against the card edge. */
  padding: 3rem 2rem;
  text-align: center;
}

.dwh-stats-title {
  /* Was Poppins, deliberately different from the numbers below it (see
     git history) for hierarchy-through-typeface -- switched to EB
     Garamond 2026-08-30 as part of trying it across every heading on the
     page except "The Dogwood Dish" (which keeps its own Dancing Script).
     Bottom margin trimmed 2026-08-30 (was 1.75rem) now that
     .dwh-stats-rule carries its own margin below it -- see that rule.

     font-size !important added 2026-08-30 -- same root cause identified
     for .dwh-newsletter-title (see its comment): the theme's
     `.entry-content h2 { font-size: 1.285714286rem }` outranks a bare
     one-class selector like this on specificity alone, no !important
     needed on the theme's side for it to still win. Applies here too
     since both "Making a Difference" and "See Our Story" are h2s. */
  font-family: "EB Garamond", Georgia, serif !important;
  /* 600, not 700 -- requested 2026-09-01 to match the Upcoming Events
     widget's heading, which reads as noticeably "cleaner" than a 700
     weight. Confirmed live via document.fonts that EB Garamond is only
     loaded at 600/700 (see the @import at the top of this file) -- there
     is no real 400 face, so 600 is the genuinely lightest weight
     available for this typeface, not just a stylistic middle ground. */
  font-weight: 600;
  font-size: 1.5rem !important;
  margin: 0 0 1rem;
  color: var(--dwh-teal-dark);
}

.dwh-stats-rule {
  /* Requested 2026-08-30, a plain <hr> rather than a border-bottom on the
     title so it reads as a deliberate divider between the title and the
     numbers, not an underline on the title itself. Teal-light, matching
     .dwh-stat-number, so it visually ties to the numbers it's separating
     from the title above -- works against both the light and dark card
     variants without needing its own override. */
  width: 56px;
  height: 3px;
  margin: 0 auto 1.75rem;
  border: none;
  border-radius: 2px;
  background: #2a9cc1;
}

.dwh-stats-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
}

.dwh-stat-number {
  /* EB Garamond, not Cormorant Garamond -- tried on request 2026-08-30 for
     comparison. Distinct typeface: a more classic book-Garamond revival,
     lower-contrast strokes and more even proportions than Cormorant's
     tall, high-contrast display styling used on the hero headline. Needs
     its own @import above since dogwood-hero.css only loads Cormorant/
     Poppins/Dancing Script, not this. */
  font-family: "EB Garamond", Georgia, serif;
  font-size: clamp(2.2rem, 5vw, 3rem);
  font-weight: 700;
  color: var(--dwh-teal-dark);
  line-height: 1.1;
}

.dwh-stat-label {
  font-size: 0.95rem;
  color: #444;
  margin-top: 0.35rem;
}

.dwh-stats-source {
  /* Moved INSIDE .dwh-stats-strip 2026-08-30 (was a sibling <span> below
     the card). As a sibling it sat on the plain page background, but its
     dark-variant color (translucent white) assumed a dark background --
     nearly invisible against white, which is what "isn't readable"
     actually was. Nesting it in the card means its color is always
     correct for whatever background it's actually on, and its spacing is
     controlled by normal flow instead of a negative-margin hack (which
     was also the mobile overlap-with-a-label complaint -- that margin was
     tuned for the old sibling layout, not this one). */
  display: block;
  margin: 1.75rem 0 0;
  font-size: 0.8rem;
  color: #777;
}

.dwh-stats-source a {
  color: var(--dwh-teal-dark);
}

/* Dark-card variant, chosen after comparison against the default
   plain-on-page look above -- add "dwh-stats-strip--dark" alongside
   "dwh-stats-strip" on the wrapping div in embed-home-stats.html to use
   this instead. --dwh-teal-deepest (now on :root, see top of file)
   matches dogwood-hero.css's own --dw-teal-deepest, so this reads as the
   same brand darkest-teal, not a new color invented just for this card. */
.dwh-stats-strip--dark {
  background: var(--dwh-teal-deepest);
  border-radius: 14px;
  box-shadow: 0 8px 24px rgba(5, 46, 57, 0.35);
}

.dwh-stats-strip--dark .dwh-stats-title {
  color: #fff;
}

.dwh-stats-strip--dark .dwh-stat-number {
  /* teal-light, not gold -- gold's already doing CTA duty on the hero and
     DONATE buttons; a third use here would dilute it as "the one accent
     color". This reuses the hero's own lighter teal stop instead, so the
     highlight still reads as a deliberate brand color, not just "brightest
     text available". Requested 2026-08-30. */
  color: #2a9cc1;
}

.dwh-stats-strip--dark .dwh-stat-label {
  color: rgba(255, 255, 255, 0.85);
}

.dwh-stats-strip--dark .dwh-stats-source {
  color: rgba(255, 255, 255, 0.7);
}

.dwh-stats-strip--dark .dwh-stats-source a {
  color: #fff;
}

/* ---------------------------------------------------------------------
   7b. Stats + video as one 40/60 row, requested 2026-08-30. Was: stats
   card, then cards row, then video, each full-width and stacked. Now:
   cards row, then this row (stats 40% / video 60%), then newsletter/
   partners -- the cards row keeps its position right after DONATE, stats
   and video are what moved to sit together. The 3 stat numbers stack to a
   single column even at desktop here (repeat(3,1fr) was too cramped at
   ~40% of the content width) -- .dwh-video-frame's own max-width/margin
   are reset since the row's grid track sizing replaces them.
   ------------------------------------------------------------------- */
.dwh-stats-video-row {
  display: grid;
  grid-template-columns: 2fr 3fr;
  gap: 1.5rem;
  /* stretch, not start (was start) -- requested 2026-08-30: at full
     content width the two cards happened to land close in height, but
     compressing the window (stats card's text reflows to more lines
     faster than the video shrinks) pulled them apart oddly. Stretch makes
     both grid items always fill the row's height, whatever that is at
     any given width, instead of each sizing purely to its own content. */
  align-items: stretch;
  margin: 2.5rem 0;
}

.dwh-stats-video-row .dwh-stats-strip {
  margin: 0;
}

.dwh-stats-video-row .dwh-stats-grid {
  grid-template-columns: 1fr;
  gap: 1.25rem;
}

/* ---------------------------------------------------------------------
   7c. Video card, requested 2026-08-30: the bare 16:9 video sitting next
   to the taller stats card left an empty gap below it in its column --
   read as "something's missing" rather than a deliberately paired row.
   Framing it in a card matching the stats card's own dark treatment
   (title + rule + content, same as the stats side) gives it real content
   parity instead of just padding it out to match height artificially.
   ------------------------------------------------------------------- */
.dwh-video-card {
  background: var(--dwh-teal-deepest);
  border-radius: 14px;
  box-shadow: 0 8px 24px rgba(5, 46, 57, 0.35);
  padding: 2rem;
  text-align: center;
}

/* .dwh-stats-title/.dwh-stats-rule are reused here on purpose rather than
   duplicated under video-specific names -- same title+rule pattern, same
   visual treatment, no reason to fork it. The title defaults to
   --dwh-teal-dark (see .dwh-stats-title), fine against the light plain
   card but low-contrast on this card's own dark background -- overridden
   to white here the same way .dwh-stats-strip--dark does for its title. */
.dwh-video-card .dwh-stats-title {
  color: #fff;
}

.dwh-video-caption {
  font-size: 0.95rem;
  color: rgba(255, 255, 255, 0.85);
  margin: 0;
}

/* Both cards made flex columns, SCOPED to being inside the row (not on
   .dwh-stats-strip/.dwh-video-card generally, which are also used
   standalone elsewhere where flex isn't needed) -- this is what lets
   align-items:stretch above actually produce equal-height cards: with
   display:grid's default block-level children, "stretch" only stretches
   the outer box, it doesn't make the video frame grow to fill that extra
   height. flex-direction:column + flex:1 on the frame does. */
.dwh-stats-video-row .dwh-stats-strip,
.dwh-stats-video-row .dwh-video-card {
  display: flex;
  flex-direction: column;
}

.dwh-stats-video-row .dwh-video-frame {
  flex: 1;
  /* aspect-ratio dropped (see base .dwh-video-frame rule) so the iframe's
     box can actually grow/shrink to match the stats card's height instead
     of being locked to 16:9 regardless of available space. YouTube's
     player letterboxes its own content inside whatever box it's given, so
     the video itself doesn't visibly distort -- only the surrounding
     iframe box's proportions change. */
  aspect-ratio: unset;
  margin: 0 0 1.25rem;
  max-width: none;
}

@media (max-width: 700px) {
  /* width/max-width/box-sizing added 2026-09-01 -- a beta tester found a
     real, reproducible bug: load in portrait (fine) -> rotate to
     landscape (fine, this row correctly switches to the desktop 2-column
     grid at that width) -> rotate back to portrait -> the row now
     overflows horizontally instead of re-stacking to 1 column. This is a
     known WebKit quirk category: .dwh-video-frame's width below was left
     IMPLICIT (inherited from the flex item's default stretch-to-parent
     behavior) rather than stated as an explicit value. In the desktop/
     landscape pass, .dwh-video-frame is flex:1 with aspect-ratio:unset
     (see that rule) and gets a real pixel width from the grid's 3fr
     track; iOS Safari can retain that resolved width as the frame's
     "used size" across the next layout pass instead of correctly
     re-deriving it from the now-1-column grid, and since aspect-ratio:
     16/9 is what applies at this breakpoint, a stale wide width forces a
     correspondingly wide computed height too -- the whole box (and this
     row along with it, since nothing above was clamping it either)
     renders wider than the viewport. Explicit width:100% on both the row
     and the frame gives Safari an unambiguous value to resolve on every
     layout pass instead of one it might carry over from a different
     grid-column-count state. */
  .dwh-stats-video-row {
    grid-template-columns: 1fr;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
  }
  .dwh-stats-grid {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }
  .dwh-stats-strip {
    padding: 2rem 1.5rem;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
  }
  .dwh-video-card {
    padding: 1.75rem 1.25rem;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
  }
  /* Fixes a real bug introduced by the equal-height change above:
     .dwh-video-frame's flex:1 + aspect-ratio:unset only produces a
     height when something external (the desktop row's align-items:
     stretch, sized off the stats card) gives the flex container real
     space to grow into. Stacked to one column here, there's no such
     external height and no aspect-ratio fallback either, so the frame
     collapsed to ~0 height -- the video wasn't broken, it was rendering
     at zero size. Restoring a fixed aspect-ratio here (stretch-matching
     doesn't apply to a stacked, non-side-by-side layout anyway) gives it
     a real height again independent of flex-grow. */
  .dwh-stats-video-row .dwh-video-frame {
    flex: none;
    aspect-ratio: 16 / 9;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
  }
}

@media (max-width: 700px) {
  .entry-content .wp-block-buttons:has(> .wp-block-button > a.wp-block-button__link[href="https://dogwoodanimalrescue.org/donate/"])
    > .wp-block-button > a.wp-block-button__link {
    padding: 0.75rem 2rem !important;
    font-size: 0.95rem;
  }
  .entry-content > .organic-block-widget-area {
    grid-template-columns: 1fr;
    padding: 1.75rem 0;
    gap: 1.25rem;
  }
  #custom_html-27,
  #custom_html-37,
  #custom_html-38 {
    padding: 1.75rem 1.25rem 1.5rem;
  }
  #n2-ss-24-align img {
    max-height: 60px;
  }
  #bloomwidget-12 {
    padding: 2rem 1.25rem;
  }
}

/* =======================================================================
   8. (Breakout, added 2026-08-30) Equivalent styling for the About/
   Support/Donation cards and the intro video AS STANDALONE PAGE BLOCKS,
   for pasting via embed-home-cards.html / embed-home-video.html --
   requested because editing widgets in that shared "Organic Widget Area
   Block" widget area was too painful, so cards/video/partners are moving
   to be plain Custom HTML blocks directly on the page instead.

   ADDITIVE ON PURPOSE: the #custom_html-27/-37/-38 and #block-5 rules
   above (sections 2 and 5) are left in place, not removed, so the
   CURRENTLY LIVE widget-based cards/video keep working and looking
   correct right up until the swap is actually made and confirmed. Once
   that's done, sections 2's card/icon rules, #block-5's rule, and the
   #custom_html-27/-38 mobile-padding rule above all become dead code --
   ask Claude to clean those up in one pass rather than deleting them
   piecemeal mid-migration.

   POSITIONING NOTE: once cards/video/partners (and the stats strip, if
   also moved) are plain sequential Custom HTML blocks, none of them need
   the grid/order/:has() machinery sections 2 and 7 use to fake a position
   inside the shared widget area -- normal block order in the editor IS
   the visual order now. Just drag these new blocks into the sequence you
   want (cards, then stats, then video, then partners, matching what's
   live now, or any other order).
   ======================================================================= */
.dwh-cards-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
  margin: 2.5rem 0;
}

.dwh-card {
  background: #bcd6e6;
  border: 1px solid var(--dwh-teal-tint);
  border-radius: 14px;
  box-shadow: 0 4px 14px rgba(10, 91, 121, 0.08);
  padding: 2rem 1.5rem 1.75rem;
  text-align: center;
  /* flex column, requested 2026-09-01 so the three su-buttons line up at
     the same height across all three cards regardless of how much
     paragraph text each card has. .dwh-cards-row's grid already stretches
     all three cards to equal height (default align-items:stretch on a
     grid row) -- this just needed the button pushed to the bottom of that
     already-equal height, which .dwh-card p's flex:1 below does. Markup
     changed to match: the button is now its own element after </p>, not
     inline content inside the same <p> separated by <br><br> -- a flex
     item has to be a direct child to be individually positioned, and
     inline content inside a paragraph can't be pinned to the bottom on
     its own. See embed-home-full.html's cards for the updated markup. */
  display: flex;
  flex-direction: column;
}

.dwh-card p {
  flex: 1 0 auto;
  margin: 0 0 1.25rem;
}

.dwh-card .su-button {
  /* Without this the button, now a flex item like h2/p, would stretch to
     the card's full width (align-items' default is stretch) instead of
     staying a natural-width pill. */
  align-self: center;
}

/* EB Garamond, requested 2026-08-30 -- trying it across every heading on
   the page except "The Dogwood Dish" (Dancing Script, kept as-is). These
   three ("About Dogwood"/"SUPPORT US!"/"MAKE A DONATION") had no explicit
   font-family before, just inheriting the theme's body font. !important
   given every other h2 on this page has needed it to beat the theme's
   `.entry-content h2` rule on one property or another so far. */
.dwh-card h2 {
  font-family: "EB Garamond", Georgia, serif !important;
  /* 600, matching .dwh-stats-title's 2026-09-01 change -- see that rule's
     comment. Previously unset here, which meant the browser's own default
     bold (700) for <h2> was winning, same "too heavy" issue. */
  font-weight: 600 !important;
}

.dwh-card h2::before {
  content: "";
  display: block;
  width: 44px;
  height: 44px;
  margin: 0 auto 0.75rem;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
}

.dwh-card--about h2::before {
  /* house/rescue icon, brand teal -- same icon as #custom_html-27 above */
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='rgb(10,91,121)'%3E%3Cpath%20d='M12%203%202%2012h3v8h6v-5h2v5h6v-8h3z'/%3E%3C/svg%3E");
}

.dwh-card--support h2::before {
  /* heart icon, red -- changed 2026-08-30 from brand teal to match the
     heart emoji (❤️) in the hero's tagline. rgb(224,34,41) approximates
     the red heart emoji's actual rendered color (Apple Color Emoji, the
     platform this project is built/reviewed on) -- not a brand token,
     specifically chosen to visually match that one emoji.

     Path replaced 2026-08-30 -- the hand-drawn path used until now (the
     one also still sitting in the dead #custom_html-37 rule above, for
     reference/comparison) was subtly asymmetric: traced by hand rather
     than from a real icon source, it read as crooked/flattened on the
     right side on close inspection, not just a viewBox-clipping issue
     (the earlier "-1 -1 26 26" widened viewBox masked the symptom rather
     than fixing the actual cause). Replaced with Font Awesome's solid
     heart glyph (viewBox 0 0 512 512) instead of attempting another
     hand-drawn path -- a real, published, properly mirrored icon design
     rather than another guess at one. */
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20512%20512'%20fill='rgb(224,34,41)'%3E%3Cpath%20d='M462.3%2062.6C407.5%2015.9%20326%2024.3%20275.7%2076.2L256%2096.5%20236.3%2076.2C186%2024.3%20104.5%2015.9%2049.7%2062.6c-62.8%2053.6-66.1%20149.8-9.9%20207.9l193.5%20199.8c12.5%2012.9%2032.8%2012.9%2045.3%200l193.5-199.8c56.3-58.1%2053-154.3-9.8-207.9z'/%3E%3C/svg%3E");
}

.dwh-card--donate h2::before {
  /* gift icon, gold -- same icon as #custom_html-38 above, still the one
     card that's the direct-donation CTA */
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='rgb(232,163,61)'%3E%3Crect%20x='3'%20y='9'%20width='18'%20height='11'%20rx='1'/%3E%3Crect%20x='3'%20y='6'%20width='18'%20height='4'%20rx='1'/%3E%3Crect%20x='11'%20y='2'%20width='2'%20height='18'/%3E%3C/svg%3E");
}

.dwh-video-frame {
  position: relative;
  max-width: 800px;
  margin: 2.5rem auto;
  aspect-ratio: 16 / 9;
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 8px 24px rgba(10, 91, 121, 0.16);
}

.dwh-video-frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

@media (max-width: 700px) {
  .dwh-cards-row {
    grid-template-columns: 1fr;
    gap: 1.25rem;
    margin: 1.75rem 0;
  }
  .dwh-card {
    padding: 1.75rem 1.25rem 1.5rem;
  }
}

/* ---------------------------------------------------------------------
   9. (Breakout) Standalone DONATE button, own class instead of the
   :has()-on-a-Gutenberg-block selector in section 1 -- that selector
   depended on the button being the native wp-block-button block section
   1 was written against. Once the whole page is hand-authored HTML (see
   embed-home-full.html), a plain class is simpler and more robust than
   re-deriving a :has() hook for whatever block markup happens to wrap it.
   Same gold-pill visual result as section 1's rule.
   ------------------------------------------------------------------- */
.dwh-donate-cta {
  /* display:block + width:50% (was inline-block, sized to just fit
     "DONATE") added 2026-08-30 -- the original button this replaced was
     a core Gutenberg wp-block-button__width-50 block, 50% of the
     available content width regardless of how short the label was. The
     breakout version lost that -- it's been sized to its own padding/text
     since it stopped being that block. Restored the original proportions
     here instead of just the color/shape. */
  display: block;
  width: 50%;
  margin: 0 auto;
  box-sizing: border-box;
  background-color: var(--dwh-gold);
  color: var(--dwh-gold-text) !important;
  border: none;
  border-radius: var(--dwh-radius-pill);
  padding: 0.9rem 2.75rem;
  font-family: "Poppins", "Open Sans", Helvetica, Arial, sans-serif;
  font-weight: 800;
  font-size: 1.05rem;
  letter-spacing: 0.02em;
  text-decoration: none;
  text-align: center;
  box-shadow: 0 6px 16px rgba(10, 91, 121, 0.18);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

/* :visited called out explicitly (and !important added above too),
   requested 2026-08-30: after clicking through once, the button read as
   light grey on gold -- unreadable. The theme almost certainly carries
   its own a:visited rule (a common pattern for distinguishing visited
   links in body text) with higher specificity than a plain .dwh-donate-
   cta class, which for a *button* rather than a text link is exactly the
   wrong behavior. Every interactive state gets the same explicit gold-
   text color so none of them can independently regress like this again. */
.dwh-donate-cta:visited,
.dwh-donate-cta:hover,
.dwh-donate-cta:visited:hover,
.dwh-donate-cta:active,
.dwh-donate-cta:focus {
  color: var(--dwh-gold-text) !important;
}

.dwh-donate-cta:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 20px rgba(10, 91, 121, 0.24);
}

.dwh-donate-wrap {
  text-align: center;
  margin: 0.5rem 0 2rem;
}

@media (max-width: 700px) {
  .dwh-donate-cta {
    padding: 0.75rem 2rem;
    font-size: 0.95rem;
  }
}

/* ---------------------------------------------------------------------
   10. (Breakout) Newsletter gradient card, own class instead of
   #bloomwidget-12 -- same visual treatment as section 6 (gradient band,
   Bloom's own form floating inside, not restyled internally), just keyed
   to a class this project controls instead of Bloom's auto-generated
   widget ID, since embed-home-full.html places the [bloom_inline]
   shortcode directly rather than through the widget system.
   ------------------------------------------------------------------- */
.dwh-newsletter-wrap {
  background: linear-gradient(135deg, var(--dwh-teal-dark), var(--dwh-teal-medium));
  border-radius: 14px;
  /* top padding trimmed 2026-08-30 (was 2.5rem all around) -- part of
     shrinking the visible teal space above the white form box, alongside
     .dwh-newsletter-title's more negative margin-bottom below. */
  padding: 1.5rem 1.5rem 2.5rem;
  margin: 2.5rem 0;
}

/* Bloom's own internal padding, requested 2026-08-30: measured live (not
   guessed) at .et_bloom_form_header (15px top / 25px bottom) and
   .et_bloom_form_content (40px top AND bottom -- around a form that's
   only ~41px tall itself), injected via Bloom's own per-instance <style>
   block. !important since that block almost certainly uses it too (every
   other Bloom-internal value captured from it so far has).

   UPDATE, same day: the "leave Bloom's internals alone, only style the
   outer wrapper" rule from the design note above was explicitly reversed
   on request right after this -- off-white background, rounded corners,
   and a pill-shaped input/button to match the rest of the page's shape
   language. Still scoped to .dwh-newsletter-wrap so this can't leak onto
   any other Bloom form elsewhere on the site. */
.dwh-newsletter-wrap .et_bloom_form_header {
  padding-top: 10px !important;
  padding-bottom: 8px !important;
}

.dwh-newsletter-wrap .et_bloom_form_content {
  padding-top: 14px !important;
  padding-bottom: 14px !important;
  border-radius: 14px !important;
}

.dwh-newsletter-wrap .et_bloom_form_container {
  border-radius: 14px !important;
  overflow: hidden;
}

/* background-color/border-radius on these three needed an extra
   specificity boost beyond a normal two-class selector, confirmed live:
   Bloom's own per-instance <style> block sets background-color via
   `.et_bloom .et_bloom_optin_2 .et_bloom_form_content` -- three classes,
   !important -- which out-specifies a plain `.dwh-newsletter-wrap
   .et_bloom_form_content` (two classes) despite !important on both
   sides; same story for the input/button radius (Bloom's own 3px, also
   !important). Repeating .dwh-newsletter-wrap is the fix -- each
   repetition is a real class-selector for specificity purposes, so
   tripling it safely outranks Bloom's rule regardless of which stylesheet
   loads first in source order, without needing an id in the markup. Also
   note the email input has no type="" attribute at all in Bloom's markup
   (confirmed live), so an [type="text"] selector silently matches
   nothing -- targeted by plain "input" instead, scoped narrowly enough
   by .et_bloom_form_content that it can't hit anything else. */
.dwh-newsletter-wrap.dwh-newsletter-wrap.dwh-newsletter-wrap .et_bloom_form_content {
  /* form_header added 2026-08-30, same off-white as form_content so the
     header/content split doesn't read as two different surfaces -- was
     still plain white (Bloom's own default), untouched by the first
     background-color fix since that only targeted form_content. */
  background-color: #f3f8fa !important;
}

/* .et_bloom_form_header carries extra classes of its own (at least
   "split" and "et_bloom_header_text_dark", confirmed live) that Bloom's
   own per-instance stylesheet apparently keys its background-color rule
   off of too -- tripling .dwh-newsletter-wrap (4 total classes) tied
   Bloom's selector instead of beating it, and the tie went the wrong way.
   Six repetitions rather than chasing Bloom's exact class count again. */
.dwh-newsletter-wrap.dwh-newsletter-wrap.dwh-newsletter-wrap.dwh-newsletter-wrap.dwh-newsletter-wrap.dwh-newsletter-wrap .et_bloom_form_header {
  background-color: #f3f8fa !important;
}

.dwh-newsletter-wrap.dwh-newsletter-wrap.dwh-newsletter-wrap .et_bloom_form_content input {
  border-radius: var(--dwh-radius-pill) !important;
}

.dwh-newsletter-wrap.dwh-newsletter-wrap.dwh-newsletter-wrap .et_bloom_submit_subscription {
  border-radius: var(--dwh-radius-pill) !important;
  /* dark teal, requested 2026-08-30 -- was Bloom's own default mid-blue
     (#358db1), now matches the DONATE/su-button pill color used
     everywhere else. White text (Bloom's own default here) already
     passes contrast against this teal, so left alone. */
  background-color: var(--dwh-teal-dark) !important;
  /* transition/hover added 2026-08-30 -- every other pill button on the
     page (DONATE, the su-buttons) has a subtle hover lift; this one
     didn't, since it was never given one when the color/shape were fixed
     earlier. -1px, not DONATE's -2px, to match the su-buttons' secondary-
     action weight rather than a primary CTA's. */
  transition: transform 0.15s ease;
}

.dwh-newsletter-wrap.dwh-newsletter-wrap.dwh-newsletter-wrap .et_bloom_submit_subscription:hover {
  transform: translateY(-1px);
}

/* Added 2026-08-30: confirmed on /home-hero-test/ that the [bloom_inline]
   shortcode's own rendered output has no headline of its own (only a
   hidden post-submit success message) -- "The Dogwood Dish" title isn't
   duplicated by adding this, it just doesn't exist without it. */
.dwh-newsletter-title {
  /* Dancing Script, requested 2026-08-30 -- same script face the hero
     reserves for pet-name-style flourishes, not used anywhere else in
     the page body. First pass sized this at 2.4rem, called out as
     "unacceptably small" -- script faces have a much smaller x-height
     relative to their em-box than a regular sans/serif, so they read as
     noticeably smaller than a sans heading at the same declared size;
     2.4rem wasn't accounting for that gap. Bumped substantially, and to a
     clamp() so it scales down gracefully on narrow screens instead of
     wrapping awkwardly. */
  font-family: "Dancing Script", cursive;
  font-weight: 700;
  /* !important added 2026-08-30 -- found the actual culprit: the theme
     carries `.entry-content h2, .comment-content h2, .mu_register h2 {
     font-size: 1.285714286rem; line-height: 1.6; }`. That selector is
     class+element (.entry-content h2), specificity (0,1,1); a bare
     .dwh-newsletter-title is (0,1,0) -- one class alone loses to one
     class + one element, so the theme's ~20.6px won regardless of the
     clamp() here despite neither side using !important before. Simply
     out-specificity-ing that selector (e.g. ".entry-content
     .dwh-newsletter-title") would also work, but !important matches how
     every other theme-fight in this file is already handled and doesn't
     depend on this exact theme selector never changing. */
  font-size: clamp(2.6rem, 7vw, 4rem) !important;
  line-height: 1.2 !important;
  color: #fff;
  text-align: center;
  /* Slight counterclockwise tilt + tightened (negative) margin, requested
     2026-08-30 to try for a more organic, hand-written feel and to close
     up the empty band the script font left above/below itself -- Dancing
     Script carries a lot of built-in ascender/descender space in its own
     em-box even at line-height:1.2, more than the visible ink needs, so
     tightening margin (not just line-height) is what actually closes it.
     margin-bottom pushed negative same day, on request -- title visibly
     overlapping into the white form box (the form's white background
     paints over the overlapping part, since it comes after in DOM order)
     is the intended effect, not just tighter spacing.

     !important added after the first negative value visibly did nothing
     live: computed margin-bottom was still a flat 24px, the theme's own
     default h2 margin, same specificity problem as font-size/line-height
     above (a bare .dwh-newsletter-title loses to whatever more specific
     theme selector sets that default) -- this wasn't a real "Bloom's
     container has extra padding" issue, the negative margin plain wasn't
     applying at all. Confirm the actual overlap amount live, not just in
     the local static preview -- the preview's plain placeholder div for
     Bloom's form doesn't share the real theme's default h2 margin, so it
     can look right there even when a fix like this silently isn't
     applying live at all. */
  margin: -0.75rem 0 -1.75rem !important;
  transform: rotate(-4deg);
  /* Dark-teal drop shadow, requested 2026-08-30 to sell the layered look
     now that the title visibly overlaps/tucks under the white form box --
     a hard offset (no blur), not a soft glow, so it reads as a solid
     shape sitting behind the white text/paper, like a cut-out label,
     rather than a diffuse glow around it. --dwh-teal-deepest (the card's
     own darkest background stop) rather than --dwh-teal-dark, so the
     shadow reads as "more of the same dark backdrop" instead of a third,
     unrelated teal shade. */
  text-shadow: 3px 3px 0 var(--dwh-teal-deepest);
}

@media (max-width: 700px) {
  .dwh-newsletter-wrap {
    padding: 1.25rem 1.25rem 2rem;
  }
  /* Previously eased back to a small positive margin here to avoid
     overlapping the form box at mobile's smaller clamp() font-size --
     overlap turned out to be the actual desired effect (see the
     margin-bottom comment above), so this now leans into it at mobile
     too instead of avoiding it, just scaled down from desktop's -1.75rem
     to roughly match the smaller glyph size at this breakpoint.
     !important needed here too -- same theme-default-h2-margin issue as
     the base rule above, confirmed live not just assumed. */
  .dwh-newsletter-title {
    margin: -0.25rem 0 -1rem !important;
  }
}

/* ---------------------------------------------------------------------
   11. (Breakout) Community Partners grid, replacing the Nextend Smart
   Slider carousel (section 4's #n2-ss-24-align rule, now dead code --
   [smartslider3 slider="24"] no longer appears in embed-home-full.html).
   Option C from the 2026-08-30 discussion: the slider's per-slide sizing
   was inconsistent between logos (each slide configured its own crop/size
   in Smart Slider's own admin) and the carousel itself read as visually
   disconnected from the card/pill language used everywhere else on the
   page. This is a plain CSS grid of uniform square tiles instead --
   `object-fit: contain` inside a fixed aspect-ratio box means every
   logo, whatever its native size, sits centered and consistently scaled
   with no per-image tuning ever needed again.

   TILES ARE RENDERED CLIENT-SIDE, not hand-authored or server-generated:
   see wordpress-embed/dogwood-partners.js, which fetches
   partners.json (built from scripts/partners/partners.json by
   scripts/partners/sync_partners_data.py) and appends
   .dwh-partner-tile elements into embed-home-full.html's empty
   #dwh-partners-grid container at runtime. (Earlier version of this
   comment, before 2026-09-01, described a build step that generated
   static HTML to paste into WordPress -- that step is gone; adding,
   removing, or reordering a partner now only touches partners.json +
   a script rerun + an SFTP upload, no WordPress content edit at all.)
   This CSS only needs to change if the *tile design* changes, not when
   the partner set does -- same as before, just one layer further removed
   from the markup now.
   ------------------------------------------------------------------- */
.dwh-partners-wrap {
  margin: 2.5rem 0;
}

.dwh-partners-grid {
  display: grid;
  /* Fixed column count, NOT auto-fill/minmax -- requested 2026-09-01: with
     8 partners, auto-fill packed as many logos per row as the container
     width allowed, which produced an uneven final row (a lonely 1-2 tile
     row dangling under a fuller one) rather than an even grid. A fixed
     column count guarantees even rows for any partner count that divides
     evenly into it. Trade-off, noted for future maintainers: this is no
     longer count-agnostic the way auto-fill was -- if the partner count in
     partners.json changes to something that doesn't divide evenly by 8
     (this rule) or 2 (the mobile rule below), a row will be uneven again;
     revisit the column count then rather than assuming it still fits.

     Was repeat(4, 1fr) (4x2, ~227px tiles at this page's fixed 960px
     content width) -- reviewer feedback 2026-09-07 called that too big
     and asked for all 8 logos on one row at desktop width. repeat(8, 1fr)
     does that; gap and .dwh-partner-tile's padding/border-radius below are
     scaled down to match the ~110px tiles that leaves (960px content
     width, 7 gaps at the new 0.75rem = 84px, so (960-84)/8 ≈ 110px) --
     unscaled padding looked chunky/disproportionate on a tile this much
     smaller. Confirmed live on /home-hero-test/ at both 1440 and 1920px
     viewports -- this page's content column is a fixed 960px regardless
     of viewport width above the mobile breakpoint, so there's no
     additional wide-desktop case to handle beyond this. Mobile (below)
     is unchanged -- this feedback was specifically about desktop/PC. */
  grid-template-columns: repeat(8, 1fr);
  gap: 0.75rem;
  margin-top: 1.5rem;
}

.dwh-partner-tile {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1;
  background: #fff;
  border: 1px solid var(--dwh-teal-tint);
  border-radius: 8px;
  box-shadow: 0 4px 14px rgba(10, 91, 121, 0.08);
  padding: 0.6rem;
  box-sizing: border-box;
  /* subtle hover lift, same -1px/transition weight as the su-buttons and
     the newsletter's SUBSCRIBE pill -- keeps the micro-interaction
     consistent sitewide rather than inventing a new one here. Applies
     whether a given tile renders as a <div> (no known partner URL yet) or
     an <a> (partner site linked) -- see the script's render_tile(). */
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  text-decoration: none;
}

a.dwh-partner-tile:hover {
  transform: translateY(-1px);
  box-shadow: 0 8px 20px rgba(10, 91, 121, 0.14);
}

.dwh-partner-tile img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}

@media (max-width: 700px) {
  .dwh-partners-wrap {
    margin: 1.75rem 0;
  }
  .dwh-partners-grid {
    /* Fixed columns at this breakpoint too, same reasoning as the desktop
       rule above -- an even, request-specific row shape rather than
       however many tiles happen to fit the viewport width.

       Was repeat(2, 1fr) (2x4: 8 partners as pairs). Changed 2026-09-07
       to repeat(4, 1fr) (4x2) -- requested to match the desktop row shape
       more closely (one row of 8 there, two rows of 4 here) instead of
       four narrow rows of 2. gap and .dwh-partner-tile's padding/border-
       radius below are scaled down to match the smaller tiles this
       produces -- confirmed live on /home-hero-test/ at both 768px
       (tablet, ~705px content width -> ~155px tiles) and 375px (phone,
       ~327px content width -> ~76px tiles); the SAME values are used
       across this whole breakpoint (not narrowed further at phone width)
       since 1fr columns already scale fluidly with the container, same
       approach as the single desktop rule above. */
    grid-template-columns: repeat(4, 1fr);
    gap: 0.5rem;
    margin-top: 1.25rem;
  }
  .dwh-partner-tile {
    padding: 0.4rem;
    border-radius: 6px;
  }
}

/* ---------------------------------------------------------------------
   12. Upcoming Events widget (The Events Calendar's own Legacy Widget,
   idBase "tribe-widget-events-list", rendered via a native WordPress
   Group block). Gives it the same card treatment as the rest of the
   page -- teal date badges, EB Garamond heading, gold pill "View
   Calendar" link -- purely CSS, no markup/content changes.

   Requested 2026-09-01 alongside a reposition (from after Community
   Partners to before it), which was explored and ABANDONED the same day:
   this widget queries The Events Calendar plugin's own database on every
   page load, so it can't be flattened into a Custom HTML block's static
   markup the way the partner logos were -- it has to stay a real,
   separate WordPress block, and every way to fit that between two
   Custom HTML sections (splitting the page into three blocks, or
   building a second static-generation pipeline off the plugin's REST
   API) added more complexity than the reorder was worth. So the widget
   is still wherever it currently sits in the page's block list (after
   Community Partners, unchanged) -- only this styling is live, not a
   position change.

   Selectors below are Tribe Common's own markup, captured live off
   /home-hero-test/ 2026-08-31 -- not this project's classes, so a future
   Events Calendar plugin update could rename them. Re-inspect the live
   DOM first if this section ever stops matching.
   ------------------------------------------------------------------- */
.entry-content > .wp-block-group:has(.tribe-events-widget-events-list) {
  margin: 2.5rem 0;
}

.tribe-events-widget-events-list {
  /* Background photo added 2026-09-01 (Aunties-party.png -- four dogs in
     birthday hats). It's a busy, colorful photo behind five rows of
     event text, a date badge per row, and a button -- shown at full
     strength it would wreck readability, so it's tinted with a
     linear-gradient of the card's own #f3f8fa (the fill color settled on
     the same day, see the earlier version of this comment) at 82%
     opacity layered on top. That keeps the photo clearly visible (colors/
     shapes read through) while keeping contrast safe for the dark event-
     title text and the various badge colors on top of it. If it ever
     needs to feel more/less present, this opacity is the one number to
     change -- confirmed live 2026-09-01 that 82% keeps every row legible
     including over the photo's darker patches (the porch window, the
     dogs' fur). background-color is the plain #f3f8fa fallback for
     before the image loads or if it fails to. */
  background-color: #f3f8fa;
  background-image:
    linear-gradient(rgba(243, 248, 250, 0.82), rgba(243, 248, 250, 0.82)),
    url("https://dogwoodanimalrescue.org/wp-content/uploads/2026/09/Aunties-party.png");
  background-size: cover;
  background-position: center top;
  background-repeat: no-repeat;
  border-radius: 14px;
  box-shadow: 0 4px 14px rgba(10, 91, 121, 0.08);
  box-sizing: border-box;
}

/* border/padding split into their own rule with the class repeated 3x --
   confirmed live 2026-09-01 that a single-class !important selector
   STILL lost to Tribe Common's own reset (Tribe Common's CSS resets a lot
   of default element/widget spacing to 0 with !important of its own, and
   apparently at higher specificity here too -- likely something like
   `.tribe-common .tribe-events-widget-events-list`, two classes, beating
   a plain one-class selector even with matching !important). Repeating
   the class is the same fix already used for Bloom's newsletter form
   (see the .dwh-newsletter-wrap.dwh-newsletter-wrap... rules) rather than
   chasing Tribe's exact selector -- each repetition is a real class for
   specificity purposes, so 3x safely outranks a 2-class competitor
   regardless of load order. Without this the card had the right
   background/radius/shadow but zero breathing room and no edge, which on
   this page's off-white body background read as no card at all -- the
   request was specifically that this widget needs to look visually
   distinct from Community Partners (which has no outer card of its own,
   only individual tiles), so this border+padding is what actually
   delivers that, not the background/shadow alone. */
.tribe-events-widget-events-list.tribe-events-widget-events-list.tribe-events-widget-events-list {
  /* #bcd6e6 (the .dwh-card background elsewhere on the page) used as a
     single-line border here instead of a fill, requested 2026-09-01 after
     the solid #bcd6e6 background read as too heavy -- #f3f8fa fill above
     plus this border gives a lighter card with enough edge contrast
     against the page's white background, while still visually tying back
     to the same card family via the border color instead of the fill.
     Widened from 1px to 2px same day -- the 1px line read as too faint
     given how close #f3f8fa and #bcd6e6 are in lightness. */
  border: 2px solid #bcd6e6 !important;
  padding: 2rem 1.75rem 1.5rem !important;
}

/* EB Garamond + centered + a decorative rule underneath, matching the
   stats/video cards' treatment (.dwh-stats-title / .dwh-stats-rule) --
   recreated here as a ::after pseudo-element instead of a real <hr>,
   since this heading comes from the plugin's own template, not markup
   this project controls. !important on font-size/margin for the same
   reason every other h2 on this page needs it: the theme's own
   `.entry-content h2 { font-size: 1.285714286rem; line-height: 1.6; }`
   otherwise wins on plain specificity. */
.tribe-events-widget-events-list__header-title {
  font-family: "EB Garamond", Georgia, serif !important;
  color: var(--dwh-teal-dark);
  text-align: center;
  font-size: 1.7rem !important;
  margin: 0 0 1.75rem !important;
  /* Deliberately NOT setting font-weight -- 2026-09-01: this heading reads
     as noticeably "cleaner" than the rest of the page's bold (700)
     headings because it's left at Tribe's own "tribe-common-h6" utility
     weight (400) instead of being forced to match. First instinct was to
     bold this to match everything else; turned out the actual preference
     was the reverse -- keep this one alone and lighten the others to
     match it instead. See section 2's .dwh-card h2, .dwh-stats-title, and
     .entry-content h2.wp-block-heading for that change. */
}

.tribe-events-widget-events-list__header-title::after {
  content: "";
  display: block;
  width: 56px;
  height: 3px;
  margin: 0.6rem auto 0;
  background: var(--dwh-teal-medium);
}

.tribe-events-widget-events-list__event-row {
  align-items: center;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--dwh-teal-tint);
}

.tribe-events-widget-events-list__event-row:last-of-type {
  border-bottom: none;
}

/* Month/day badge -- width left as fit-content rather than a fixed px
   value on purpose: the surrounding column width is Tribe's own grid
   (.tribe-common-g-col), not this project's, so pinning an exact width
   here risks fighting whatever that column actually measures out to. */
.tribe-events-widget-events-list__event-date-tag-datetime {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: fit-content;
  margin: 0 auto;
  background: var(--dwh-teal-dark);
  border-radius: 10px;
  line-height: 1.15;
  /* !important on padding -- confirmed live 2026-09-01 that Tribe Common
     sets its own padding on this exact element via a more specific
     selector (extra .tribe-common ancestor class), which otherwise wins
     over a plain one-class selector regardless of load order. Everything
     else in this rule (display/background/border-radius) had no
     competing Tribe rule and applied fine without needing this. */
  padding: 0.4rem 0.65rem !important;
}

/* color set directly on each text child rather than relying on
   inheriting it from the badge above -- confirmed live 2026-09-01 that
   Tribe's own tribe-common-h2/h-alt utility classes (also present on
   these elements, see the live-DOM comment above this section) set an
   explicit color of their own, and an explicit rule always wins over an
   inherited value no matter the specificity math. Without this, the
   month abbreviation rendered as Tribe's default dark grey on this dark
   teal badge -- effectively invisible. */
.tribe-events-widget-events-list__event-date-tag-month {
  font-family: "Poppins", "Open Sans", Helvetica, Arial, sans-serif;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #fff !important;
}

.tribe-events-widget-events-list__event-date-tag-daynum {
  font-family: "Poppins", "Open Sans", Helvetica, Arial, sans-serif !important;
  font-size: 1.3rem !important;
  font-weight: 800;
  line-height: 1.1;
  color: #fff !important;
}

.tribe-events-widget-events-list__event-title {
  font-family: "EB Garamond", Georgia, serif !important;
  margin: 0 0 0.15rem !important;
}

.tribe-events-widget-events-list__event-datetime-wrapper {
  color: #5a6b70;
}

/* :visited called out explicitly, same reason as the DONATE button and
   su-buttons (section 9's comment): the theme's own a:visited rule reads
   as low-contrast grey, which for a repeated list of links is worse than
   a one-off button -- every event title would dim the moment it's been
   clicked once. */
.tribe-events-widget-events-list__event-title-link,
.tribe-events-widget-events-list__event-title-link:visited {
  color: #17323d !important;
  text-decoration: none;
}

.tribe-events-widget-events-list__event-title-link:hover {
  color: var(--dwh-teal-dark) !important;
  text-decoration: underline;
}

.tribe-events-widget-events-list__view-more {
  text-align: center;
  margin-top: 1.5rem;
}

/* Class repeated 3x on background/padding -- confirmed live 2026-09-01
   that Tribe Common's own CSS was resetting both to transparent/0
   (same higher-specificity-reset pattern already hit twice elsewhere in
   this section, see the card/badge comments above), even though this
   rule had matched fine for color/border-radius/box-shadow. Without this
   the button was rendering as bare gold text with a shadow and no fill at
   all -- not a pill, just text -- which is exactly why it read as
   inconsistent with DONATE/the su-buttons/SUBSCRIBE. */
.tribe-events-widget-events-list__view-more-link,
.tribe-events-widget-events-list__view-more-link:visited {
  display: inline-block;
  color: var(--dwh-gold-text) !important;
  border-radius: var(--dwh-radius-pill);
  font-family: "Poppins", "Open Sans", Helvetica, Arial, sans-serif;
  font-weight: 700;
  font-size: 0.9rem;
  letter-spacing: 0.02em;
  text-decoration: none !important;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  box-shadow: 0 4px 12px rgba(10, 91, 121, 0.14);
}

.tribe-events-widget-events-list__view-more-link.tribe-events-widget-events-list__view-more-link.tribe-events-widget-events-list__view-more-link {
  background: var(--dwh-gold) !important;
  padding: 0.6rem 1.75rem !important;
}

.tribe-events-widget-events-list__view-more-link:hover {
  transform: translateY(-1px);
  box-shadow: 0 8px 18px rgba(10, 91, 121, 0.2);
}

@media (max-width: 700px) {
  .entry-content > .wp-block-group:has(.tribe-events-widget-events-list) {
    margin: 1.75rem 0;
  }
  .tribe-events-widget-events-list.tribe-events-widget-events-list.tribe-events-widget-events-list {
    padding: 1.5rem 1.25rem 1.25rem !important;
  }
}
