/* pet sections, breed and species pages, galleries
   Part of the split style.css. inc/enqueue.php enqueues each file as
   its own <link>, in filename order -- they are NOT concatenated, so a
   comment or a rule cut across the join does not heal at the seam. It
   breaks both files, and the browser drops everything it cannot parse
   without saying so. Keep every construct whole inside one file.
   Source order is still the cascade, so moving a rule between files
   can change which one wins. */

.pet-product-section { padding-top: clamp(2.25rem, 4vw, 4rem); }
.pet-legacy-catalog { padding-top: clamp(2.5rem, 5vw, 4.5rem); }
.pet-event-agenda { padding-top: clamp(2.5rem, 5vw, 4.5rem); }
.pet-event-faq-section { padding-block: clamp(2.5rem, 5vw, 4.5rem) 1rem; }
/* .pet-pdp-section and the info grid's own padding-top left this list on
   2026-08-29 for the reason spelled out further down: the section wrapper no
   longer exists and the info grid now sits inside a disclosure panel that
   carries the space. */
.pet-pdp-panels { margin-top: clamp(2rem, 4vw, 3.5rem); }
.pet-pdp-related { padding-top: clamp(2.5rem, 5vw, 4.5rem); }

/* Current storefront refinements: denser PDPs, clearer catalogue states, and softer empty/error pages. */
.pet-shop-specialties {
  margin: clamp(2rem, 4vw, 3.5rem) auto 0;
  max-width: 1180px;
}
.pet-specialty-intro {
  color: var(--pet-muted);
  line-height: 1.6;
  margin: 0 0 1.2rem;
  max-width: 640px;
}
.pet-shop-specialties-heading {
  display: grid;
  gap: .6rem;
  margin-bottom: 1.2rem;
}
.pet-shop-specialties-heading h2 {
  font-size: clamp(1.55rem, 2.8vw, 2.4rem);
  letter-spacing: -.04em;
  margin: 0;
}
/* Must never wrap onto a second line (explicit, repeated site-wide
   requirement -- same treatment as .pet-category-description). nowrap plus
   a horizontal-scroll fallback keeps the full sentence reachable on narrow
   phones instead of an ellipsis silently hiding part of it; max-width was
   dropped from the parent heading block above since it forced the wrap
   this is fixing. */
.pet-shop-specialties-heading p {
  color: var(--pet-muted);
  line-height: 1.6;
  margin: 0 0 .3rem;
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
  white-space: nowrap;
}
.pet-shop-specialties-heading p::-webkit-scrollbar { display: none; }
.pet-specialty-grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
/* Same visual pattern as .pet-info-cta on the /pets/ index cards -- makes
   the card's click target ("Learn more" for a dedicated species page,
   "Check availability" for a contact-form inquiry) explicit instead of
   relying on the whole card being silently clickable. */
/* width: fit-content so the hover underline below tracks the text rather than
   running the full width of the card. It used to sit on the anchor-only rule,
   which disappeared when this slot stopped being a link. */
.pet-specialty-card-cta { color: var(--pet-primary); display: block; font-size: .85rem; font-weight: 800; margin-top: .8rem; width: fit-content; }
.pet-specialty-card-cta b { display: inline-block; margin-inline-start: .3rem; }
[dir="rtl"] .pet-specialty-card-cta b { transform: rotate(180deg); }
/* A decorative <span> on both pages now: the whole card is the click target,
   and the only anchor is the .pet-specialty-card-link overlay above it.
   /shop/aquariums/ used to render this slot as the link itself, because only
   some of the 14 aquascaping groups have a catalogue subcategory to point at
   (see $specialty_catalog_subcategories in update-shop-category-pages.php) and
   a whole-card overlay looked as though it would make the destination-less
   cards indistinguishable. It does not: a card without a destination gets no
   overlay, so it neither lifts on hover nor responds to a click, which reads
   as inert exactly as before.

   The hover colour is therefore driven off the card rather than off this
   element -- the overlay sits above it and takes the pointer, so its own
   :hover would never fire. */
.pet-specialty-grid-links article:has(.pet-specialty-card-link:hover) .pet-specialty-card-cta,
.pet-specialty-grid-links article:has(.pet-specialty-card-link:focus-visible) .pet-specialty-card-cta {
  color: var(--pet-primary-hover);
  text-decoration: underline;
  text-underline-offset: .18em;
}
/* Replaces the old static .pet-eyebrow label in this exact slot on every
   section hero -- same size/weight/case so the hero doesn't shift, but now a
   real Home -> ... -> {page} trail instead of a dead-end tag. The markup comes
   from pet_town_render_breadcrumbs() in inc/seo.php, which also feeds the
   BreadcrumbList JSON-LD, so this styles exactly what search engines are told. */
.pet-breadcrumbs { align-items: center; color: var(--pet-text-secondary); display: flex; flex-wrap: wrap; font-size: .75rem; font-weight: 800; gap: .4em; letter-spacing: .1em; margin: 0 0 1.25rem; text-transform: uppercase; }
.pet-breadcrumbs a { color: inherit; text-decoration: none; }
.pet-breadcrumbs a:hover { text-decoration: underline; }
.pet-breadcrumbs [aria-current] { color: var(--pet-text); }
/* Flexbox already lays the crumbs out right-to-left in Hebrew, but "→" is a
   bidi-neutral character: it kept pointing right, i.e. back the way the
   visitor came, against the direction the trail actually reads. Mirrored the
   same way as the .pet-specialty-card-cta arrow above; inline-block because a
   transform does nothing to an inline box. */
[dir="rtl"] .pet-breadcrumbs [aria-hidden="true"] { display: inline-block; transform: rotate(180deg); }
.pet-specialty-grid article {
  background: var(--pet-surface);
  border: 1px solid var(--pet-border);
  border-radius: 22px;
  box-shadow: 0 16px 34px color-mix(in srgb, var(--pet-shadow-color) 6%, transparent);
  box-sizing: border-box;
  display: block;
  padding: 1.35rem;
  position: relative;
  scroll-margin-top: 2rem;
}
/* Clickable variant (dog breed cards): a plain grid can't center a partial
   last row, so this lays cards out with flexbox instead -- 3 per row, and
   a shorter final row (Doberman + custom order) centers automatically. */
.pet-specialty-grid-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}
.pet-specialty-grid-links article {
  flex: 0 1 calc((100% - 2rem) / 3);
}
/* The link covers the whole card invisibly; <h3>/<p> stay as plain content
   next to it because WordPress's wpautop() mangles a <p> nested directly
   inside an <a> on render (confirmed against the stored post_content). */
.pet-specialty-card-link {
  border-radius: inherit;
  inset: 0;
  position: absolute;
  transition: border-color .2s ease, box-shadow .2s ease, transform .2s ease;
  /* Explicit stacking, not implied. The overlay is absolutely positioned and
     last in the DOM, which in theory already paints it over the card's
     in-flow content -- but wpautop wraps it in a <p> of its own on render,
     and the owner reported taps on the photo doing nothing on iOS. z-index
     states the intent instead of relying on paint order surviving whatever
     WordPress wraps around it. */
  z-index: 1;
}
/* Belt and braces for the same report: the photo is decorative inside a card
   whose whole surface is one link, so it never needs to receive a pointer
   itself. With this, a tap over the image hits the overlay however the
   stacking resolved. Text stays selectable; only the picture opts out. */
.pet-specialty-card-photos {
  pointer-events: none;
}
.pet-specialty-grid-links article:has(.pet-specialty-card-link:hover),
.pet-specialty-grid-links article:has(.pet-specialty-card-link:focus-visible) {
  border-color: var(--pet-primary);
  box-shadow: 0 18px 38px color-mix(in srgb, var(--pet-shadow-color) 12%, transparent);
  transform: translateY(-2px);
}
.pet-specialty-grid h3 {
  font-size: 1.05rem;
  margin: 0 0 .55rem;
}
.pet-specialty-card-icon {
  align-items: center;
  background: var(--pet-primary-soft);
  border-radius: 50%;
  color: var(--pet-primary);
  display: flex;
  height: 44px;
  justify-content: center;
  margin: 0 0 .75rem;
  width: 44px;
}
.pet-specialty-card-icon svg {
  fill: currentColor;
  height: 24px;
  width: 24px;
}
.pet-specialty-card-photos {
  display: grid;
  gap: .4rem;
  grid-template-columns: repeat(3, 1fr);
  margin: 0 0 .75rem;
}
.pet-specialty-card-photos:has(figure:only-child) {
  grid-template-columns: 1fr;
  max-width: 200px;
}
.pet-specialty-card-photos figure {
  margin: 0;
}
.pet-specialty-card-photos img {
  aspect-ratio: 4 / 3;
  background: var(--pet-surface-muted);
  border-radius: 10px;
  display: block;
  object-fit: contain;
  width: 100%;
}
.pet-specialty-card-photos-square img {
  aspect-ratio: 1 / 1;
  background: var(--pet-surface);
}
.pet-specialty-card-photos figcaption {
  color: var(--pet-muted);
  font-size: .72rem;
  margin-top: .25rem;
  text-align: center;
}
.pet-specialty-credits {
  /* Was a one-off grey measuring 2.71 on the page background -- under even
     the 3:1 floor, let alone the 4.5 a .78rem credit line owes. */
  color: var(--pet-text-secondary);
  font-size: .78rem;
  line-height: 1.6;
  margin: 1.2rem 0 0;
}
.pet-specialty-credits a {
  color: inherit;
  text-decoration: underline;
}
.pet-breed-detail-page .pet-specialty-credits { margin: 1.2rem auto 2.5rem; max-width: 1180px; padding: 0 24px; }
.pet-breed-gallery-section { margin: 0 auto; max-width: 1180px; padding: clamp(1.5rem, 3vw, 2.5rem) 24px 0; }
.pet-breed-gallery-section h2 { font-size: clamp(1.35rem, 2.4vw, 1.9rem); letter-spacing: -.03em; margin: 0 0 1rem; }
.pet-breed-gallery { display: grid; gap: 1rem; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.pet-breed-gallery figure { margin: 0; }
.pet-breed-gallery img { aspect-ratio: 4 / 3; background: var(--pet-surface-muted); border-radius: 16px; display: block; object-fit: contain; width: 100%; }
.pet-breed-gallery figcaption { color: var(--pet-muted); font-size: .85rem; margin-top: .4rem; text-align: center; }
.pet-breed-gallery-note { color: var(--pet-muted); font-size: .85rem; margin: .75rem 0 0; }
/* Reuses .pet-breed-gallery's own look (see above), including object-fit:
   contain rather than cover -- these are real kennel photos at mixed
   portrait/landscape/full-body-vs-portrait framing, and cropping to fill a
   square (cover) was cutting dogs' bodies off. contain letterboxes each
   photo on the same background instead, so the whole dog stays visible. */
.pet-pet-gallery { margin: clamp(2rem, 4vw, 3.5rem) auto 0; max-width: 1180px; }
.pet-pet-gallery h2 { font-size: clamp(1.55rem, 2.8vw, 2.4rem); letter-spacing: -.04em; margin: 0 0 1rem; }
.pet-pet-gallery-grid { display: grid; gap: 1rem; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.pet-pet-gallery-grid figure { margin: 0; }
.pet-pet-gallery-grid img { aspect-ratio: 1 / 1; background: var(--pet-surface-muted); border-radius: 16px; display: block; object-fit: contain; width: 100%; }
.pet-pet-gallery-placeholder { background: var(--pet-surface-muted); border-radius: 16px; color: var(--pet-text-secondary); font-size: .95rem; padding: 2rem; text-align: center; }
.pet-specialty-grid p {
  color: var(--pet-muted);
  font-size: .92rem;
  line-height: 1.6;
  margin: 0;
}
.pet-product-badge {
  align-self: flex-start;
  background: var(--pet-accent-soft);
  border-radius: 999px;
  color: var(--pet-accent-text);
  font-size: .72rem;
  font-weight: 900;
  letter-spacing: .02em;
  margin: .9rem 0 -.55rem .9rem;
  padding: .45rem .7rem;
  position: relative;
  z-index: 1;
}
[dir="rtl"] .pet-product-badge {
  margin-left: 0;
  margin-right: .9rem;
}
.pet-product-badge-confirm {
  background: var(--pet-success-soft);
  color: var(--pet-success);
}
.pet-product-badge-request {
  background: var(--pet-accent-soft);
  color: var(--pet-accent-text);
}
/* Must never wrap onto a second line (explicit, repeated requirement).
   Genuinely long descriptions can't always fit narrow phones at a legible
   font-size, so this is nowrap + a horizontal-scroll safety net -- same
   pattern as the header nav above -- rather than an ellipsis that would
   silently hide part of the sentence. */
.pet-category-description {
  color: var(--pet-muted);
  line-height: 1.6;
  margin: 0;
  max-width: 760px;
  overflow-x: auto;
  scrollbar-width: none;
  white-space: nowrap;
}
.pet-category-description::-webkit-scrollbar { display: none; }
.pet-legacy-product-card {
  position: relative;
  transition: border-color .2s, box-shadow .2s, transform .2s;
}
.pet-legacy-product-card:hover {
  border-color: var(--pet-border-strong);
  box-shadow: 0 18px 38px color-mix(in srgb, var(--pet-shadow-color) 10%, transparent);
  transform: translateY(-3px);
}
.pet-product-card-link {
  align-items: center;
  border-top: 1px solid var(--pet-border);
  color: var(--pet-primary);
  display: flex;
  font-weight: 900;
  gap: .5rem;
  justify-content: center;
  margin-top: auto;
  padding-top: .9rem;
  text-decoration: underline;
}
/* "Stretched link": makes the whole card clickable (image, title, price
   included) without restructuring the markup to wrap all of that in the
   <a> itself -- content saved via wp_update_post() gets run through
   wpautop(), which has a proven history on this project of mangling a
   loose <a> wrapping multiple block-level siblings (see the dog-breed-card
   and nav-dropdown comments elsewhere in this file). A pseudo-element
   positioned over the nearest positioned ancestor (.pet-legacy-product-card,
   already position: relative) sidesteps that entirely -- the link's own
   markup and position in the DOM never change. */
.pet-product-card-link::after {
  content: "";
  inset: 0;
  position: absolute;
}
.pet-pdp {
  padding-block: clamp(1rem, 2vw, 2rem) 76px;
}
.pet-pdp-breadcrumbs {
  margin-bottom: 1rem;
}
.pet-pdp-hero {
  gap: clamp(1.25rem, 3.5vw, 3.5rem);
}
.pet-pdp-image-wrap {
  min-height: 390px;
}
.pet-pdp-purchase h1 {
  margin-bottom: .55rem;
}
.pet-pdp-status {
  margin-top: .85rem;
}
.pet-pdp-price {
  margin: .3rem 0;
}
.pet-pdp-note {
  margin-bottom: .85rem;
}
.pet-pdp-actions {
  margin-top: .85rem;
}
.pet-pdp-panels {
  margin-top: clamp(1.75rem, 3.5vw, 3rem);
}
/* .pet-pdp-section and .pet-pdp-info-grid used to be listed here too. The
   first no longer exists -- the 2026-08-29 product page replaced the two-column
   section with a disclosure panel -- and the second now sits inside one of
   those panels, which carries the space itself. Leaving either name here would
   have been a rule that reads as live and paints nothing. */
.pet-pdp-related {
  padding-top: clamp(1.75rem, 3.5vw, 3rem);
}
.pet-not-found {
  color: var(--pet-text);
  margin: 0 auto;
  max-width: 960px;
  padding: clamp(3rem, 8vw, 7rem) 24px 100px;
  text-align: center;
}
.pet-not-found-card {
  background: linear-gradient(135deg, var(--pet-primary-soft), var(--pet-surface-muted));
  border: 1px solid var(--pet-border);
  border-radius: 32px;
  padding: clamp(2rem, 6vw, 5rem);
}
.pet-not-found strong {
  color: var(--pet-accent-text);
  display: block;
  font-size: .8rem;
  letter-spacing: .14em;
  margin-bottom: .8rem;
  text-transform: uppercase;
}
.pet-not-found h1 {
  font-size: clamp(2.4rem, 7vw, 5rem);
  letter-spacing: -.055em;
  line-height: .98;
  margin: 0 0 1rem;
}
.pet-not-found p {
  /* The card behind this is a --pet-primary-soft to --pet-surface-muted
     gradient, and --pet-muted measures 4.24 and 4.36 on those two. */
  color: var(--pet-text-secondary);
  font-size: clamp(1rem, 2vw, 1.2rem);
  line-height: 1.65;
  margin: 0 auto 1.4rem;
  max-width: 620px;
}
.pet-not-found-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  justify-content: center;
}

.pet-commerce-page .woocommerce,
.pet-commerce-page .woocommerce form,
.pet-commerce-page .woocommerce-MyAccount-content,
.pet-commerce-page .woocommerce-MyAccount-navigation {
  box-sizing: border-box;
}
.pet-commerce-page .woocommerce {
  color: var(--pet-text);
}
.pet-commerce-page .woocommerce a {
  color: var(--pet-primary);
  font-weight: 800;
  text-underline-offset: 3px;
}
.pet-commerce-page .woocommerce-notices-wrapper,
.pet-commerce-page .wc-block-components-notice-banner {
  margin-bottom: 1rem;
}
.pet-commerce-page .woocommerce-info,
.pet-commerce-page .woocommerce-message,
.pet-commerce-page .woocommerce-error,
.pet-commerce-page .wc-block-components-notice-banner {
  background: var(--pet-info-soft);
  border: 1px solid var(--pet-info);
  border-radius: 18px;
  color: var(--pet-text);
  line-height: 1.55;
  padding: 1rem 1.2rem;
}
.pet-commerce-page .woocommerce-error {
  background: var(--pet-danger-soft);
  border-color: var(--pet-danger);
}
.pet-account-page .woocommerce {
  display: grid;
  gap: clamp(1rem, 3vw, 2rem);
}
.pet-account-page .woocommerce:has(.woocommerce-MyAccount-navigation) {
  grid-template-columns: 280px minmax(0, 1fr);
}
/* Explicit rather than left to auto-placement. Measured on a real logged-in
   dashboard: nav (first in the DOM) was landing in the wide 688px track and
   the content panel (second) in the narrow 280px one -- exactly reversed from
   what grid-template-columns above declares and what an isolated copy of the
   same three rules renders correctly. Direction was ltr, order and
   grid-column both computed auto on both elements, nothing else in the whole
   matched-rule list touches either property, and the swap survived removing
   every other candidate -- so rather than leave two elements sized by
   whichever mechanism was actually doing this, each is pinned to its own
   track by name. */
.pet-account-page .woocommerce-MyAccount-navigation { grid-column: 1; }
.pet-account-page .woocommerce-MyAccount-content { grid-column: 2; }
.pet-account-page .woocommerce-MyAccount-navigation {
  background: var(--pet-surface-muted);
  border: 1px solid var(--pet-border);
  border-radius: var(--pet-radius-lg);
  float: none !important;
  padding: .75rem;
  width: auto !important;
}
.pet-account-page .woocommerce-MyAccount-navigation ul {
  display: grid;
  gap: .35rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.pet-account-page .woocommerce-MyAccount-navigation a {
  align-items: center;
  border-radius: 999px;
  color: var(--pet-text);
  display: flex;
  min-height: 44px;
  padding: .7rem 1rem;
  text-decoration: none;
}
.pet-account-page .woocommerce-MyAccount-navigation .is-active a,
.pet-account-page .woocommerce-MyAccount-navigation a:hover {
  background: var(--pet-primary);
  color: var(--pet-surface);
}
.pet-account-page .woocommerce-MyAccount-content,
.pet-account-page .woocommerce form.login,
.pet-account-page .woocommerce form.register,
.pet-account-page .woocommerce-ResetPassword {
  background: var(--pet-surface);
  border: 1px solid var(--pet-border);
  border-radius: 26px;
  box-shadow: 0 18px 38px color-mix(in srgb, var(--pet-shadow-color) 7%, transparent);
  padding: clamp(1.25rem, 3vw, 2rem);
}
.pet-account-page .woocommerce-MyAccount-content {
  /* WooCommerce's own woocommerce-layout.css floats and width-constrains
     this to 68% (nav gets 30%) for its default 2-column layout. We lay the
     two out with CSS Grid instead, but never neutralized the old float/width
     rule, so it silently persisted -- shrinking this panel inside its grid
     cell (or inside the single mobile column, where it's most visible) and
     leaving a large empty gap next to it. !important because we're
     deliberately overriding WooCommerce core CSS that loads before ours but
     could change specificity/order across plugin updates. */
  float: none !important;
  width: auto !important;
}
.pet-account-page .woocommerce form.login,
.pet-account-page .woocommerce form.register,
.pet-account-page .woocommerce-ResetPassword {
  max-width: 620px;
}
.pet-account-page .woocommerce h2,
.pet-account-page .woocommerce h3,
.pet-commerce-page .wc-block-components-title {
  color: var(--pet-text);
  font-weight: 900;
  letter-spacing: -.03em;
}
.pet-commerce-page .woocommerce form .form-row {
  margin: 0 0 1rem;
}
.pet-commerce-page .woocommerce label,
.pet-commerce-page .wc-block-components-text-input label,
.pet-commerce-page .wc-block-components-checkbox__label {
  color: var(--pet-text);
  font-size: .9rem;
  font-weight: 800;
}
.pet-commerce-page .woocommerce input.input-text,
.pet-commerce-page .woocommerce textarea,
.pet-commerce-page .woocommerce select,
.pet-commerce-page .select2-container .select2-selection,
.pet-commerce-page .wc-block-components-text-input input,
.pet-commerce-page .wc-block-components-combobox-control input,
.pet-commerce-page .wc-block-components-textarea {
  background: var(--pet-surface);
  /* An input's edge owes 3:1; the value this replaces measured 1.90 on
     white. --pet-border-input measures 3.79. */
  border: 1px solid var(--pet-border-input) !important;
  border-radius: 14px !important;
  box-shadow: none !important;
  color: var(--pet-text);
  min-height: 50px;
}
.pet-commerce-page .woocommerce input.input-text:focus,
.pet-commerce-page .woocommerce textarea:focus,
.pet-commerce-page .woocommerce select:focus,
.pet-commerce-page .wc-block-components-text-input input:focus,
.pet-commerce-page .wc-block-components-combobox-control input:focus,
.pet-commerce-page .wc-block-components-textarea:focus {
  /* A real ring, not the .18-alpha wash this replaces -- composited, that
     glow measured well under 3:1 against every ground it appeared on, which
     made the focused field practically indistinguishable from its
     neighbours. --pet-focus measures 12.23 on white. */
  border-color: var(--pet-focus) !important;
  outline: 3px solid var(--pet-focus) !important;
  outline-offset: 2px;
}
.pet-commerce-page .woocommerce button.button,
.pet-commerce-page .woocommerce a.button,
.pet-commerce-page .woocommerce input.button,
.pet-commerce-page .wc-block-components-button,
.pet-commerce-page .wc-block-components-checkout-place-order-button {
  background: var(--pet-primary) !important;
  border: 0 !important;
  border-radius: 999px !important;
  color: var(--pet-surface) !important;
  font-weight: 900;
  min-height: 50px;
  padding: .8rem 1.2rem !important;
}
.pet-commerce-page .woocommerce button.button:hover,
.pet-commerce-page .woocommerce a.button:hover,
.pet-commerce-page .woocommerce input.button:hover,
.pet-commerce-page .wc-block-components-button:hover,
.pet-commerce-page .wc-block-components-checkout-place-order-button:hover {
  background: var(--pet-primary-hover) !important;
  transform: translateY(-1px);
}
.pet-commerce-page .wc-block-cart-items__row,
.pet-commerce-page .wc-block-components-checkout-step,
.pet-commerce-page .wc-block-components-sidebar {
  border: 1px solid var(--pet-border);
  box-shadow: 0 14px 30px color-mix(in srgb, var(--pet-shadow-color) 6%, transparent);
}
.pet-commerce-page .wc-block-components-sidebar {
  position: sticky;
}
.pet-account-page .woocommerce-password-strength {
  border-radius: 12px;
  font-weight: 900;
  margin-top: .5rem;
  padding: .55rem .75rem;
}
.pet-account-page .woocommerce-password-strength.short,
.pet-account-page .woocommerce-password-strength.bad {
  background: var(--pet-accent-soft);
  color: var(--pet-accent-text);
}
.pet-account-page .woocommerce-password-strength.good,
.pet-account-page .woocommerce-password-strength.strong {
  background: var(--pet-success-soft);
  color: var(--pet-success);
}

/* The intro text is capped at 640px, which left the right half of the row
   empty while the buttons sat underneath it. They share a row now: the
   paragraph takes the space it needs, the actions sit beside it and drop
   below only when there is no room. */
.pet-specialty-lead {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  justify-content: space-between;
  margin-bottom: 1.4rem;
}

.pet-specialty-lead .pet-specialty-intro {
  flex: 1 1 420px;
  margin-bottom: 0;
}

.pet-specialty-lead .pet-cta-actions {
  flex: 0 1 auto;
}

/* Pointer to the ferret page from the small-pets section: the heading names
   ferrets, the content here does not cover them. */
.pet-specialty-aside {
  color: var(--pet-muted);
  font-size: .95rem;
  margin: 0 0 1.6rem;
  max-width: 640px;
}

.pet-specialty-aside a {
  color: var(--pet-primary);
  font-weight: 700;
  white-space: nowrap;
}

/* Fish price-list intro block (scripts/update-pet-category-pages.php,
   pet_town_render_fish_catalog_section()) -- deliberately not
   .pet-section-hero: that class carries the full page-hero background and
   padding meant for the one hero at the top of the page, and this sits
   further down as a lighter sub-heading for the catalogue that follows. */
.pet-fish-catalog-intro {
  padding-top: clamp(2.5rem, 5vw, 4.5rem);
}
.pet-fish-catalog-intro h2 {
  font-size: clamp(1.8rem, 4vw, 3rem);
  letter-spacing: -.04em;
  margin: 0 0 .6rem;
}
.pet-fish-catalog-intro p {
  color: var(--pet-muted);
  line-height: 1.6;
  margin: 0;
  max-width: 720px;
}

/* Flags a card whose name in the current page language is missing from the
   supplier's price list (see inventory/fish-pricing-report.md) -- the name
   shown instead is the source's own scientific/trade name, not a
   translation this codebase invented. */
.pet-fish-name-note {
  color: var(--pet-muted);
  font-size: .78rem;
  font-style: italic;
  line-height: 1.4;
  margin: .2rem 0 0;
}

/* Own-bred stock strip on the pets pages (update-pet-category-pages.php:
   pet_town_render_bred_stock_section). Cards are whole-card links, the same
   pattern the aquascaping specialty cards use; the arrow glyph inherits the
   [dir="rtl"] rotation from .pet-product-card-link in 50-catalog.css. */
.pet-bred-stock-section { padding: clamp(2rem, 5vw, 3.5rem) 0; }
.pet-bred-stock-section > h2 { margin-bottom: .5rem; }
.pet-bred-stock-section > p { color: var(--pet-muted); margin-bottom: 1.5rem; }
.pet-bred-stock-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
.pet-bred-stock-card { background: var(--pet-surface); border: 1px solid var(--pet-border); border-radius: 16px; color: inherit; display: flex; flex-direction: column; gap: .4rem; padding: 1.1rem 1.2rem; position: relative; text-decoration: none; transition: border-color .2s, transform .2s; }
/* Hover is read off the overlay, not off the card, because the card is no
   longer the link -- same coupling as .pet-specialty-card above. */
.pet-bred-stock-card:has(.pet-bred-stock-link:hover),
.pet-bred-stock-card:has(.pet-bred-stock-link:focus-visible) { border-color: var(--pet-primary); transform: translateY(-2px); }
/* Stretched over the whole card, and z-index stated rather than implied: the
   overlay is last in the DOM and absolutely positioned, which should already
   paint it above the in-flow content, but wpautop has a history on this
   project of wrapping it in a <p> of its own. */
.pet-bred-stock-link { border-radius: inherit; inset: 0; position: absolute; z-index: 1; }
/* The card's photograph. A fixed 1/1 box with object-fit: contain, not a
   crop: these are hand-held photographs of live stock in whatever aspect the
   phone produced (5712x4284 landscape and 2018x3077 portrait both occur), and
   a cover crop would cut animals out of a group shot. aspect-ratio plus the
   width/height on the <img> reserves the space before the file lands, so the
   strip does not shift as the photographs decode. */
/* The picture never needs the pointer: the whole card surface is one link,
   and a decorative image that takes a tap is exactly the iOS complaint that
   put pointer-events: none on .pet-specialty-card-photos. */
.pet-bred-stock-photo { align-items: center; aspect-ratio: 1 / 1; background: var(--pet-bg); border-radius: 12px; display: flex; justify-content: center; margin: 0 0 .3rem; overflow: hidden; pointer-events: none; }
.pet-bred-stock-photo img { display: block; height: 100%; object-fit: contain; width: 100%; }
.pet-bred-stock-card h3 { font-size: 1.02rem; margin: 0; }
.pet-bred-stock-card .pet-legacy-price { margin: 0; }
.pet-bred-stock-description { color: var(--pet-muted); font-size: .88rem; line-height: 1.55; margin: 0; }
.pet-bred-stock-care-label { font-size: .85rem; font-weight: 800; margin: .4rem 0 0; }
.pet-bred-stock-care { display: grid; gap: .35rem; margin: 0; padding-inline-start: 1.1rem; }
.pet-bred-stock-care li { font-size: .82rem; line-height: 1.45; }
.pet-bred-stock-card .pet-product-card-link { align-items: center; color: var(--pet-primary); display: flex; font-size: .85rem; font-weight: 800; gap: .35rem; margin-top: auto; padding-top: .5rem; }

/* The section's species photograph (the `image` record
   scripts/update-fish-catalog.php writes; licence register in
   docs/fish-section-images-2026-08-24.md). Natural-aspect photographs, not
   square product shots: cap the width and let height follow.

   There is deliberately no credit rule here any more. The owner asked for no
   attribution anywhere on the page, and the lawful way to give him that was
   to re-licence the photographs -- every one is now public domain or CC0,
   which need no displayed credit -- rather than to delete a credit a CC BY /
   CC BY-SA file is owed. .pet-fish-photo-credit is gone with the figcaption
   that used it. If a future image needs attribution, restore both; do not
   quietly ship it bare. */
.pet-fish-section-photo {
  margin: 0 0 1.1rem;
  max-width: 640px;
}
.pet-fish-section-photo img {
  border: 1px solid var(--pet-border);
  border-radius: var(--pet-radius-lg);
  display: block;
  height: auto;
  max-width: 100%;
}

/* Answers the owner's "why do the fish have so many different prices with no
   explanation given?" once, under the price-list heading. The sibling rule
   above sets margin: 0 on every intro paragraph, so the second one needs its
   own gap or the two run together. */
.pet-fish-catalog-intro p + p {
  margin-top: .55rem;
}

/* The same question answered per row: the size the price actually depends
   on. Quiet, but it is data the customer is comparing prices with, so it is
   --pet-text-secondary (5.80 on the page ground) rather than the lighter
   --pet-muted the italic name-note uses -- the same call
   .pet-specialty-credits documents further up this file. */
.pet-fish-size {
  color: var(--pet-text-secondary);
  font-size: .82rem;
  line-height: 1.4;
  margin: .25rem 0 0;
}

/* The species chip row that used to live here is now the shared
   pet-section-jump component: assets/css/85-section-jump.css and
   assets/pet-section-jump.js. It moved out of this file because it is no
   longer a pets component -- /shop/aquariums/, /shop/terrariums/ and
   /pets/rodents/ are the next callers. */

/* A fish row sold in more than one pack prints every pack with its own price,
   and the per-piece figure under them (scripts/update-pet-category-pages.php).
   The live feeder shrimp are the case that made this necessary: the card used
   to show "3036" beside an animal 1.5-2.5 cm long, with nothing saying that
   the number is a kilogram. Whole rule kept inside this one file -- the
   stylesheets are separate <link>s and are never concatenated. */
.pet-fish-packs {
  display: flex;
  flex-direction: column;
  gap: .2rem;
  list-style: none;
  margin: .45rem 0 0;
  padding: 0;
}
.pet-fish-packs li {
  align-items: baseline;
  display: flex;
  gap: .75rem;
  justify-content: space-between;
}
.pet-fish-pack-label {
  color: var(--pet-text-secondary);
  font-size: .85rem;
}
.pet-fish-pack-price {
  font-variant-numeric: tabular-nums;
  font-weight: 800;
}
.pet-fish-piece-price {
  color: var(--pet-text-secondary);
  font-size: .82rem;
  margin: .35rem 0 0;
}

/* The 10+1 offer on the fish price list
   (scripts/lib/fish-offer.php; declared in assets/data/fish-offer.json).

   Two sizes of the same thing, and the split is the whole design. The banner
   carries the sentence once, above a list 447 positions long, where a visitor
   cannot scroll past it. The note carries a badge and five words on every one
   of those positions, because a price the customer is reading halfway down
   the page has to say what it comes with, and the sentence repeated 447 times
   would bury the names and prices the list exists for.

   Colours are the pair the palette already measured for exactly this job:
   --pet-accent-text on --pet-accent-soft (4.91) for the warm panel, and
   --pet-text on the --pet-accent fill for the badge (the pairing
   tests/palette-contrast.php names "badges set dark text on the warm fill").
   --pet-accent is a fill here and nowhere a foreground; it measures 2.91 on
   white and that test fails a stylesheet that forgets it.

   No direction-specific rules: both blocks are flex rows with a gap, so the
   badge leads on /ru/ and /en/ and trails on the RTL Hebrew page without a
   [dir="rtl"] override. */
.pet-fish-offer {
  background: var(--pet-accent-soft);
  border-radius: var(--pet-radius-lg);
  /* A grid rather than flow, because of the two stacked variants below. With
     one variant it behaves identically -- a single-item grid of one column is
     the block it was. */
  display: grid;
  margin: 1.1rem 0 0;
  max-width: 720px;
  padding: 1rem 1.25rem;
}

/* ---------------------------------------------------------------------------
   THE TWO VARIANTS, AND WHY THE HIDDEN ONE STILL TAKES UP ROOM
   ---------------------------------------------------------------------------

   An offer declared `audience: "registered"` ships BOTH halves in the served
   HTML -- the invitation visible, the terms carrying `hidden` -- and
   assets/offer-audience.js moves that attribute once it knows who is reading.
   It has to be done in the browser: /{lang}/pets/fish/ is cached whole, so a
   personal state rendered on the server is the state the edge hands to the
   next visitor.

   The swap must not move anything, on a site whose Lighthouse CLS is 0. The
   announcement bar solves the same problem with a fixed height in pixels, but
   it holds one line; this panel holds a sentence that wraps differently in
   Russian, Hebrew and English and at every width, so a typed height would be
   a guess that is wrong somewhere.

   So both variants are placed in the SAME grid cell and the hidden one keeps
   its box: the cell is as tall as the taller of the two from the first paint,
   whichever one is showing, at every width and in every language. That is why
   `[hidden]` is overridden here to visibility rather than display -- the one
   place in these stylesheets where that is deliberate. visibility: hidden
   still removes the element from the accessibility tree and its links from
   the tab order, so the hidden half is genuinely hidden; it only continues to
   reserve the space that stops the page from jumping. Measured in headless
   Chrome over the real 450-row page: with the override the banner is
   144.73px before and after the swap, and every card 202.77px; without it the
   banner was 144.73 then 134.34, and the document 10px shorter.

   !important, and it is not decoration. 50-catalog.css ends with a blanket
   `[hidden] { display: none !important; }` so that the catalogue's filtering
   cannot be defeated by any component's own display declaration, and that
   sheet is loaded on this page. An ordinary declaration here loses to it
   whatever the file order, silently, and the only symptom is the shift this
   rule exists to prevent -- which is exactly how it was found. The scope is
   two selectors inside a promotion banner; nothing catalog.js filters is
   inside them.

   With CSS absent the attribute means what it always means and the hidden
   half is simply not laid out, which is the correct fallback.

   And each of the two selectors below restores ITS OWN display value rather
   than a convenient one. Writing `display: block` for both cost an hour: the
   card's note is a flex row, and as a block its badge and its sentence wrap
   at different points, so the box it reserved was 60px where the box it would
   occupy was 69px. On the Hebrew page at 390px that put a 9px error on each
   of 447 cards -- the document was 52,715px tall before the swap and
   51,316px after. A hidden element reserves the right space only when it is
   laid out exactly as it would be if it were showing. */
.pet-fish-offer-variant { grid-area: 1 / 1; }

.pet-fish-offer-variant[hidden] {
  display: block !important;
  visibility: hidden;
}

.pet-fish-offer-marks > .pet-fish-offer-note[hidden] {
  display: flex !important;
  visibility: hidden;
}

/* The same stack on each of the 447 cards, for the same reason: a card must
   be the same height before and after the browser learns who is reading. */
.pet-fish-offer-marks { display: grid; }
.pet-fish-offer-marks > .pet-fish-offer-note { grid-area: 1 / 1; }

/* The guest variant's two account links. Underlined rather than left to
   colour alone -- colour is not the only thing that may distinguish a link
   (WCAG 1.4.1) -- and set in --pet-accent-text, the tone the palette already
   measured at 4.91 on --pet-accent-soft. --pet-accent itself is a fill here
   and nowhere a foreground; tests/palette-contrast.php fails a stylesheet
   that forgets that. */
.pet-fish-offer-actions {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin: .55rem 0 0;
}

.pet-fish-offer-link {
  color: var(--pet-accent-text);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Decoration, and aria-hidden in the markup. --pet-text-secondary measures
   5.14 on the warm ground, comfortably more than a separator owes. */
.pet-fish-offer-sep { color: var(--pet-text-secondary); }
.pet-fish-offer-headline {
  align-items: center;
  color: var(--pet-accent-text);
  display: flex;
  font-size: .75rem;
  font-weight: 800;
  gap: .5rem;
  letter-spacing: .14em;
  margin: 0 0 .45rem;
  text-transform: uppercase;
}
.pet-fish-offer-text {
  color: var(--pet-accent-text);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.5;
  margin: 0;
}
/* The badge is the same token in both places, at the same size, so that the
   thing a shopper learns from the banner is the thing they recognise beside
   every price. letter-spacing is reset because the headline it sits inside
   is tracked-out uppercase and "10+1" is a quantity, not a label. */
.pet-fish-offer-badge {
  background: var(--pet-accent);
  border-radius: 999px;
  color: var(--pet-text);
  font-size: .78rem;
  font-variant-numeric: tabular-nums;
  font-weight: 900;
  letter-spacing: 0;
  padding: .1rem .45rem;
  text-transform: none;
  white-space: nowrap;
}
/* Under the price on each card, at the weight of .pet-fish-size beside it:
   this is one more fact about what the price buys, not a second heading. */
.pet-fish-offer-note {
  align-items: center;
  color: var(--pet-text-secondary);
  display: flex;
  flex-wrap: wrap;
  font-size: .8rem;
  gap: .4rem;
  line-height: 1.4;
  margin: .4rem 0 0;
}

/* A fish's own photograph, on the cards that have one -- six of 466 today.
   The section figure above the grid is a different thing and keeps its own
   rules; this is the picture of one fish, and it has to sit in a card that was
   laid out for text alone. object-fit: contain because these arrive cut out on
   white at whatever proportion the fish is: a discus is nearly round and a
   danio is a stripe, and cropping either to a fixed box would cut the fish.
   The height is fixed so a row of cards keeps one baseline whatever shape the
   fish in it are. */
.pet-fish-card-photo {
  display: block;
  width: 100%;
  height: 170px;
  object-fit: contain;
  background: transparent;
}

@media (max-width: 780px) {
  .pet-fish-card-photo { height: 130px; }
}

/* ...and the rule that makes the two above take effect, added 2026-08-27.
   Neither of them had ever applied. The <img> is a direct child of
   `.pet-legacy-product-card`, so `50-catalog.css`'s
   `.pet-legacy-product-card > img` (0-1-1) outranks a bare class (0-1-0) and
   was setting all five properties instead: `height: 260px`, `padding: 1rem`
   and `background: var(--pet-surface-muted)`. Loading later does not help --
   specificity is settled before source order, which AGENTS.md records having
   been learned three times now.

   Measured in headless Chrome on the fish price list: every card photo on the
   page came out 428px wide inside a 398px card, a 31px overflow in all three
   languages at both viewports. `box-sizing` here is `content-box`, so the
   inherited `width: 100%` (395.875px) and `padding: 1rem` add up rather than
   nesting. `.pet-legacy-product-card` has `overflow: hidden`, which is why
   this was invisible for as long as it existed: the padding box was clipped
   and the contained picture inside it sat nowhere near the cut. It stops
   being invisible the moment a card carries a picture wider than its own
   padding, and it is a real overflow either way.

   `box-sizing: border-box` is the fix for the overflow; `padding: 0` and the
   transparent background are the fish rule's own intent, which is different
   from the shop grid's on purpose -- these are aquarium scenes that fill
   their frame edge to edge, not pack shots floating on a white sweep, so a
   grey mat around them would draw a box that is not in the picture.

   The height stays at the 260px that has actually been rendering rather than
   dropping to the 170px the rule above asks for. It is the number the six
   fish photographs already on this page have shipped at, and the eight
   GloFish masters are portrait (305x463): `object-fit: contain` makes the
   HEIGHT the binding constraint for a portrait picture, so 170px would paint
   them 112px wide in a 398px card and 260px paints them 171px. The rule above
   keeps its numbers because they are what a landscape picture wants; this is
   the override that says the fish page renders the taller band. */
.pet-legacy-product-card > img.pet-fish-card-photo {
  background: transparent;
  box-sizing: border-box;
  height: 260px;
  padding: 0;
}

@media (max-width: 780px) {
  /* The card is roughly half a phone wide, so the same band takes a much
     larger share of it. 200px paints a portrait master 132px wide, which is
     two thirds of the card, and keeps the spec block above the fold. */
  .pet-legacy-product-card > img.pet-fish-card-photo { height: 200px; }
}

/* The short description on a fish card. Four cards carry one today, so this
   must not change the height of the 453 that do not -- it is only ever added
   below the price, never reserved. Clamped to four lines: the copy is written
   for a product page and the card is a summary, not the page. */
.pet-fish-card-copy {
  margin: 8px 0 0;
  font-size: 13px;
  line-height: 1.45;
  color: var(--pet-muted);
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* The detail card the owner's mock-up of 2026-08-26 asks for, on the ten fish
   the catalogue actually describes: binomial, three chips, description,
   possible colours, a spec list with icons, the price with its caption and
   the card's one action.

   Nothing below is reachable from the other 439 cards -- every selector
   names a class that only pet_town_fish_detail_card_parts() emits, and that
   function returns empty strings for a row with no `copy`. That is the
   property tests/fish-glofish-card.php holds byte for byte, and it is why
   this block can be as tall as it likes without touching a price list that
   is 449 positions long.

   Logical properties throughout (margin-inline, padding-inline, and flex,
   which follows the writing direction on its own). The Hebrew page carries
   dir="rtl" on its wrapper, so the chips, the swatch row and the spec rows
   all mirror without a single [dir="rtl"] override. */

/* The species, under the name, as the mock-up has it. Italic and quiet: it
   is what the fish IS, not what it is called, and the name above is the line
   a shopper scans. */
.pet-fish-card-latin {
  color: var(--pet-text-secondary);
  font-size: .82rem;
  font-style: italic;
  line-height: 1.4;
  margin: .2rem 0 0;
}
.pet-fish-card-latin em { font-style: italic; }

/* Family, water, how the colour is chosen. Read-only labels, so <li> and not
   a link or a control: the page's real filtering is the species chip row at
   the top, and a chip here that looked clickable and was not would be worse
   than one that plainly is not. */
.pet-fish-card-chips {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem;
  list-style: none;
  margin: .5rem 0 0;
  padding: 0;
}
.pet-fish-card-chip {
  background: var(--pet-surface-muted);
  border: 1px solid var(--pet-border);
  border-radius: 999px;
  color: var(--pet-text-secondary);
  font-size: .74rem;
  font-weight: 700;
  line-height: 1.3;
  padding: .18rem .55rem;
  white-space: nowrap;
}

/* The colours a buyer may get. The dot and the word travel together in one
   <li>: colour is never the only carrier of the fact, which is both the
   accessibility rule and what the mock-up draws.

   The dot's size is fixed here rather than derived from the font, so the row
   reserves exactly the same height before and after the stylesheet is
   applied -- a swatch that grows with a late webfont is the same layout
   shift a late image causes. flex: none stops it collapsing when a long
   colour name wraps beside it, and the inset ring keeps a pale swatch
   visible on the white card without drawing a hard outline round a dark one. */
.pet-fish-card-colours { margin-top: .55rem; }
.pet-fish-card-colours-label {
  color: var(--pet-text-secondary);
  font-size: .78rem;
  font-weight: 700;
  line-height: 1.4;
  margin: 0;
}
.pet-fish-card-colour-list {
  display: flex;
  flex-wrap: wrap;
  gap: .25rem .6rem;
  list-style: none;
  margin: .3rem 0 0;
  padding: 0;
}
.pet-fish-card-colour {
  align-items: center;
  display: flex;
  gap: .3rem;
}
.pet-fish-card-colour-dot {
  background: var(--pet-fish-colour, var(--pet-surface-muted));
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--pet-text) 22%, transparent);
  display: block;
  flex: none;
  height: 13px;
  width: 13px;
}
.pet-fish-card-colour-name {
  color: var(--pet-text-secondary);
  font-size: .78rem;
  line-height: 1.4;
}

/* The husbandry figures. One row per fact: icon, the fact in words, the
   value pushed to the end of the row with an auto inline margin, which
   mirrors on the Hebrew page without a second rule.

   The icons are decorative and every one of them has its own label beside
   it, so --pet-primary here is a glyph next to text and not a meaning
   carried by colour. It is deliberately not --pet-accent: that token
   measures 2.91 on white and tests/palette-contrast.php refuses it in any
   foreground property. */
.pet-fish-card-specs {
  border-top: 1px solid var(--pet-border);
  display: flex;
  flex-direction: column;
  gap: .3rem;
  list-style: none;
  margin: .6rem 0 0;
  padding: .55rem 0 0;
}
.pet-fish-card-spec {
  align-items: center;
  display: flex;
  gap: .4rem;
  line-height: 1.4;
}
.pet-fish-card-spec-icon {
  color: var(--pet-primary);
  fill: currentColor;
  flex: none;
}
.pet-fish-card-spec-label {
  color: var(--pet-text-secondary);
  font-size: .78rem;
}
.pet-fish-card-spec-value {
  color: var(--pet-text);
  font-size: .8rem;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  margin-inline-start: auto;
  text-align: end;
}

/* "Price for 1 fish", under the price or under the size list. The card sells
   a live animal one at a time, and the size list above it prints four
   figures; without this line the biggest number on the card is a size
   bracket's price with nothing saying what quantity it buys. */
.pet-fish-card-price-note {
  color: var(--pet-text-secondary);
  font-size: .78rem;
  line-height: 1.4;
  margin: .3rem 0 0;
}

/* The card's action. There is no basket on this page -- it is a browsable
   price list -- so this is the same #pet-contact-form jump every other "ask
   about this" button on the pets pages uses, and it is styled as the button
   it is rather than as a fake add-to-basket control. Full width so it reads
   as the end of the card. */
/* box-sizing, because `.pet-button` is padded and bordered and this theme
   sets no global border-box: `width: 100%` on a content-box button adds
   3rem of padding and 4px of border to the card's full content width, and
   the card is `overflow: hidden`, so the pill was clipped 26px short at each
   end. Measured 2026-08-27 in headless Chrome: a 406px button inside a 398px
   card, at both 390px and 1280px and in all three languages.

   flex rather than block, because `.pet-button` centres its label with
   `align-items`/`justify-content` and neither survives `display: block`.
   With block the words sat against the top edge of a 56px pill instead of in
   the middle of it, and `text-align: center` -- which is what block left in
   its place -- only ever fixed the horizontal half of that.

   margin-block-start: auto keeps the action pinned to the foot of the card,
   which is what it did before by borrowing 50-catalog.css's bare-link rule.
   That rule now excludes buttons (it was drawing the label in the pill's own
   colour), so the pinning has to be stated here instead of inherited, and
   the gap above it moves to the two blocks that can precede it -- scoped to
   the detail card, because `.pet-fish-offer-marks` is on all 449 and a
   margin added there would move every one of them. */
.pet-fish-card-action {
  box-sizing: border-box;
  display: flex;
  margin-block-start: auto;
  width: 100%;
}

.pet-fish-product-card-detailed .pet-fish-card-price-note,
.pet-fish-product-card-detailed .pet-fish-offer-marks {
  margin-block-end: .7rem;
}

/* The one-sentence stand-in for the "how we help" block, on every
   /{lang}/pets/{slug}/ page. That block used to be printed eight times --
   as an <aside> <ol> on six of these pages and folded into the article on
   /pets/dogs/ -- and the owner's WP3 rule of 2026-08-29 is that it renders
   exactly once, on /{lang}/pets/#how-we-help. This paragraph says the same
   thing in one sentence, in the page's own species wording, and links there.

   Six pages carry it inside the aside, where 90-misc.css already colours
   .pet-pet-detail-layout p; dogs carries it inline in the article, which is
   why the link colour is stated here rather than left to inherit from
   whichever of the two containers it landed in. */
.pet-help-reference {
  line-height: 1.6;
  margin: 0 0 1rem;
}

.pet-help-reference a {
  color: var(--pet-primary);
  font-weight: 700;
}

/* The arrow points at the link's destination, so it turns with the reading
   direction the way 40-sections.css turns .pet-info-cta b. Noted while
   writing this: .pet-specialty-aside's two &rarr; arrows on /pets/rodents/
   are NOT turned, and neither are the fish-catalog links' -- a pre-existing
   RTL inconsistency, left for R2 rather than swept into a WP3 commit. */
[dir="rtl"] .pet-help-reference a span {
  display: inline-block;
  transform: rotate(180deg);
}

/* ---------------------------------------------------------------------
   WP4: the block that carries what is specific to one pet child page
   (update-pet-category-pages.php: pet_town_render_pet_focus_section).
   Fish and reptiles render it above what it introduces -- the price list
   and the own-bred cards -- and rodents renders it after them, so the
   component has to sit correctly both above and below a section rather
   than assume a fixed neighbour. Hence symmetric block padding and no
   top or bottom margin of its own.

   Same 1180px measure as .pet-shop-specialties above, so the three
   sections a pets page can hold line up on one left edge. */
.pet-pet-focus {
  margin: clamp(2rem, 4vw, 3.5rem) auto 0;
  max-width: 1180px;
}
.pet-pet-focus > h2 {
  margin-bottom: .6rem;
}
.pet-pet-focus > p {
  color: var(--pet-muted);
  line-height: 1.7;
  margin: 0 0 .9rem;
  max-width: 72ch;
}
/* The link out of the block (rodents: into the shop's rodent section).
   .pet-text-link carries no styling anywhere in assets/css/ -- checked
   2026-08-29, it is used in the pets aside and matches nothing -- so the
   colour and weight are stated here rather than inherited from a rule
   that does not exist. */
.pet-pet-focus-link {
  margin: 0 0 1.2rem;
}
.pet-pet-focus-link a {
  color: var(--pet-primary);
  font-weight: 800;
}
/* The arrow points at the destination, so it turns with the reading
   direction -- the same treatment .pet-help-reference's arrow gets above
   and .pet-info-cta b gets in 40-sections.css. */
[dir="rtl"] .pet-pet-focus-link a span {
  display: inline-block;
  transform: rotate(180deg);
}

/* Cards linking to /{lang}/guides/{slug}/. Deliberately the same shape as
   .pet-bred-stock-card above -- an <article> with a stretched overlay
   <a>, never an <a> wrapped around an <h3>, because wpautop() runs over
   the saved post_content and tears the second shape apart (the comment on
   the bred strip in update-pet-category-pages.php records what that looked
   like on production).

   The z-index is stated rather than implied, and the honest version of
   why is worth writing down because the obvious claim turned out to be
   wrong. This card carries a .pet-product-card-link <span> for its "read
   the guide" affordance, and 80-pets.css gives that class an absolutely
   positioned `::after { inset: 0 }` stretched link of its own -- so the
   expectation was that without a z-index the pseudo-element would cover
   the real anchor and the card would stop being clickable. Measured in
   headless Chrome over the built pages, 72 hit tests in ru/he/en against
   document.elementFromPoint: deleting `z-index: 1` changed nothing. Both
   are in one stacking context and the anchor is later in the DOM, so it
   already paints on top.

   It stays for the reason .pet-bred-stock-link states beside it: that
   ordering is an implicit property of markup wpautop() rewrites, and this
   content is stored in post_content and run through it. One declaration
   is cheaper than depending on the shape of somebody else's output. */
.pet-guide-link-grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 240px), 1fr));
  margin-top: .4rem;
}
.pet-guide-link-card {
  background: var(--pet-surface);
  border: 1px solid var(--pet-border);
  border-radius: 16px;
  display: flex;
  flex-direction: column;
  gap: .4rem;
  padding: 1.1rem 1.2rem;
  position: relative;
  transition: border-color .2s, transform .2s;
}
.pet-guide-link-card:has(.pet-guide-link:hover),
.pet-guide-link-card:has(.pet-guide-link:focus-visible) {
  border-color: var(--pet-primary);
  transform: translateY(-2px);
}
.pet-guide-link-card h3 {
  font-size: 1.02rem;
  margin: 0;
}
.pet-guide-link-card .pet-product-card-link {
  align-items: center;
  border-top: 0;
  color: var(--pet-primary);
  display: flex;
  font-size: .85rem;
  font-weight: 800;
  gap: .35rem;
  justify-content: flex-start;
  margin-top: auto;
  padding-top: .5rem;
  text-decoration: none;
}
.pet-guide-link {
  border-radius: inherit;
  inset: 0;
  position: absolute;
  z-index: 1;
}

/* The age/size ladder on an own-bred card. It exists because the card's
   heading and price are the LEAD variant's, and for rats and mice the lead
   is also the dearest rung -- so the card advertised 25 ILS over a line
   whose newborns are 5. Every rung is a variant of that line in
   bred-animals.json; a line with one variant renders no list at all.

   Rendered as a definition-like two-column row rather than a comma list so
   the prices align down the card, and pointer-events: none because the
   whole card is one link and a list item that swallows a tap is the iOS
   complaint that already put the same declaration on
   .pet-specialty-card-photos. */
.pet-bred-stock-stages-label {
  color: var(--pet-text-secondary);
  font-size: .78rem;
  font-weight: 800;
  letter-spacing: .02em;
  margin: .35rem 0 .1rem;
  text-transform: uppercase;
}
.pet-bred-stock-stages {
  display: grid;
  gap: .18rem;
  list-style: none;
  margin: 0;
  padding: 0;
  pointer-events: none;
}
.pet-bred-stock-stages li {
  color: var(--pet-muted);
  display: flex;
  font-size: .85rem;
  gap: .5rem;
  justify-content: space-between;
}
.pet-bred-stock-stages b {
  color: var(--pet-text);
  font-weight: 800;
  white-space: nowrap;
}
