/**
 * TrendMix — Professional Design Layer
 *
 * Loaded last, after consistency.css. Everything here is presentation only:
 * no selectors are renamed, no markup is required, no behaviour is touched.
 *
 * Rules of the layer:
 *   - Colour, spacing and radius come from tokens. Hard-coded hex values are
 *     only used where a token does not exist yet, and each one is commented.
 *   - Logical properties (inline-start/end, block-start/end) everywhere, so
 *     the stylesheet is direction-agnostic and needs no RTL override.
 *   - Each component appears once. If a value is already correct upstream it
 *     is not repeated here.
 *
 * Contents
 *   1.  Tokens
 *   2.  Document safety, focus and motion
 *   3.  Typography
 *   4.  Container and section rhythm
 *   5.  Buttons and links
 *   6.  Forms
 *   7.  Cards
 *   8.  Header and navigation
 *   9.  Footer
 *   10. Page heroes
 *   11. Accordions and FAQ
 *   12.  Small components
 *   12b. Error and search pages
 *   12c. WooCommerce shop archive
 *   12d. Plain and account pages
 *   13. Responsive corrections
 */

/* ==========================================================================
   1. TOKENS
   ========================================================================== */

:root {
  /*
   * Brand ramp. The palette itself arrives as an inline :root block from
   * inc/customizer.php, which also writes --ui-primary* and --ui-accent*.
   * Only values that have no palette equivalent live here.
   */
  /*
   * Legacy gradient names. These were literal blue and orange values, so the
   * 404 numeral and any other element still using them rendered in a colour
   * the palette no longer contains. They are re-pointed at the palette so
   * there is nothing left to fall out of sync.
   */
  --brand-gradient: linear-gradient(
    135deg,
    var(--ui-primary-dark) 0%,
    var(--ui-primary) 55%,
    var(--ui-primary-light) 100%
  );
  --gold-gradient: linear-gradient(
    135deg,
    var(--ui-accent-dark) 0%,
    var(--ui-accent) 45%,
    var(--ui-accent-light) 100%
  );
  --luxury-gradient: linear-gradient(
    135deg,
    var(--ui-primary-dark) 0%,
    var(--ui-primary) 42%,
    var(--ui-accent) 100%
  );

  --pf-tint-1: 0.06;
  --pf-tint-2: 0.12;
  --pf-tint-3: 0.22;

  /* Translucent brand washes, built from the resolved channel list. */
  --pf-wash-1: rgba(var(--ui-primary-rgb), var(--pf-tint-1));
  --pf-wash-2: rgba(var(--ui-primary-rgb), var(--pf-tint-2));
  --pf-wash-3: rgba(var(--ui-primary-rgb), var(--pf-tint-3));
  --pf-gold-wash: rgba(var(--ui-accent-rgb), 0.14);

  /* One band padding for every full-width section. */
  --pf-band: clamp(3.5rem, 6vw, 5.75rem);
  --pf-band-tight: clamp(2.75rem, 4.5vw, 4rem);
  --pf-head-gap: clamp(1.5rem, 2.6vw, 2.25rem);

  /* One shape scale. Upstream files already mix 8/12/14/18/24; these are the
     only radii components are allowed to use from here on. */
  --pf-r-sm: 10px;
  --pf-r-md: 14px;
  --pf-r-lg: 20px;
  --pf-r-xl: 28px;

  /* One elevation pair. */
  --pf-lift: 0 18px 42px rgba(var(--ui-primary-rgb), 0.14),
             0 3px 10px rgba(20, 16, 15, 0.05);
  --pf-lift-soft: 0 10px 26px rgba(20, 16, 15, 0.08),
                  0 2px 6px rgba(20, 16, 15, 0.04);

  /* Motion. */
  --pf-ease: cubic-bezier(0.4, 0, 0.2, 1);
  --pf-ease-back: cubic-bezier(0.34, 1.3, 0.64, 1);
  --pf-dur: 260ms;
  --pf-transition: transform var(--pf-dur) var(--pf-ease),
                   box-shadow var(--pf-dur) var(--pf-ease),
                   border-color var(--pf-dur) var(--pf-ease),
                   background-color var(--pf-dur) var(--pf-ease),
                   color var(--pf-dur) var(--pf-ease);

  /* Shell (header/footer) ink, tuned for white text on --ui-shell. */
  --pf-shell-ink: rgba(255, 255, 255, 0.76);
  --pf-shell-ink-strong: rgba(255, 255, 255, 0.94);
  --pf-shell-line: rgba(255, 255, 255, 0.14);
  --pf-shell-tile: rgba(255, 255, 255, 0.08);
}

/* ==========================================================================
   2. DOCUMENT SAFETY, FOCUS AND MOTION
   ========================================================================== */

html {
  /*
   * clip, not hidden: hidden would turn the root into a scroll container and
   * break position:sticky on the header and the sticky purchase card.
   */
  overflow-x: clip;
  overscroll-behavior-x: none;
  scroll-padding-block-start: 96px;
}

body {
  overflow-x: clip;
  overscroll-behavior-x: none;
  /* Arabic body copy reads better with the extra leading. */
  line-height: 1.85;
}

@supports not (overflow: clip) {
  html,
  body {
    overflow-x: hidden;
  }
}

/* One focus ring for the whole site. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--ui-primary);
  outline-offset: 3px;
  border-radius: var(--pf-r-sm);
}

/* Inputs keep their ring as a shadow so the border does not double up. */
:where(input, select, textarea):focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(var(--ui-primary-rgb), 0.2);
}

.skip-link:focus,
.skip-link:focus-visible {
  position: fixed;
  inset-block-start: 12px;
  inset-inline-start: 12px;
  z-index: 999;
  width: auto;
  height: auto;
  padding: 0.75rem 1.25rem;
  clip: auto;
  color: #fff;
  background: var(--ui-primary);
  border-radius: var(--pf-r-sm);
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ==========================================================================
   3. TYPOGRAPHY
   ========================================================================== */

h1,
h2,
h3,
h4,
h5,
h6 {
  letter-spacing: -0.015em;
  text-wrap: balance;
}

/* Arabic letterforms break below this size; keep descenders from clipping. */
h1,
h2,
h3 {
  line-height: 1.28;
}

p,
li,
dd {
  line-height: 1.85;
}

/*
 * Section headings. The templates use six different class names for the same
 * job, so they are listed once here instead of drifting apart page by page.
 */
.page-hero-title,
.tm-section-title,
.service-section-title,
.about-section-title,
.contact-section-title,
.ab-heading,
.tm-faq__title,
.tm-blog__title,
.tm-packages__title,
.tm-sd-section-title,
.services-archive__title,
.tm-search-page__title {
  color: var(--ui-text-headings);
  font-weight: 800;
  line-height: 1.28;
  text-wrap: balance;
}

/* Eyebrows. One spec, matching --ui-eyebrow-*. */
.page-hero-label,
.tm-home-label,
.tm-section-eyebrow,
.service-section-eyebrow,
.about-section-label,
.contact-section-label,
.ab-eyebrow,
.tm-sd-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  width: fit-content;
  font-family: var(--font-sans);
  font-size: var(--ui-eyebrow-size);
  font-weight: var(--ui-eyebrow-weight);
  letter-spacing: var(--ui-eyebrow-tracking);
  line-height: 1.4;
}

/* Muted copy. */
.page-hero-subtitle,
.tm-home-hero__description,
.tm-home-faq-answer p,
.service-card-excerpt,
.tm-service-card__excerpt,
.tm-post-card__excerpt,
.tm-blog-card__excerpt,
.ab-text,
.contact-section-lead,
.tm-sd-section-subtitle {
  color: var(--ui-text-secondary);
  line-height: 1.85;
}

/* ==========================================================================
   4. CONTAINER AND SECTION RHYTHM
   ========================================================================== */

.container,
.container--wide,
.container--narrow,
.tm-container,
.tm-container-narrow {
  margin-inline: auto;
  padding-inline: 0;
}

.site-main > section {
  padding-block: var(--pf-band);
}

/* Sections that carry a tinted surface keep their own padding. */
.tm-home-hero,
.tm-home-final {
  padding-block: var(--pf-band);
}

/*
 * Branded bands. Three large wine surfaces sit next to each other at the foot
 * of the home page, so each gets its own step of the palette ramp instead of
 * blending into one continuous block:
 *   stats strip -> primary dark, final CTA -> primary, footer -> deep shell.
 */
.tm-home-trust {
  background: var(--ui-primary-dark);
}

.tm-home-trust__label {
  color: rgba(255, 255, 255, 0.82);
  font-weight: 600;
}

.tm-home-trust__item {
  border-color: rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.06);
  transition: transform var(--pf-dur) var(--pf-ease),
              background-color var(--pf-dur) var(--pf-ease),
              border-color var(--pf-dur) var(--pf-ease);
}

.tm-home-trust__item:hover {
  border-color: rgba(var(--ui-accent-rgb), 0.5);
  background: rgba(255, 255, 255, 0.1);
  transform: translateY(-3px);
}

.tm-home-final__inner {
  border-radius: var(--pf-r-xl);
  border: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow: 0 24px 60px rgba(var(--ui-primary-rgb), 0.35);
}

/* Section head: eyebrow, title, subtitle, optional link, in one rhythm. */
.tm-home-section-head,
.tm-home-structured-head,
.tm-home-tools__head,
.tm-home-testimonials__head,
.tm-home-numbers__head,
.tm-home-process__intro,
.tm-home-insights__head,
.tm-faq__heading,
.tm-blog__heading,
.tm-packages__heading,
.ab-head,
.tm-sd-section-header,
.services-archive__head,
.page-hero > .container {
  margin-block-end: var(--pf-head-gap);
}

/* A "see all" link parked in a section head must sit on the title's baseline. */
.tm-home-insights__head,
.tm-home-tools__head,
.tm-home-testimonials__head,
.tm-home-numbers__head {
  align-items: center;
  justify-content: space-between;
  gap: 1rem 1.5rem;
  flex-wrap: wrap;
}

@media (max-width: 767px) {
  .tm-home-insights__head,
  .tm-home-tools__head,
  .tm-home-testimonials__head,
  .tm-home-numbers__head {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ==========================================================================
   5. BUTTONS AND LINKS
   ========================================================================== */

.btn,
.tm-btn,
.tm-home-btn,
.ab-btn,
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce a.button.alt,
.woocommerce button.button.alt,
input[type="submit"] {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  font-weight: 700;
  letter-spacing: 0;
  transition: var(--pf-transition);
}

.btn:hover,
.tm-btn:hover,
.tm-home-btn:hover,
.ab-btn:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover,
.woocommerce a.button.alt:hover,
.woocommerce button.button.alt:hover,
input[type="submit"]:hover {
  transform: translateY(-2px);
}

/*
 * Sheen sweep on hover. A narrow skewed highlight travelling across the fill,
 * which is what makes a flat button read as a pressed surface.
 */
.btn::after,
.tm-btn::after,
.tm-home-btn::after,
.ab-btn::after,
.woocommerce a.button::after,
.woocommerce button.button::after,
.woocommerce input.button::after,
input[type="submit"]::after {
  position: absolute;
  inset-block: 0;
  inset-inline-start: -70%;
  z-index: -1;
  width: 45%;
  content: '';
  background: linear-gradient(
    100deg,
    transparent,
    rgba(255, 255, 255, 0.32),
    transparent
  );
  transform: skewX(-18deg);
  opacity: 0;
  pointer-events: none;
}

.btn:hover::after,
.tm-btn:hover::after,
.tm-home-btn:hover::after,
.ab-btn:hover::after,
.woocommerce a.button:hover::after,
.woocommerce button.button:hover::after,
.woocommerce input.button:hover::after,
.woocommerce a.button.alt:hover::after,
.woocommerce button.button.alt:hover::after,
input[type="submit"]:hover::after {
  opacity: 1;
  animation: pf-sheen 720ms var(--pf-ease) forwards;
}

@keyframes pf-sheen {
  to {
    inset-inline-start: 130%;
  }
}

/* Filled variants lift with a brand shadow instead of a grey one. */
.btn-primary:hover,
.tm-btn--primary:hover,
.tm-home-btn--primary:hover,
.ab-btn:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover,
.woocommerce a.button.alt:hover,
.woocommerce button.button.alt:hover,
input[type="submit"]:hover {
  box-shadow: 0 12px 26px rgba(var(--ui-primary-rgb), 0.28);
}

/*
 * The ghost variant is an outline on a dark brand panel, so the filled-button
 * shadow above reads as a green halo bleeding through the transparent fill.
 * A neutral dark lift keeps the separation without tinting the surface.
 */
.ab-btn--ghost-light:hover {
  box-shadow: 0 12px 26px rgba(0, 0, 0, 0.28);
}

/* Outline and ghost variants need a background to read as a hover at all. */
.btn-secondary:hover,
.btn-outline:hover,
.btn-ghost:hover,
.tm-btn--outline:hover,
.tm-btn--ghost:hover,
.tm-home-btn--light:hover,
.tm-home-btn--dark:hover {
  color: var(--ui-primary);
  background: var(--pf-wash-1);
  border-color: rgba(var(--ui-primary-rgb), var(--pf-tint-3));
}

.btn:active,
.tm-btn:active,
.tm-home-btn:active,
.ab-btn:active,
.woocommerce a.button:active,
.woocommerce button.button:active,
input[type="submit"]:active {
  transform: translateY(0);
}

/* Inline links inside body copy. */
.site-main :where(p, li) a:not(.btn):not(.tm-btn):not(.ab-btn) {
  text-decoration-color: rgba(var(--ui-accent-rgb), 0.7);
  text-underline-offset: 0.22em;
  text-decoration-thickness: 1.5px;
  transition: color var(--pf-dur) var(--pf-ease),
              text-decoration-color var(--pf-dur) var(--pf-ease);
}

.site-main :where(p, li) a:not(.btn):not(.tm-btn):not(.ab-btn):hover {
  color: var(--ui-primary);
  text-decoration-color: var(--ui-primary);
}

/* ==========================================================================
   6. FORMS
   ========================================================================== */

:where(input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]),
       select,
       textarea) {
  min-height: var(--control-height);
  padding: 0.7rem 1rem;
  color: var(--ui-text-primary);
  background: #fff;
  border: 1px solid rgba(20, 16, 15, 0.14);
  border-radius: var(--pf-r-md);
  transition: border-color var(--pf-dur) var(--pf-ease),
              box-shadow var(--pf-dur) var(--pf-ease);
}

:where(input, select, textarea):hover:not(:focus) {
  border-color: rgba(20, 16, 15, 0.24);
}

:where(input, select, textarea):focus {
  border-color: var(--ui-primary);
}

textarea {
  min-height: 148px;
  line-height: 1.8;
  resize: vertical;
}

::placeholder {
  color: var(--ui-text-subtle);
  opacity: 1;
}

:where(label) {
  color: var(--ui-text-secondary);
  font-size: 0.9rem;
  font-weight: 600;
}

:where(input[type="checkbox"], input[type="radio"]) {
  accent-color: var(--ui-primary);
  width: 18px;
  height: 18px;
}

/* ==========================================================================
   7. CARDS
   ========================================================================== */

/*
 * One hover behaviour for every card family on the site. The rules above set
 * up the surface; these give it the lift, the shadow and the gold hairline
 * that make a card feel clickable.
 */
.service-card,
.tm-service-card,
.tm-product-card,
.tm-home-service-card,
.tm-home-package-card,
.tm-post-card,
.tm-blog-card,
.tm-home-tool,
.tm-home-pillar,
.tm-home-insight,
.tm-home-testimonial,
.about-value-card,
.tm-contact-card,
.tm-sidebar-card,
.tm-sd-benefit-card,
.tm-sd-included-card,
.tm-sd-stat-card,
.tm-sd-related-card,
.tm-sd-process-step,
.tm-pk-plan-card,
.ab-aside-card,
.ab-capability,
.tm-404-page__nav-link,
.woocommerce .wc-block-grid .wc-block-grid__product {
  transition: var(--pf-transition);
}

.service-card:hover,
.tm-service-card:hover,
.tm-product-card:hover,
.tm-home-service-card:hover,
.tm-home-package-card:hover,
.tm-post-card:hover,
.tm-blog-card:hover,
.tm-home-tool:hover,
.tm-home-pillar:hover,
.tm-home-insight:hover,
.tm-home-testimonial:hover,
.about-value-card:hover,
.tm-contact-card:hover,
.tm-sidebar-card:hover,
.tm-sd-benefit-card:hover,
.tm-sd-included-card:hover,
.tm-sd-stat-card:hover,
.tm-sd-related-card:hover,
.tm-sd-process-step:hover,
.tm-pk-plan-card:hover,
.ab-aside-card:hover,
.ab-capability:hover,
.tm-404-page__nav-link:hover {
  border-color: rgba(var(--ui-accent-rgb), 0.5);
  box-shadow: var(--pf-lift);
  transform: translateY(-5px);
}

/*
 * Capabilities hover: one hue, one shadow, on the element that has a surface.
 *
 * The shared rule above treats `.ab-capability` as the card, but on this page
 * the card is the `.ab-capability__link` inside it. The <li> is a bare grid item
 * with no background and no border, so everything the shared rule put on it was
 * either invisible or wrong:
 *
 *   - border-color did nothing: the <li> has border-width 0.
 *   - box-shadow painted a green glow on a transparent box, so the card wore
 *     two shadows at once -- this one bleeding out from behind the link, and the
 *     link's own --ui-card-elevated on top of it. That halo is what read as a
 *     dirty edge around the hovered card.
 *   - transform never applied at all. `animations.js` tags every direct child of
 *     any `[class*="grid"]`, so each <li> carries `data-tm-anim`, and the reveal
 *     rule `.tm-anim-ready [data-tm-anim].is-animated { transform: none }`
 *     outranks a class-and-pseudo rule like this one. The lift was silently
 *     dead; only the inner link's -4px ever showed.
 *
 * So the <li> is reset to a plain grid item and the whole hover moves to the
 * link, which is what actually paints.
 *
 * The border also moves from --ui-accent to --ui-primary. The accent is the
 * teal #2fbfa0 while the primary is the green #0fa96b, and the title already
 * turns green on hover, so the old rule ringed the card in teal while the text
 * inside it went green. Two hues on one card read as a mistake rather than as
 * emphasis. Note the token it used to come from, --ui-border-gold, is a
 * misnomer: its value is the accent teal, not a gold.
 */
.ab-capability:hover {
  border-color: transparent;
  box-shadow: none;
  transform: none;
}

.ab-capability__link:hover {
  border-color: rgba(var(--ui-primary-rgb), 0.45);
  box-shadow: var(--pf-lift);
  transform: translateY(-4px);
}

/* Keep the title in step with the border: one hue, primary throughout. */
.ab-capability__link:hover .ab-capability__title {
  color: var(--ui-primary);
}

/* CTA rows inside a card sit at the bottom so a row of cards lines up. */
.tm-home-service-card,
.tm-home-package-card,
.tm-post-card,
.tm-blog-card,
.service-card,
.tm-product-card {
  display: flex;
  flex-direction: column;
}

.tm-home-service-card__body,
.tm-home-package-card__body,
.tm-post-card__body,
.tm-blog-card__body,
.service-card-body,
.tm-product-card__body {
  display: flex;
  flex: 1;
  flex-direction: column;
}

.tm-home-service-card .service-card-cta,
.tm-home-service-card .tm-btn,
.tm-home-package-card .tm-btn,
.tm-post-card .tm-btn,
.tm-blog-card .tm-btn,
.service-card .service-card-cta,
.tm-product-card .tm-btn {
  margin-block-start: auto;
}

/* Card titles share one scale. */
.tm-home-service-card__title,
.tm-home-package-card__title,
.tm-post-card__title,
.tm-blog-card__title,
.service-card-title,
.tm-service-card__title,
.tm-pk-plan-card__title,
.tm-sd-related-card__title {
  font-size: 1.12rem;
  font-weight: 700;
  line-height: 1.5;
}

/* Images inside a card frame get a branded placeholder, so a slow or missing
   image reads as a designed panel rather than a hole in the grid. */
.service-card-image,
.tm-service-card__thumbnail-wrap,
.tm-home-service-card__image,
.tm-home-package-card__image,
.tm-product-card__image,
.tm-post-card__thumbnail,
.tm-blog-card__image {
  background:
    linear-gradient(135deg, var(--pf-wash-1), transparent 60%),
    var(--ui-surface-tertiary);
}

.service-card-image img,
.tm-service-card__thumbnail-wrap img,
.tm-home-service-card__image img,
.tm-home-package-card__image img,
.tm-product-card__image img,
.tm-post-card__thumbnail img,
.tm-blog-card__image img {
  transition: transform 600ms var(--pf-ease);
}

/* ==========================================================================
   8. HEADER AND NAVIGATION
   ========================================================================== */

.site-header {
  position: sticky;
  inset-block-start: 0;
  z-index: 900;
  background: rgba(255, 255, 255, 0.96);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border-block-end: 1px solid var(--ui-border-light);
  /*
   * The shadow is permanent rather than scroll-triggered. The header is
   * sticky, so it overlaps content at all times past the fold and a shadow
   * that only appears on scroll would be a behaviour change, not a style.
   */
  box-shadow: 0 8px 26px rgba(var(--ui-primary-rgb), 0.06);
}

.site-header-inner {
  min-height: 76px;
  gap: clamp(1rem, 2.5vw, 2rem);
}

.site-logo img {
  max-height: 48px;
}

/* Nav items. */
.nav-menu {
  gap: clamp(0.125rem, 0.5vw, 0.375rem);
}

.nav-menu > li > a {
  position: relative;
  padding: 0.55rem 0.8rem;
  border-radius: var(--pf-r-sm);
  transition: color var(--pf-dur) var(--pf-ease),
              background-color var(--pf-dur) var(--pf-ease);
}

.nav-menu > li > a:hover {
  color: var(--ui-primary);
  background: var(--pf-wash-1);
}

/*
 * The current page is marked with the gold rule and the brand colour only. A
 * tinted block behind a nav item reads as a button, not as a location.
 */
.nav-menu > li.current-menu-item > a,
.nav-menu > li.current-menu-ancestor > a {
  color: var(--ui-primary);
  background: transparent;
  font-weight: 700;
}

/* Gold underline marks the current page instead of a tint alone. */
.nav-menu > li.current-menu-item > a::after,
.nav-menu > li.current-menu-ancestor > a::after {
  position: absolute;
  inset-block-end: 2px;
  inset-inline: 0.8rem;
  height: 2px;
  content: '';
  background: var(--ui-accent);
  border-radius: var(--pf-r-sm);
}

/* Dropdowns. */
.nav-menu .sub-menu {
  padding: 0.5rem;
  background: #fff;
  border: 1px solid var(--ui-border-light);
  border-radius: var(--pf-r-md);
  box-shadow: 0 18px 44px rgba(20, 16, 15, 0.12);
}

.nav-menu .sub-menu a {
  padding: 0.6rem 0.8rem;
  border-radius: var(--pf-r-sm);
  transition: color var(--pf-dur) var(--pf-ease),
              background-color var(--pf-dur) var(--pf-ease);
}

.nav-menu .sub-menu a:hover {
  color: var(--ui-primary);
  background: var(--pf-wash-1);
}

/* Header actions. */
.header-actions {
  gap: 0.5rem;
}

.cart-link,
.header-actions .btn-ghost {
  position: relative;
  min-height: 42px;
  padding: 0.45rem 0.85rem;
  border-radius: var(--pf-r-sm);
  border: 1px solid transparent;
  transition: color var(--pf-dur) var(--pf-ease),
              background-color var(--pf-dur) var(--pf-ease),
              border-color var(--pf-dur) var(--pf-ease);
}

.cart-link:hover,
.header-actions .btn-ghost:hover {
  color: var(--ui-primary);
  background: var(--pf-wash-1);
  border-color: rgba(var(--ui-primary-rgb), var(--pf-tint-2));
}

.cart-count-badge {
  display: inline-grid;
  place-items: center;
  min-width: 20px;
  height: 20px;
  padding-inline: 5px;
  color: #fff;
  background: var(--ui-primary);
  border-radius: var(--pf-r-sm);
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 1;
}

.mobile-menu-toggle {
  width: 44px;
  height: 44px;
  border: 1px solid var(--ui-border-light);
  border-radius: var(--pf-r-sm);
}

.mobile-menu-toggle:hover {
  background: var(--pf-wash-1);
  border-color: rgba(var(--ui-primary-rgb), var(--pf-tint-2));
}

.hamburger-line {
  background: var(--ui-text-primary);
}

/* Off-canvas menu.
   The panel follows the footer shell, so every link colour below moves from
   the default dark ink to white; leaving any of them dark makes them
   unreadable on the wine surface. */
.mobile-nav {
  background: var(--ui-shell);
  border-block-start: 3px solid var(--ui-accent);
}

.mobile-nav-inner {
  padding: var(--space-4) clamp(1rem, 4vw, 1.5rem) 2.5rem;
}

.mobile-nav-menu li,
.mobile-nav .nav-menu li {
  border-block-end: 1px solid var(--pf-shell-line);
}

.mobile-nav-menu a,
.mobile-nav .nav-menu a {
  padding: 1rem 0.25rem;
  color: var(--pf-shell-ink-strong);
  font-weight: 600;
  transition: color var(--pf-dur) var(--pf-ease),
              background-color var(--pf-dur) var(--pf-ease);
}

.mobile-nav-menu a:hover,
.mobile-nav .nav-menu a:hover {
  color: var(--ui-accent);
  background: rgba(255, 255, 255, 0.06);
}

.mobile-nav-menu li.current-menu-item > a,
.mobile-nav .nav-menu li.current-menu-item > a {
  color: var(--ui-accent);
  font-weight: 700;
}

/* Sub-level items get an inset and a quieter ink so the hierarchy is clear. */
.mobile-nav .nav-menu .sub-menu {
  padding-inline-start: 1rem;
  background: rgba(0, 0, 0, 0.18);
  border-block-start: 1px solid var(--pf-shell-line);
  border-radius: 0;
}

.mobile-nav .nav-menu .sub-menu li {
  border-block-end: 0;
}

.mobile-nav .nav-menu .sub-menu a {
  padding: 0.7rem 0.25rem;
  color: var(--pf-shell-ink);
  font-size: 0.92rem;
  font-weight: 500;
}

.mobile-nav-actions .btn {
  min-height: 48px;
}

.mobile-menu-close {
  color: #fff;
  border-color: var(--pf-shell-line);
  background: rgba(255, 255, 255, 0.06);
}

/*
 * The close glyph is two spans with an inline background of #333, and an
 * inline declaration outranks any stylesheet rule. This is the one place a
 * !important is the only way to keep the glyph visible on the dark panel.
 */
.mobile-menu-close .hamburger-line > span {
  background: #fff !important;
}

.mobile-menu-close:hover {
  background: rgba(255, 255, 255, 0.14);
}

/* The header toggle becomes the close affordance while the panel is open. */
body.mobile-menu-open .mobile-menu-toggle .hamburger-line {
  background: var(--ui-primary);
}

/* ==========================================================================
   9. FOOTER
   ========================================================================== */

.site-footer {
  position: relative;
  color: var(--pf-shell-ink);
  background: var(--ui-shell);
  border-block-start: 0;
  border-block-end: 0;
}

/*
 * A 4px brand rule instead of the old 3px flat bar. It is the one place a
 * gradient is allowed on a large surface because it is a 4px edge, not a fill.
 */
.site-footer::before {
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  height: 4px;
  content: '';
  background: linear-gradient(
    90deg,
    var(--ui-primary),
    var(--ui-primary-light) 45%,
    var(--ui-accent)
  );
}

.footer-top {
  padding-block: clamp(3rem, 5vw, 4.5rem) clamp(2rem, 3.5vw, 3rem);
  gap: clamp(2rem, 3.5vw, 3rem);
}

.footer-logo img {
  max-height: 52px;
  margin-block-end: 1.1rem;
}

.footer-logo-text {
  font-size: 1.4rem;
  font-weight: 800;
}

.footer-tagline {
  max-width: 34ch;
  margin-block-end: 1.5rem;
  color: var(--pf-shell-ink-strong);
  font-size: 0.95rem;
  line-height: 1.9;
}

/* Social tiles. */
.footer-social {
  gap: 0.75rem;
}

.footer-social-link {
  width: 44px;
  height: 44px;
  color: var(--pf-shell-ink-strong);
  background: var(--pf-shell-tile);
  border: 1px solid var(--pf-shell-line);
  border-radius: var(--pf-r-md);
  transition: transform var(--pf-dur) var(--pf-ease-back),
              background-color var(--pf-dur) var(--pf-ease),
              color var(--pf-dur) var(--pf-ease);
}

.footer-social-link:hover {
  color: #fff;
  background: var(--ui-primary);
  border-color: var(--ui-primary-light);
  transform: translateY(-3px);
}

/* Column headings with a short accent underline. */
.footer-col-title {
  position: relative;
  margin-block-end: 1.5rem;
  padding-block-end: 0.85rem;
  color: #fff;
  font-size: 1.05rem;
  font-weight: 800;
  letter-spacing: 0;
  text-transform: none;
}

.footer-col-title::after {
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 0;
  width: 40px;
  height: 3px;
  content: '';
  background: var(--ui-accent);
  border-radius: var(--pf-r-sm);
}

/* Link lists. */
.footer-nav-list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.footer-nav-list a {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--pf-shell-ink);
  text-decoration: none;
  transition: color var(--pf-dur) var(--pf-ease),
              transform var(--pf-dur) var(--pf-ease);
}

/*
 * Directional marker drawn as a border chevron rather than a glyph, so it
 * points toward the inline-end in both LTR and RTL without a transform.
 */
.footer-nav-list a::before {
  width: 0.45rem;
  height: 0.45rem;
  content: '';
  border-inline-end: 1.5px solid currentColor;
  border-block-end: 1.5px solid currentColor;
  opacity: 0;
  transform: rotate(45deg);
  transition: opacity var(--pf-dur) var(--pf-ease);
}

.footer-nav-list a:hover {
  color: #fff;
  transform: translateX(-3px);
}

[dir="rtl"] .footer-nav-list a:hover {
  transform: translateX(3px);
}

.footer-nav-list a:hover::before {
  opacity: 1;
}

/* Contact rows get an icon tile, matching the social tiles. */
.footer-contact-item {
  gap: 0.85rem;
  margin-block-end: 1rem;
}

.footer-contact-icon {
  width: 42px;
  height: 42px;
  padding: 10px;
  color: var(--ui-accent);
  background: var(--pf-shell-tile);
  border: 1px solid var(--pf-shell-line);
  border-radius: var(--pf-r-md);
  flex: 0 0 auto;
}

.footer-contact-item span {
  color: var(--pf-shell-ink-strong);
  line-height: 1.6;
}

/* Bottom bar. */
.footer-bottom {
  padding-block: 1.5rem;
  border-block-start: 1px solid var(--pf-shell-line);
  font-size: 0.9rem;
}

.footer-copyright {
  color: rgba(255, 255, 255, 0.6);
}

.footer-legal {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
}

.footer-legal a {
  color: var(--pf-shell-ink);
  text-decoration: none;
  transition: color var(--pf-dur) var(--pf-ease);
}

.footer-legal a:hover {
  color: var(--ui-accent);
}

@media (max-width: 767px) {
  .footer-bottom {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
  }
}

/* ==========================================================================
   10. PAGE HEROES
   ========================================================================== */

/*
 * Two hero treatments exist and both are intentional:
 *   - Light panel: .page-hero (about, services, packages, contact, blog).
 *     A wine-tinted neutral with a faint grid, dark wine heading, gold rule.
 *   - Dark band: .tm-sd-hero (single package / single service).
 *     The palette hero gradient with white ink.
 * They are kept explicitly here so neither can drift into the other.
 */

.page-hero,
.contact-hero,
.about-hero,
.tm-blog-hero {
  min-height: 0;
  padding-block: var(--pf-band);
}

/*
 * One type scale for every centred hero head. Four separate clamps had been
 * declared for the same heading -- 4.25rem / 4.35rem / 4.4rem ceilings and a
 * 5vw / 5.2vw slope -- across layout.css, consistency.css and this file, so
 * the same page element rendered at three slightly different sizes depending
 * on which template it sat in. `clamp` also needs a unitless 0 middle term to
 * interpolate smoothly from a fixed floor.
 */
.page-hero-title,
.contact-hero .page-hero-title,
.tm-blog__title {
  color: var(--ui-primary-dark);
  font-size: clamp(2.3rem, 5vw + 0.2rem, 4.3rem);
  font-weight: 800;
  line-height: 1.22;
}

.page-hero-subtitle,
.contact-hero .page-hero-subtitle {
  max-width: 68ch;
  margin-inline: auto;
  color: var(--ui-text-secondary);
  font-size: clamp(1rem, 0.5vw + 0.9rem, 1.15rem);
  line-height: 1.9;
}

/* Dark band heroes. */
.tm-sd-hero,
.tm-pk-hero {
  min-height: 0;
  padding-block: var(--pf-band);
}

.tm-sd-hero__title,
.tm-pk-hero .page-hero-title {
  color: #fff;
  font-size: clamp(2.3rem, 5vw + 0.2rem, 4.3rem);
  font-weight: 800;
  line-height: 1.22;
}

/*
 * The single service/package head centres its title like every other hero, so
 * the accent rule above it has to centre too. This is the one hero whose
 * heading carries its own class rather than .page-hero-title, which is why it
 * was missing from the shared rule in consistency.css.
 */
.tm-sd-hero__title::before {
  content: "";
  display: block;
  width: 56px;
  height: 2px;
  margin-inline: auto;
  margin-bottom: var(--space-5);
  border-radius: var(--pf-r-pill, 999px);
  background: var(--ui-accent);
}

/*
 * The excerpt is a hero subtitle, not body copy. A full WordPress excerpt runs
 * to five or six lines under the title and pushes the stat cards and actions
 * out of the first screen, so it is clamped to roughly two lines with an
 * ellipsis. `ch` on a clamped block is what does the truncating; the max-width
 * is the fallback width the clamp is computed against.
 */
.tm-sd-hero__excerpt {
  display: -webkit-box;
  max-width: 62ch;
  margin-inline: auto;
  color: rgba(255, 255, 255, 0.84);
  font-size: clamp(0.95rem, 0.4vw + 0.85rem, 1.05rem);
  line-height: 1.75;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}

/* ==========================================================
   10a. Home hero
   ========================================================== */

/*
 * The hero used to be a white card floating on a pale grid, off to one side of
 * a two-column grid whose second column held nothing. It now reads as a hero:
 * a full-bleed band of brand colour with the headline, copy, actions and stat
 * pills centred on it in white.
 *
 * The band paints its own gradient from the palette's hero stops, so it is
 * never blank without an admin uploading anything. An optional background photo
 * arrives as `--tm-hero-image` from the Customizer and sits in its own layer
 * under a scrim of `--tm-hero-overlay`; when no photo is set neither is
 * emitted and the gradient alone carries the section.
 */
.tm-home-hero {
  /*
   * How dark the scrim goes. The palette gradient puts the brand's mid
   * primary at its centre -- a mid-bright green under the default logo palette
   * -- and white body copy over that lands near 3.7:1, short of AA. The base
   * value is set high enough to carry the copy on the gradient alone; the
   * `--has-image` modifier below swaps in whatever the admin picked for their
   * photo, which is the case the control actually exists for.
   */
  --tm-scrim: 0.62;

  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: grid;
  align-items: center;
  min-height: clamp(520px, 76vh, 720px);
  padding-block: clamp(4rem, 9vw, 7rem);
  background-color: var(--ui-hero-surface);
  background-image: var(--ui-hero-bg);
  border-bottom: 0;
}

.tm-home-hero--has-image {
  --tm-scrim: var(--tm-hero-overlay, 0.55);
}

/*
 * The three decorative layers are split across two pseudo-elements and one
 * element pseudo rather than stacked on one, because two of them need
 * conflicting treatments: the scrim has to cover the photo edge to edge, while
 * the grid has to be masked so it dissolves toward the corners. One masked
 * element cannot do both. The negative z-indices put the whole set behind the
 * copy while still inside the hero's own `isolation: isolate` context, so
 * nothing leaks out and nothing in the page behind can bleed in.
 *
 *   -3  photo        ::before
 *   -2  scrim        ::after
 *   -1  grid + bloom .tm-home-hero__grid::before
 */

/* The optional photo. `--tm-hero-image` is absent unless one was chosen, so
   the layer resolves to `none` and the gradient shows through untouched. */
.tm-home-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -3;
  background-image: var(--tm-hero-image, none);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  pointer-events: none;

  /*
   * Both pseudo-elements are being redeclared for a second time, and they have
   * to clear more than they set. Two earlier blocks in consistency.css hang
   * `width`/`height`/`border-radius` on this same pair -- one pair of outlined
   * circles, one bloom blob -- and neither resets the box, so the declarations
   * survive. With `inset: 0` in force, a leftover `width: 42rem` beats the
   * inset and pins the layer to a fixed square: the scrim stopped short of the
   * band and left a hard vertical seam down the page.
   *
   * So: size from the inset (width/height auto), drop the circle, drop the
   * hairline ring, drop the mask.
   */
  width: auto;
  height: auto;
  border: 0;
  border-radius: 0;
  -webkit-mask-image: none;
  mask-image: none;
}

/* Scrim. Full-bleed and unmasked, so the bottom of a bright photo cannot
   out-read the stat strip. Lighter at the top and heaviest at the bottom: the
   top has only the headline over it, the foot carries the copy and the pills.

   The tint is --ui-primary-900 (#034d31), the brand's darkest green step, so
   the band darkens toward the palette instead of toward black. A near-black
   scrim over this photo read as a dead grey panel; the green keeps it on-brand.

   The stops sit well above `--tm-scrim` itself. A photo chosen for its bright
   brand-green cast still pushed white body copy under 4.5:1 here, and the
   headline fought the artwork behind it, so each stop carries a floor of its
   own rather than scaling down with the admin's slider. Raising `--tm-scrim`
   still darkens the band further; lowering it no longer bleaches the photo. */
.tm-home-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  background-image: linear-gradient(
    to bottom,
    rgba(3, 77, 49, max(0.72, calc(var(--tm-scrim) * 0.94))) 0%,
    rgba(3, 77, 49, max(0.82, var(--tm-scrim))) 50%,
    rgba(3, 77, 49, min(0.95, max(0.9, calc(var(--tm-scrim) + 0.24)))) 100%
  );

  /* See the note on ::before: clears the inherited 46rem box, ring and radius. */
  width: auto;
  height: auto;
  border: 0;
  border-radius: 0;
  -webkit-mask-image: none;
  mask-image: none;
}

/* Grid + bloom. Both are meant to fade out, so they share the one mask. */
.tm-home-hero__grid::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    radial-gradient(
      ellipse 38rem 38rem at 14% 12%,
      rgba(var(--ui-accent-rgb), 0.26) 0%,
      rgba(var(--ui-accent-rgb), 0.09) 45%,
      rgba(var(--ui-accent-rgb), 0) 70%
    ),
    linear-gradient(to right, rgba(255, 255, 255, 0.06) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255, 255, 255, 0.06) 1px, transparent 1px);
  background-size: auto, 72px 72px, 72px 72px;
  -webkit-mask-image: radial-gradient(ellipse at 50% 22%, #000 0%, transparent 76%);
  mask-image: radial-gradient(ellipse at 50% 22%, #000 0%, transparent 76%);
}

.tm-home-hero > .container {
  position: relative;
  z-index: 1;
}

/* Single centred column. The two-column grid and its empty second column are
   gone, so nothing offsets the content to one side any more. */
.tm-home-hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  padding-block: 0;
  text-align: center;
}

/*
 * The white card is dropped: its padding, border and start-edge accent were
 * sized to frame copy on a light panel, and against a saturated band they read
 * as a box drawn around the headline rather than as a hero. The copy is centred
 * and bounded by measure instead.
 */
.tm-home-hero__content-inner {
  width: 100%;
  max-width: 54rem;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
}

/*
 * `margin-bottom` here carries `!important` on purpose. layout.css pins the
 * headline and the standfirst with `margin-bottom: 24px/34px !important`, and
 * an `!important` declaration beats any later rule of the same specificity no
 * matter which file it is in. Centring needs the inline margins too, so the
 * shorthand has to win outright.
 */
.tm-home-hero__title {
  max-width: 22ch;
  margin: 0 auto var(--space-5) !important;
  font-size: clamp(2.25rem, 5.4vw, 4rem);
  line-height: 1.16;
  letter-spacing: -0.02em;
  color: #ffffff;
  text-shadow: 0 2px 24px rgba(4, 26, 20, 0.35);
  text-wrap: balance;
}

/* The accent line keeps its own row so the two halves of the headline stack. */
.tm-home-hero__title span {
  display: block;
}

.tm-home-hero__title .text-accent {
  color: var(--ui-accent-light);
}

/* Same `!important` reasoning as the headline above. */
.tm-home-hero__description {
  max-width: 62ch;
  margin: 0 auto var(--space-7) !important;
  color: rgba(255, 255, 255, 0.82);
  font-size: var(--text-lg);
  line-height: 1.9;
  text-shadow: 0 1px 12px rgba(4, 26, 20, 0.3);
}

/* ---------- Actions ---------- */

.tm-home-hero__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
}

/*
 * On a saturated band the solid green button disappears into it, so the primary
 * action becomes a white plate and the secondary a white outline. That inverts
 * the light-card pairing and keeps the pair legible on any palette.
 */
.tm-home-hero__actions .btn-primary {
  background: #ffffff;
  border-color: #ffffff;
  color: var(--ui-primary-dark);
  box-shadow: 0 14px 30px rgba(4, 26, 20, 0.28);
}

.tm-home-hero__actions .btn-primary:hover {
  background: var(--ui-primary-50);
  border-color: var(--ui-primary-50);
  color: var(--ui-primary-dark);
  box-shadow: 0 18px 38px rgba(4, 26, 20, 0.34);
}

.tm-home-hero__actions .btn-accent {
  background: transparent !important;
  background-image: none !important;
  border: 1.5px solid rgba(255, 255, 255, 0.7) !important;
  color: #ffffff !important;
  box-shadow: none !important;
  opacity: 1;
}

.tm-home-hero__actions .btn-accent:hover {
  background: rgba(255, 255, 255, 0.14) !important;
  border-color: #ffffff !important;
  color: #ffffff !important;
  opacity: 1;
}

/* ---------- Responsive ---------- */

@media (max-width: 1024px) {
  .tm-home-hero {
    min-height: auto;
  }

  .tm-home-hero__title {
    max-width: 20ch;
  }
}

@media (max-width: 640px) {
  .tm-home-hero {
    padding-block: clamp(3rem, 14vw, 4.5rem);
  }

  .tm-home-hero__title {
    max-width: none;
    font-size: clamp(1.9rem, 8vw, 2.6rem);
  }

  .tm-home-hero__description {
    margin-bottom: var(--space-6);
    font-size: 1rem;
  }

  .tm-home-hero__actions .btn {
    width: 100%;
    justify-content: center;
  }
}

/* ==========================================================================
   11. ACCORDIONS AND FAQ
   ========================================================================== */

/*
 * The home and package FAQ lists were hairline rows with no padding, so the
 * question sat on the divider and the toggle floated far from the text. Each
 * item is now a card.
 */
.tm-home-faq__list,
.tm-faq__list,
.tm-sd-faq__list,
.tm-faq .container .tm-home-faq__list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  max-width: 860px;
  margin-inline: auto;
  border-block-start: 0;
}

/*
 * Home FAQ layout.
 *
 * The grid was `.7fr 1.3fr` capped at 1100px inside a 1280px container, and the
 * list carried `max-width: 860px` inside a 650px column. The four items ended up
 * as 381px cards stacked down one side with a large void beside them, and the
 * heading floated in a column of its own. The section now uses the full
 * container: a fixed heading column, and the questions as a 2x2 grid that fills
 * whatever is left.
 */
.tm-home-faq__grid {
  grid-template-columns: minmax(0, 360px) minmax(0, 1fr);
  gap: clamp(2rem, 4vw, 3.5rem);
  align-items: start;
  max-width: none;
}

.tm-home-faq .tm-home-faq__list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.9rem;
  align-content: start;
  max-width: none;
  margin: 0;
}

/* An expanded answer needs the full row, not half of it. */
.tm-home-faq .tm-home-faq-item.is-open {
  grid-column: 1 / -1;
}

@media (max-width: 1024px) {
  .tm-home-faq__grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 2rem;
  }
}

@media (max-width: 680px) {
  .tm-home-faq .tm-home-faq__list {
    grid-template-columns: minmax(0, 1fr);
  }
}

.tm-home-faq-item,
.tm-faq-item,
.tm-sd-faq-item {
  border: 1px solid var(--ui-border-light);
  border-radius: var(--pf-r-md);
  background: #fff;
  box-shadow: var(--ui-elev-1);
  transition: border-color var(--pf-dur) var(--pf-ease),
              box-shadow var(--pf-dur) var(--pf-ease);
}

.tm-home-faq-item:hover,
.tm-faq-item:hover,
.tm-sd-faq-item:hover {
  border-color: rgba(var(--ui-primary-rgb), var(--pf-tint-2));
  box-shadow: var(--pf-lift-soft);
}

.tm-home-faq-item.is-open,
.tm-faq-item.is-open,
.tm-sd-faq-item.is-open {
  border-color: rgba(var(--ui-primary-rgb), var(--pf-tint-3));
}

.tm-home-faq-question,
.tm-faq-question,
.tm-sd-faq-item__question {
  gap: 1.25rem;
  min-height: 0;
  padding: 1.15rem 1.35rem;
  color: var(--ui-text-headings);
  font-size: 1.02rem;
  font-weight: 700;
  line-height: 1.65;
  transition: color var(--pf-dur) var(--pf-ease);
}

.tm-home-faq-question:hover,
.tm-faq-question:hover,
.tm-sd-faq-item__question:hover {
  color: var(--ui-primary);
}

/* Toggle button. */
.tm-home-faq-question > span:last-child,
.tm-faq-icon,
.tm-sd-faq-item__question .tm-faq-icon {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: 0 0 34px;
  color: var(--ui-primary);
  background: var(--pf-wash-1);
  border: 1px solid rgba(var(--ui-primary-rgb), var(--pf-tint-2));
  border-radius: 50%;
  font-size: 1.15rem;
  font-weight: 400;
  line-height: 1;
  transition: background-color var(--pf-dur) var(--pf-ease),
              color var(--pf-dur) var(--pf-ease),
              transform var(--pf-dur) var(--pf-ease),
              border-color var(--pf-dur) var(--pf-ease);
}

.tm-home-faq-question[aria-expanded='true'] > span:last-child,
.tm-faq-question[aria-expanded='true'] .tm-faq-icon,
.tm-sd-faq-item__question[aria-expanded='true'] .tm-faq-icon {
  color: #fff;
  background: var(--ui-primary);
  border-color: var(--ui-primary);
  transform: rotate(45deg);
}

.tm-home-faq-answer,
.tm-faq-answer,
.tm-sd-faq-item__answer {
  padding: 0 1.35rem 1.35rem;
}

.tm-home-faq-answer p,
.tm-faq-answer-inner,
.tm-sd-faq-item__answer p {
  max-width: 76ch;
  margin: 0;
  padding-block-start: 1rem;
  border-block-start: 1px solid var(--ui-border-soft);
  color: var(--ui-text-secondary);
  font-size: 0.98rem;
  line-height: 1.9;
}

/* ==========================================================================
   12. SMALL COMPONENTS
   ========================================================================== */

/* Badges and pills. */
.tm-badge,
.tm-pk-plan-card__badge,
.tm-sd-hero__badge,
.service-card-category,
.tm-blog-card__category {
  border-radius: var(--pf-r-sm);
  font-weight: 700;
  letter-spacing: 0.01em;
}

/* Pagination. */
.tm-pagination,
.services-pagination,
.woocommerce .woocommerce-pagination ul.page-numbers {
  gap: 0.4rem;
}

.tm-pagination a,
.tm-pagination span,
.services-pagination a,
.services-pagination span,
.woocommerce .woocommerce-pagination ul.page-numbers li > * {
  min-width: 42px;
  min-height: 42px;
  display: inline-grid;
  place-items: center;
  padding-inline: 0.6rem;
  color: var(--ui-text-secondary);
  background: #fff;
  border: 1px solid var(--ui-border-light);
  border-radius: var(--pf-r-sm);
  text-decoration: none;
  transition: var(--pf-transition);
}

.tm-pagination .is-current span,
.services-pagination .is-current span,
.woocommerce .woocommerce-pagination ul.page-numbers li > span.current {
  color: #fff;
  background: var(--ui-primary);
  border-color: var(--ui-primary);
}

.tm-pagination a:hover,
.services-pagination a:hover,
.woocommerce .woocommerce-pagination ul.page-numbers li > a:hover {
  color: var(--ui-primary);
  border-color: rgba(var(--ui-primary-rgb), var(--pf-tint-3));
  background: var(--pf-wash-1);
  transform: translateY(-2px);
}

/* Breadcrumbs. */
.tm-sd-breadcrumb {
  font-size: 0.9rem;
  color: rgba(255, 255, 255, 0.7);
}

.tm-sd-breadcrumb a {
  color: rgba(255, 255, 255, 0.86);
  text-decoration: none;
}

.tm-sd-breadcrumb a:hover {
  color: var(--ui-accent);
}

/* Sticky sidebar / purchase card. */
.service-sidebar-sticky,
.service-purchase-card {
  border-radius: var(--pf-r-lg);
}

/* Sticky offsets must clear the sticky header. */
.service-purchase-card {
  inset-block-start: 96px;
}

/* Trust / stats strips. */
.tm-home-trust__item,
.tm-sd-trust-item,
.tm-sd-trust__item,
.tm-home-numbers__grid > * {
  border-radius: var(--pf-r-md);
}

/* Testimonials keep a short gold rail on the inline-start edge. */
.tm-home-testimonial {
  border-radius: var(--pf-r-lg);
}

/* Tables. */
:where(table) {
  width: 100%;
  border-collapse: collapse;
}

:where(th, td) {
  padding: 1rem 1.25rem;
  text-align: start;
  border-block-end: 1px solid var(--ui-border-soft);
}

:where(thead th) {
  color: var(--ui-text-headings);
  background: var(--ui-surface-secondary);
  font-weight: 700;
}

/* Images should never push a grid track wider than its column. */
:where(img, svg, video, iframe) {
  max-width: 100%;
}

/*
 * A fixed minimum left short cards (a one-line value card on the contact page)
 * looking half empty. Cards now take their height from their content; grid
 * stretch still keeps a row aligned.
 */
.about-value-card,
.contact-value-card {
  min-height: 0;
}

/* ==========================================================================
   12b. ERROR AND SEARCH PAGES
   ========================================================================== */

/*
 * The photo veil on a single service or package mixed a slate-blue stop into
 * the gradient, which cooled the hero away from the rest of the brand.
 *
 * The outer stops were rgba(var(--ui-primary-rgb), ...). That token is the
 * brand's *mid* green (15, 169, 107), so a bright green was being laid over
 * the artwork and the band read washed-out rather than deep. The tint is now
 * #034d31 -- --ui-primary-900, the darkest step of the same ramp -- matching
 * the front-page scrim in .tm-home-hero::after, and the mid stop is folded in
 * to that same value instead of a separate near-black.
 */
.tm-sd-hero__veil,
.service-detail-hero__veil {
  background: linear-gradient(
    180deg,
    rgba(3, 77, 49, 0.86) 0%,
    rgba(3, 77, 49, 0.91) 55%,
    rgba(3, 77, 49, 0.95) 100%
  );
}

.tm-404-page__search-form,
.tm-search-page__search-form {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  max-width: 640px;
  margin-inline: auto;
}

.tm-404-page__search-form input,
.tm-search-page__search-form input {
  flex: 1 1 240px;
  min-width: 0;
}

.tm-404-page__search-form button,
.tm-search-page__search-form button,
.tm-404-page__search-form .btn,
.tm-search-page__search-form .btn {
  flex: 0 0 auto;
  width: auto;
  min-width: 160px;
}

.tm-404-page__badge {
  background: var(--pf-wash-2);
  border: 1px solid rgba(var(--ui-primary-rgb), var(--pf-tint-2));
  border-radius: var(--pf-r-sm);
  color: var(--ui-primary);
}

/* ==========================================================================
   12c. WOOCOMMERCE SHOP ARCHIVE
   ========================================================================== */

/*
 * WooCommerce renders the shop archive from its own plugin template, which
 * emits the products header, the ordering form and the product grid with none
 * of the theme's container, hero band or card chrome. Rather than add a
 * template file, the layout is rebuilt here so the shop matches every other
   page. Markup is untouched.
 */

.woocommerce-shop .site-main,
.woocommerce.archive .site-main,
.woocommerce.product-category .site-main,
.woocommerce.woocommerce-page .site-main {
  padding-block-end: var(--pf-band);
}

/* Header band, matching .page-hero. */
.woocommerce-shop .woocommerce-products-header,
.woocommerce.archive .woocommerce-products-header {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-block-end: var(--pf-head-gap);
  padding: var(--pf-band) clamp(1.5rem, 4vw, 2.5rem);
  background: var(--ui-surface-secondary);
  border-block-end: 1px solid var(--ui-border-soft);
}

.woocommerce-shop .woocommerce-products-header__title,
.woocommerce.archive .woocommerce-products-header__title {
  margin: 0;
  color: var(--ui-primary-dark);
  font-family: var(--font-display);
  font-size: clamp(2rem, 3.6vw, 3rem);
  font-weight: 800;
  line-height: 1.25;
}

/* Toolbar: result count on the start side, sort select on the end side. */
.woocommerce-shop .woocommerce-result-count,
.woocommerce.archive .woocommerce-result-count,
.woocommerce-shop .woocommerce-ordering,
.woocommerce.archive .woocommerce-ordering {
  width: min(100% - 3rem, var(--container-max));
  margin-inline: auto;
}

.woocommerce-shop .woocommerce-result-count,
.woocommerce.archive .woocommerce-result-count {
  margin-block: 0 0.75rem;
  color: var(--ui-text-muted);
  font-size: 0.9rem;
}

.woocommerce-shop .woocommerce-ordering,
.woocommerce.archive .woocommerce-ordering {
  display: flex;
  justify-content: flex-end;
  margin-block: 0 1.75rem;
}

.woocommerce-shop .woocommerce-ordering select,
.woocommerce.archive .woocommerce-ordering select {
  width: auto;
  min-width: 260px;
  max-width: 100%;
  padding-block: 0.65rem;
  padding-inline: 2.5rem 1rem;
  font-size: 0.95rem;
  cursor: pointer;
}

/* Product grid. */
.woocommerce-shop ul.products,
.woocommerce.archive ul.products {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: clamp(1.25rem, 2.5vw, 2rem);
  width: min(100% - 3rem, var(--container-max));
  margin: 0 auto;
  padding: 0;
  list-style: none;
}

.woocommerce-shop ul.products li.product,
.woocommerce.archive ul.products li.product {
  display: flex;
  flex-direction: column;
  /* WooCommerce floats the loop items and pins a percentage width from its
     columns-3 class. Both have to go for the grid above to size them. */
  float: none;
  width: auto;
  overflow: hidden;
  background: #fff;
  border: 1px solid var(--ui-border-light);
  border-radius: var(--pf-r-lg);
  box-shadow: var(--ui-elev-2);
  transition: var(--pf-transition);
}

.woocommerce-shop ul.products li.product:hover,
.woocommerce.archive ul.products li.product:hover {
  border-color: rgba(var(--ui-accent-rgb), 0.5);
  box-shadow: var(--pf-lift);
  transform: translateY(-5px);
}

.woocommerce-shop ul.products li.product a.woocommerce-LoopProduct-link,
.woocommerce.archive ul.products li.product a.woocommerce-LoopProduct-link {
  display: flex;
  flex: 1;
  flex-direction: column;
  color: inherit;
  text-decoration: none;
}

.woocommerce-shop ul.products li.product img,
.woocommerce.archive ul.products li.product img {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background: var(--ui-surface-tertiary);
  transition: transform 600ms var(--pf-ease);
}

.woocommerce-shop ul.products li.product:hover img,
.woocommerce.archive ul.products li.product:hover img {
  transform: scale(1.04);
}

.woocommerce-shop .woocommerce-loop-product__title,
.woocommerce.archive .woocommerce-loop-product__title {
  margin: 1.15rem 1.25rem 0;
  padding: 0;
  font-size: 1.12rem;
  font-weight: 700;
  line-height: 1.5;
}

.woocommerce-shop ul.products li.product .price,
.woocommerce.archive ul.products li.product .price {
  display: block;
  margin: 0.6rem 1.25rem 1.25rem;
  color: var(--ui-primary);
  font-size: 1.1rem;
  font-weight: 700;
}

/* The add-to-cart link is a sibling of the product link, so it needs its own
   inset rather than the body's flex padding. */
.woocommerce-shop ul.products li.product .add_to_cart_button,
.woocommerce.archive ul.products li.product .add_to_cart_button {
  margin: 0 1.25rem 1.25rem;
}

/* ==========================================================================
   12d. PLAIN AND ACCOUNT PAGES
   ========================================================================== */

/*
 * Templates without a dedicated hero (legal pages, account, search) fall back
 * to .page-title inside a centred column. That column used to read as loose
 * text on white; it now carries the same heading scale, gold rule and card
 * surface as every other page.
 */

.page-wrapper {
  padding-block: var(--pf-band);
}

.page-content-container {
  max-width: 820px;
  margin-inline: auto;
}

.page-title {
  position: relative;
  margin-block-end: 1.75rem;
  padding-block-end: 1.25rem;
  color: var(--ui-primary-dark);
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 3.2vw, 2.6rem);
  font-weight: 800;
  line-height: 1.25;
  text-align: start;
}

.page-title::after {
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 0;
  width: 64px;
  height: 3px;
  content: '';
  background: var(--ui-accent);
  border-radius: var(--pf-r-sm);
}

/*
 * Centring the accent rule when its heading is centred.
 *
 * The rule is `position: absolute`, so `margin-inline: auto` cannot centre it:
 * for an absolutely positioned box the inline margins resolve against the static
 * position and both compute to 0. An earlier rule here put `margin-inline: auto`
 * on `.page-title::after` alongside the heading, which looks like it centres the
 * rule and does not. On the cart and my-account pages -- the two places that
 * centre `.page-title` -- the word sat dead centre while the rule stayed pinned
 * to the inline-start edge, 148px away, on a 820px column.
 *
 * A centred rule needs both offsets pinned and the width auto:
 * `inset-inline: 0` plus `width: 64px` makes the box over-constrained, and CSS
 * then resolves the auto margin to centre it. Written with logical properties so
 * it works in both directions without a separate RTL rule.
 */
.woocommerce-cart .page-title::after,
.woocommerce-account .page-title::after {
  inset-inline: 0;
  margin-inline: auto;
}

.page-content > h2,
.page-content h2 {
  margin-block: 2rem 0.85rem;
  color: var(--ui-text-headings);
  font-weight: 700;
  line-height: 1.35;
}

.page-content p,
.page-content li {
  color: var(--ui-text-secondary);
  line-height: 1.85;
}

.page-content a {
  color: var(--ui-primary);
  text-decoration-color: rgba(var(--ui-accent-rgb), 0.7);
  text-underline-offset: 0.22em;
}

.page-content a:hover {
  color: var(--ui-primary-dark);
}

/* WooCommerce login / register forms: one card, one control width. */
.woocommerce form.login,
.woocommerce form.register,
.woocommerce .woocommerce-MyAccount-content,
.woocommerce .woocommerce-MyAccount-navigation {
  background: #fff;
  border: 1px solid var(--ui-border-light);
  border-radius: var(--pf-r-lg);
  box-shadow: var(--ui-elev-2);
}

.woocommerce form.login,
.woocommerce form.register {
  max-width: 520px;
  margin-inline: auto;
  padding: clamp(1.5rem, 3vw, 2.25rem);
}

.woocommerce form.login p,
.woocommerce form.register p {
  margin-block-end: 1rem;
}

.woocommerce form.login label,
.woocommerce form.register label {
  display: block;
  margin-block-end: 0.4rem;
  color: var(--ui-text-secondary);
  font-size: 0.9rem;
  font-weight: 600;
}

.woocommerce form.login input[type='text'],
.woocommerce form.login input[type='email'],
.woocommerce form.login input[type='password'],
.woocommerce form.register input[type='text'],
.woocommerce form.register input[type='email'],
.woocommerce form.register input[type='password'] {
  width: 100%;
}

.woocommerce form.login .form-row,
.woocommerce form.register .form-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.85rem;
}

.woocommerce form.login .woocommerce-form__label-for-checkbox,
.woocommerce form.register .woocommerce-form__label-for-checkbox {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  color: var(--ui-text-secondary);
  font-size: 0.9rem;
  font-weight: 500;
}

.woocommerce form.login .woocommerce-form__input-checkbox,
.woocommerce form.register .woocommerce-form__input-checkbox {
  margin: 0;
}

.woocommerce form.login button[type='submit'],
.woocommerce form.register button[type='submit'] {
  flex: 1 1 180px;
  width: auto;
}

.woocommerce .woocommerce-MyAccount-navigation {
  padding: 1.25rem;
  margin-block-end: 1.5rem;
}

.woocommerce .woocommerce-MyAccount-navigation ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.woocommerce .woocommerce-MyAccount-navigation a {
  display: inline-block;
  padding: 0.5rem 0.9rem;
  color: var(--ui-text-secondary);
  background: var(--ui-surface-secondary);
  border-radius: var(--pf-r-sm);
  text-decoration: none;
  transition: color var(--pf-dur) var(--pf-ease),
              background-color var(--pf-dur) var(--pf-ease);
}

.woocommerce .woocommerce-MyAccount-navigation a:hover,
.woocommerce .woocommerce-MyAccount-navigation .is-active a {
  color: #fff;
  background: var(--ui-primary);
}

/*
 * The account page centres its form card, so the page title centres with it.
 * Left over right-aligned on a 1440px screen the two read as unrelated.
 *
 * The heading gets `margin-inline: auto` because it is in normal flow and can be
 * centred that way. Its ::after is handled separately above -- auto inline
 * margins do nothing on an absolutely positioned box, so listing the pseudo here
 * alongside the heading only ever looked like it worked.
 */
.woocommerce-account .page-title {
  text-align: center;
  margin-inline: auto;
}

/* ==========================================================================
   13. RESPONSIVE CORRECTIONS
   ========================================================================== */

@media (max-width: 1023px) {
  .site-header-inner {
    min-height: 68px;
  }

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

@media (max-width: 767px) {
  .site-main > section {
    padding-block: var(--pf-band-tight);
  }

  .footer-top {
    grid-template-columns: minmax(0, 1fr);
  }

  /* Text must be able to shrink or long Arabic words overflow their card. */
  :where(h1, h2, h3, h4, .page-hero-title, .tm-section-title, .ab-heading) {
    overflow-wrap: break-word;
    word-break: normal;
  }

  .tm-home-faq-question,
  .tm-faq-question,
  .tm-sd-faq-item__question {
    padding: 1rem;
  }

  .tm-home-faq-answer,
  .tm-faq-answer,
  .tm-sd-faq-item__answer {
    padding: 0 1rem 1.15rem;
  }
}

@media (max-width: 479px) {
  .site-header-inner {
    min-height: 62px;
  }

  .site-logo img {
    max-height: 40px;
  }

  .tm-home-hero__content-inner {
    padding: 1.4rem;
  }

  .tm-home-faq-question > span:last-child,
  .tm-faq-icon {
    width: 30px;
    height: 30px;
    flex-basis: 30px;
  }
}

@media (max-width: 560px) {
  /*
   * Stat strips stay two-up. Collapsing a row of four figures into a single
   * column pushes the next section a full screen further down without making
   * any of the figures easier to read.
   */
  .tm-home-numbers__grid,
  .tm-home-trust__grid,
  .tm-sd-stats__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ==========================================================================
   14. PACKAGE + SERVICE ARCHIVE CARDS
   ========================================================================== */

/*
 * `--card-tint` / `--card-edge` are declared as RGB channel triples
 * ("253 246 248") so they read correctly through `rgb(var(--card-tint))`, but
 * several card rules in consistency.css consume them as whole colour values
 * (`background: var(--card-tint, #faeef4)`). Because the variable *is* defined,
 * the fallback never applies and the whole `background` shorthand becomes
 * invalid at computed-value time, which resets the card to a transparent
 * surface. The archives therefore showed loose images and text inside a
 * hairline box instead of cards. Reading the token in its channel form restores
 * the intended tint, and the fallback covers cards that never set it.
 */
.packages-section .tm-home-package-card,
.services-archive .service-card,
.services-archive .tm-home-package-card,
.tm-home-packages .tm-home-package-card,
.tm-home-services .tm-home-service-card {
  background-color: rgb(var(--card-tint, 253 246 248));
  border-color: var(--card-edge, var(--ui-card-border));
  border-style: solid;
  border-width: 1px;
}

/*
 * The grids stretch their rows, but package cards opted out with
 * `align-self: start`, so cards in one row ended at different heights whenever
 * their content lengths differed. Service cards went the other way:
 * `height: calc(100% - 18px)` plus an 18px top pad on the grid left a dead
 * strip under every card and doubled the visual gap between rows.
 */
.packages-section .tm-home-package-card {
  align-self: stretch;
  height: auto;
}

/* The home grids carried the same `align-self: start` opt-out. */
.tm-home-packages .tm-home-package-card,
.tm-home-services .tm-home-service-card {
  align-self: stretch;
  height: auto;
}

.services-archive .service-card {
  display: flex;
  height: 100%;
}

.services-archive .services-grid {
  padding-block-start: 0;
}

/*
 * `.services-archive .service-card-body` was pinned to `display: block
 * !important`, which cancelled the column layout and with it the
 * `margin-block-start: auto` that pushes pricing and the CTA to the bottom of
 * the card. Cards in the same row showed their CTA at four different heights.
 */
.services-archive .service-card-body {
  display: flex !important;
  flex-direction: column;
  flex: 1 1 auto;
}

/* Match the inner rhythm of the two archives so the pages read as one system. */
.packages-section .tm-home-package-card__body {
  padding: var(--space-4) var(--ui-card-padding, 1.5rem) var(--ui-card-padding, 1.5rem);
  gap: var(--space-3);
}

/*
 * `main .tm-home-packages-grid` forced four columns with `!important` on every
 * viewport, so the packages archive ran four 300px cards at 1440 and two
 * ~150px cards at 375. Three columns reads correctly at desktop width, and a
 * single column is the only usable option on a phone.
 */
.packages-archive .tm-home-packages-grid {
  grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
}

@media (max-width: 900px) {
  .packages-archive .tm-home-packages-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  }
}

@media (max-width: 640px) {
  .packages-archive .tm-home-packages-grid {
    grid-template-columns: minmax(0, 1fr) !important;
  }

  .packages-archive .tm-package-card__terms {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
  }
}

/*
 * The home grids pinned two columns on every viewport, which leaves ~150px
 * cards on a 375px phone.
 */
@media (max-width: 640px) {
  .tm-home-packages .tm-home-packages-grid,
  .tm-home-services .tm-home-services-grid {
    grid-template-columns: minmax(0, 1fr) !important;
  }
}

.packages-section .tm-home-package-card:hover,
.services-archive .service-card:hover {
  border-color: var(--ui-primary);
}

/* ==========================================================================
   15. SINGLE PACKAGE / DETAIL PAGE
   ========================================================================== */

/*
 * The package hero paints the wine gradient from `.tm-sd-hero`, but its inner
 * elements carried no rules at all: the breadcrumb rendered as dark text on the
 * dark band, the badge lost its pill, and the three stat cards collapsed into
 * one full-width block with the icon stacked above the label. Everything below
 * restores the intended white-on-brand treatment.
 */
.tm-sd-hero .tm-sd-hero__breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  margin-block-end: 1.25rem;
  font-size: 0.875rem;
  color: rgba(255, 255, 255, 0.7);
}

.tm-sd-hero .tm-sd-hero__breadcrumb a {
  color: rgba(255, 255, 255, 0.86);
  text-decoration: none;
  transition: color var(--ui-transition, 200ms ease);
}

.tm-sd-hero .tm-sd-hero__breadcrumb a:hover,
.tm-sd-hero .tm-sd-hero__breadcrumb a:focus-visible {
  color: #fff;
  text-decoration: underline;
}

.tm-sd-hero .tm-sd-hero__breadcrumb .sep {
  opacity: 0.55;
}

.tm-sd-hero .tm-sd-hero__breadcrumb .current {
  color: #fff;
  font-weight: 600;
}

/*
 * The badge carries the service tagline, which can run long, so it is kept to a
 * single centred line: it reads as a compact marker above the title rather than
 * a second headline competing with it.
 */
.tm-sd-hero .tm-sd-hero__badge {
  display: inline-flex;
  align-items: center;
  max-width: min(100%, 34rem);
  gap: 0.45rem;
  margin-block-end: 0.9rem;
  padding: 0.3rem 0.75rem;
  border-radius: var(--pf-r-pill, 999px);
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.24);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.45;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tm-sd-hero .tm-sd-hero__badge svg {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  color: var(--ui-accent, #2fbfa0);
}

/*
 * Proof cards sit inside the hero container, between the excerpt and the
 * actions. `auto-fit` is used rather than a fixed column count because the
 * two templates emit different numbers of them (package 3, service up to 4),
 * and neither should be left with an orphaned card on a row of its own.
 */
.tm-sd-hero .tm-sd-hero__stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1rem;
  margin: 2rem 0;
  padding: 0;
  list-style: none;
}

.tm-sd-hero .tm-sd-stat-card {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  min-width: 0;
  /* base.css puts a margin-bottom on every bare `li`; the hero list is a grid,
     so the cell spacing has to come from the gap alone. */
  margin: 0;
  padding: 1rem 1.25rem;
  border-radius: var(--pf-r-lg, 16px);
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.16);
  text-align: start;
}

.tm-sd-hero .tm-sd-stat-card__icon {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: var(--ui-primary);
  color: #fff;
}

.tm-sd-hero .tm-sd-stat-card__icon svg {
  width: 22px;
  height: 22px;
}

.tm-sd-hero .tm-sd-stat-card__info {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  min-width: 0;
}

.tm-sd-hero .tm-sd-stat-card__label {
  font-size: 0.75rem;
  color: rgba(255, 255, 255, 0.72);
}

.tm-sd-hero .tm-sd-stat-card__value {
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.45;
  color: #fff;
  unicode-bidi: isolate;
}

/* Overview: framed artwork plus normalised body copy from the editor. */
.tm-sd-overview__content {
  min-width: 0;
}

.tm-sd-overview__title {
  margin: 0 0 1rem;
  font-size: clamp(1.35rem, 2.2vw, 1.9rem);
  line-height: 1.35;
  color: var(--ui-text-primary, #1f1416);
}

.tm-sd-overview__img-wrap,
.tm-sd-overview__placeholder {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: var(--ui-radius-xl, 24px);
  border: 1px solid var(--ui-border-light, rgba(20, 16, 15, 0.09));
  background: var(--ui-surface-tertiary, #f7f2f4);
  box-shadow: 0 24px 48px -32px rgba(31, 20, 22, 0.55);
}

.tm-sd-overview__img-wrap img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.tm-sd-overview__placeholder {
  display: grid;
  place-items: center;
  color: var(--ui-primary);
}

.tm-sd-overview__body {
  color: var(--ui-text-secondary, #4d4345);
  line-height: 1.9;
}

.tm-sd-overview__body > * + * {
  margin-block-start: 1rem;
}

.tm-sd-overview__body > :first-child {
  margin-block-start: 0;
}

.tm-sd-overview__body p {
  margin-block: 0;
}

.tm-sd-overview__body h2,
.tm-sd-overview__body h3,
.tm-sd-overview__body h4 {
  margin-block: 1.5rem 0.5rem;
  font-size: 1.125rem;
  line-height: 1.5;
  color: var(--ui-text-primary, #1f1416);
}

.tm-sd-overview__body ul,
.tm-sd-overview__body ol {
  padding-inline-start: 1.25rem;
  display: grid;
  gap: 0.5rem;
}

.tm-sd-overview__body img {
  max-width: 100%;
  height: auto;
  border-radius: var(--pf-r-md, 12px);
}

/*
 * The package trust bar — same component as `.tm-sd-trust` above, so it tracks
 * the same breakpoints rather than keeping a fixed four-column row that had no
 * mobile handling.
 */
.tm-sd-trust-bar {
  display: grid;
  grid-template-columns: repeat(4, auto);
  justify-content: space-between;
  align-items: stretch;
  gap: 1rem;
  margin-block-start: 2.5rem;
  padding-block-start: 2rem;
  border-block-start: 1px solid var(--ui-border-light, rgba(20, 16, 15, 0.09));
}

.tm-sd-trust-bar .tm-sd-trust-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
  padding: 1rem 1.25rem;
  border-radius: var(--pf-r-lg, 16px);
  background: var(--ui-surface-primary, #fff);
  border: 1px solid var(--ui-border-light, rgba(20, 16, 15, 0.09));
  box-shadow: 0 18px 36px -30px rgba(31, 20, 22, 0.5);
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1.5;
  color: var(--ui-text-secondary, #4d4345);
}

.tm-sd-trust-bar .tm-sd-trust-item svg {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  color: var(--ui-primary);
}

/* Plan cards: equal heights and a CTA pinned to the bottom of each card. */
.tm-pk-plans-grid {
  gap: clamp(1.25rem, 2vw, 2rem);
  align-items: stretch;
}

.tm-pk-plan-card {
  height: 100%;
}

.tm-pk-plan-card__features {
  flex: 1 1 auto;
}

.tm-pk-plan-card__footer {
  margin-block-start: auto;
}

/*
 * `.service-purchase-form` adds its own 28px inset. Inside a plan card that
 * already has 36/28/28 padding the form became a second floating box, so the
 * inset is dropped and only the internal rhythm is kept.
 */
.tm-pk-purchase-form {
  display: flex;
  flex-direction: column;
  gap: 0.875rem;
  margin: 0;
  padding: 0;
}

.tm-pk-purchase-form .payment-plan-option {
  padding: 0.75rem 0.875rem;
}

.tm-pk-purchase-form .payment-plan-options {
  gap: 0.5rem;
}

/*
 * `.tm-sd-benefit-card__title` had no rule, so it inherited the global `h3`
 * scale: 30px inside a 308px card, which produced a 210px-tall heading and
 * pushed the rest of the card out of view.
 */
.tm-sd-benefit-card__title {
  margin: 0 0 0.5rem;
  font-size: 1.0625rem;
  font-weight: 700;
  line-height: 1.5;
  color: var(--ui-text-primary, #1f1416);
  overflow-wrap: anywhere;
}

.tm-sd-benefits__grid,
.tm-sd-related__grid {
  gap: 1.25rem;
}

/*
 * The package template wraps its FAQs in `.tm-sd-faq__accordion` while the
 * service template uses `.tm-sd-faq__list`. Neither container had a layout, so
 * the accordion items sat flush against each other with no separation.
 */
.tm-sd-faq__accordion,
.tm-sd-faq__list {
  display: grid;
  gap: 0.75rem;
}

.tm-sd-faq__accordion .tm-sd-faq-item,
.tm-sd-faq__list .tm-sd-faq-item {
  transition: var(--pf-transition);
}

.tm-sd-faq__accordion .tm-sd-faq-item[open],
.tm-sd-faq__list .tm-sd-faq-item[open] {
  border-color: var(--ui-primary);
}

@media (max-width: 1024px) {
  .tm-sd-hero .tm-sd-hero__stats,
  .tm-sd-trust-bar {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* Below two columns the proof cards go full width and stack. */
@media (max-width: 560px) {
  .tm-sd-hero .tm-sd-hero__stats,
  .tm-sd-trust-bar {
    grid-template-columns: minmax(0, 1fr);
  }

  .tm-sd-trust-bar {
    gap: 0.6rem;
  }

  .tm-sd-hero .tm-sd-hero__breadcrumb {
    font-size: 0.8125rem;
  }
}

@media (max-width: 900px) {
  /*
   * The related grid drops to a single column here. At full width the 16/10
   * media frame grew to ~460px tall and pushed each card past 600px, so the
   * frame is capped and the cover crop absorbs the difference.
   */
  .tm-sd-related-card__media {
    max-height: 220px;
  }
}

/*
 * The hero badge used to be styled only under `.tm-pk-hero`, so the service
 * hero shipped an unstyled span. The rules above are now keyed to `.tm-sd-hero`
 * and both templates share one pill.
 */

/*
 * The service trust bar. `.tm-sd-trust` and the package's `.tm-sd-trust-bar`
 * are the same component under two names, so they are styled together below.
 *
 * Layout notes, both directions:
 *
 * - At desktop the four cards are 308px wide holding roughly 120px of content,
 *   which left each card hugging one edge with a wide empty gap. `auto` columns
 *   let each card shrink-wrap its label and `space-between` spreads them across
 *   the row, so the strip reads as four deliberate chips.
 *
 * - Neither variant had a single breakpoint, so at 375px every card was 76px
 *   wide with 40px of padding either side. That left ~36px for a 22px icon plus
 *   its gap, and the Arabic label wrapped onto three lines. Below 1024px the row
 *   becomes two columns and below 560px a single full-width column, where there
 *   is finally room for the icon and label on one line.
 */

.tm-sd-trust {
  display: grid;
  grid-template-columns: repeat(4, auto);
  justify-content: space-between;
  align-items: stretch;
  gap: 1rem;
  margin-block-start: 2.5rem;
  padding-block-start: 2rem;
  border-block-start: 1px solid var(--ui-border-light, rgba(20, 16, 15, 0.09));
}

.tm-sd-trust .tm-sd-trust__item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
  padding: 1rem 1.25rem;
  border-radius: var(--pf-r-lg, 16px);
  background: var(--ui-surface-primary, #fff);
  border: 1px solid var(--ui-border-light, rgba(20, 16, 15, 0.09));
  box-shadow: 0 18px 36px -30px rgba(31, 20, 22, 0.5);
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1.5;
  color: var(--ui-text-secondary, #4d4345);
}

.tm-sd-trust .tm-sd-trust__item svg {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  color: var(--ui-primary);
}

@media (max-width: 1024px) {
  .tm-sd-trust {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 560px) {
  .tm-sd-trust {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.6rem;
  }

  .tm-sd-trust .tm-sd-trust__item {
    padding: 0.9rem 1rem;
  }
}

/*
 * The service overview used `.tm-sd-section-title` while the package template
 * uses `.tm-sd-overview__title`. Both should share the same display size.
 */
.tm-sd-overview .tm-sd-section-title {
  margin: 0 0 1rem;
  font-size: clamp(1.35rem, 2.2vw, 1.9rem);
  line-height: 1.35;
  color: var(--ui-text-primary, #1f1416);
}

.tm-sd-overview__text {
  color: var(--ui-text-secondary, #4d4345);
  line-height: 1.9;
  margin: 0 0 1rem;
}

/* ==========================================================================
   15b. COMPACT PLAN CARDS
   ========================================================================== */

/*
 * The plan cards were correct structurally but the payment selector inside each
 * card was a tall vertical stack (each option ~102 px), which turned a 3-card
 * row into a 3,000 px wall of radios. The selector is now a compact horizontal
 * group, the card padding is reduced, and the CTA area is separated with a
 * hairline so the purchase button reads as the action.
 */
.tm-pk-plan-card {
  padding: 1.5rem !important;
}

.tm-pk-plan-card__header {
  margin-bottom: 0.75rem;
  min-height: 0;
}

.tm-pk-plan-card__price-box {
  padding: 1rem 1.25rem !important;
  margin-bottom: 1rem !important;
}

.tm-pk-plan-card__features {
  gap: 0.4rem !important;
  margin-bottom: 1rem !important;
}

.tm-pk-plan-card__features li {
  font-size: 0.84rem;
  line-height: 1.5;
}

.tm-pk-plan-card__more {
  margin-top: 0.5rem !important;
}

.tm-pk-plan-card__footer {
  padding-block-start: 1rem !important;
  border-block-start: 1px solid var(--ui-border-light, rgba(20, 16, 15, 0.09));
  margin-block-start: auto !important;
}

.tm-pk-purchase-form {
  display: flex;
  flex-direction: column;
  gap: 0.75rem !important;
  margin: 0;
  padding: 0 !important;
}

/*
 * Payment options inside a plan card. The card footer is narrow, so the options
 * are a 2x2 grid rather than one column, and each option stacks its name over
 * its amount — the earlier single-line version ran the two together into one
 * phrase ("دفعتان 2 × 1,250 ر.س") with a 7px gap and no hierarchy.
 *
 * `min-height` is reset because components.css puts a 72px floor on every
 * `.payment-plan-option`, which left 21px of text floating in an over-tall box
 * and made the whole selector look bloated.
 */
.tm-pk-purchase-form .payment-plan-options {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5rem !important;
}

.tm-pk-purchase-form .payment-plan-option {
  align-items: flex-start;
  gap: 0.55rem !important;
  min-width: 0;
  min-height: 0;
  padding: 0.65rem 0.7rem !important;
}

/*
 * The native control is hidden from view but stays focusable and in the
 * accessibility tree; the visible dot is drawn on the label. A 15px native
 * radio was effectively invisible against the tinted row.
 */
.tm-pk-purchase-form .payment-plan-radio {
  position: absolute;
  width: 1px;
  height: 1px;
  min-width: 0;
  min-height: 0;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
  accent-color: var(--ui-primary);
}

.tm-pk-purchase-form .payment-plan-option::before {
  content: "";
  flex: 0 0 16px;
  width: 16px;
  height: 16px;
  margin-block-start: 0.2rem;
  background: #fff;
  border: 1.5px solid var(--ui-border-light);
  border-radius: 50%;
  transition: border-color var(--pf-dur) var(--pf-ease),
              background-color var(--pf-dur) var(--pf-ease),
              box-shadow var(--pf-dur) var(--pf-ease);
}

.tm-pk-purchase-form .payment-plan-option:hover::before {
  border-color: rgba(var(--ui-primary-rgb), var(--pf-tint-3));
}

.tm-pk-purchase-form .payment-plan-option:has(input:checked)::before {
  background: var(--ui-primary);
  border-color: var(--ui-primary);
  /* Inset ring rather than a second element: reads as a filled dot. */
  box-shadow: inset 0 0 0 3px #fff;
}

.tm-pk-purchase-form .payment-plan-option:has(input:focus-visible)::before {
  outline: 2px solid var(--ui-primary);
  outline-offset: 3px;
}

/*
 * The wrapper between the option row and the label is dissolved with
 * `display: contents`. Left as a flex item it kept its own border-radius and
 * width, which pushed the label under the radio — the checked radio then drew
 * straight through the first line of text.
 */
.tm-pk-purchase-form .payment-plan-option-content {
  display: contents;
}

.tm-pk-purchase-form .payment-plan-label {
  display: flex;
  flex: 1;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.1rem !important;
  min-width: 0;
}

.tm-pk-purchase-form .payment-plan-name {
  color: var(--ui-text-headings);
  font-size: 0.83rem;
  font-weight: 700;
  line-height: 1.45;
}

.tm-pk-purchase-form .payment-plan-amount {
  color: var(--ui-text-secondary);
  font-size: 0.76rem;
  font-weight: 600;
  line-height: 1.45;
  font-variant-numeric: tabular-nums;
}

/*
 * The border tint alone is easy to miss beside three unselected rows, so the
 * chosen option also carries a ring and takes the brand colour.
 */
.tm-pk-purchase-form .payment-plan-option.is-selected {
  box-shadow: 0 0 0 2.5px rgba(var(--ui-primary-rgb), 0.14);
}

.tm-pk-purchase-form .payment-plan-option.is-selected .payment-plan-name,
.tm-pk-purchase-form .payment-plan-option:has(input:checked) .payment-plan-name {
  color: var(--ui-primary);
}

.tm-pk-purchase-form .payment-plan-option.is-selected .payment-plan-amount,
.tm-pk-purchase-form .payment-plan-option:has(input:checked) .payment-plan-amount {
  color: var(--ui-primary);
}

.tm-pk-purchase-form .payment-plan-selector-title {
  margin-bottom: 0.4rem !important;
  font-size: 0.78rem !important;
}

@media (max-width: 640px) {
  .tm-pk-purchase-form .payment-plan-option {
    min-width: 100%;
  }
}

/* ==========================================================================
   16b. SERVICE DESCRIPTION

   The description is stored as one long plain paragraph, so it rendered as a
   slab of text sitting straight on the tinted band with nothing above it to
   say what it was. It is now a labelled white panel with a readable measure.

   It previously shared a row with a sticky purchase card, but that card stands
   taller than the viewport, so pinning it clipped the payment options and the
   CTA out of reach. The purchase bar below is short enough to never need it.
   ========================================================================== */

.tm-sd-detail__grid {
  max-width: 860px;
  margin-inline: auto;
}

.tm-sd-detail__main {
  min-width: 0;
}

.single-tm_service .service-detail-content {
  /* The 68ch measure applied to the text itself; the panel now owns the width
     so the copy inside keeps the same readable line length. */
  max-width: none;
  margin-inline: 0;
  padding: clamp(1.5rem, 3.5vw, 2.75rem);
  background: #fff;
  border: 1px solid var(--ui-border-light);
  border-radius: var(--pf-r-xl);
  box-shadow: var(--ui-elev-1);
}

/* Prose rhythm inside the panel. */
.single-tm_service .service-content-body {
  max-width: 68ch;
  color: var(--ui-text-secondary);
  font-size: 1.03rem;
  line-height: 1.95;
}

.single-tm_service .service-content-body > :first-child {
  margin-block-start: 0;
}

.single-tm_service .service-content-body > :last-child {
  margin-block-end: 0;
}

.single-tm_service .service-content-body p {
  margin-block: 0 1.15rem;
}

.single-tm_service .service-content-body h2 {
  margin-block: 2.25rem 0.85rem;
  padding-block-end: 0.6rem;
  color: var(--ui-text-headings);
  border-block-end: 1px solid var(--ui-border-soft);
  font-size: clamp(1.3rem, 2.2vw, 1.6rem);
  font-weight: 800;
  line-height: 1.35;
}

.single-tm_service .service-content-body h3 {
  margin-block: 1.75rem 0.6rem;
  color: var(--ui-text-headings);
  font-size: clamp(1.1rem, 1.8vw, 1.28rem);
  font-weight: 700;
  line-height: 1.45;
}

.single-tm_service .service-content-body h4 {
  margin-block: 1.35rem 0.5rem;
  color: var(--ui-text-headings);
  font-size: 1.05rem;
  font-weight: 700;
}

.single-tm_service .service-content-body strong {
  color: var(--ui-text-headings);
  font-weight: 700;
}

.single-tm_service .service-content-body ul,
.single-tm_service .service-content-body ol {
  display: grid;
  gap: 0.55rem;
  margin-block: 0 1.15rem;
  padding-inline-start: 1.35rem;
}

.single-tm_service .service-content-body li {
  margin-block-end: 0;
  line-height: 1.85;
}

.single-tm_service .service-content-body a {
  color: var(--ui-primary);
  text-decoration-color: rgba(var(--ui-accent-rgb), 0.7);
  text-underline-offset: 0.22em;
}

.single-tm_service .service-content-body img,
.single-tm_service .service-content-body figure {
  max-width: 100%;
  border-radius: var(--pf-r-md);
}

.single-tm_service .service-content-body blockquote {
  margin-block: 1.5rem;
  margin-inline: 0;
  padding: 1rem 1.25rem;
  padding-inline-start: 1.25rem;
  color: var(--ui-text-secondary);
  background: var(--pf-wash-1);
  border-inline-start: 4px solid var(--ui-primary);
  border-radius: var(--pf-r-md);
}

.single-tm_service .service-content-body table {
  margin-block: 1.25rem;
  font-size: 0.95rem;
}

/* The delivery and requirement blocks divide the panel. */
.single-tm_service .tm-sd-delivery,
.single-tm_service .tm-sd-requirements {
  margin-block-start: 2rem;
  padding-block-start: 1.75rem;
  border-block-start: 1px solid var(--ui-border-soft);
}

/* ==========================================================================
   16. SERVICE PURCHASE BAR

   The service template used to render one plan card per payment tier, which
   borrowed the package grid: `repeat(auto-fit, minmax(300px, 1fr))` fitted
   three cards on a row and pushed the fourth onto a row of its own, so the
   tiers read as competing products rather than as ways to pay for one service.

   It then became one tall card. That card stood taller than the viewport, so
   when it was pinned as a sidebar the payment options and the CTA were clipped
   out of reach and could not be scrolled to. Laying the same content out as a
   row — price, payment methods, action — keeps the whole thing roughly 200px
   tall, so it fits on screen without any pinning.
   ========================================================================== */

.tm-sd-buy {
  padding-block: clamp(2rem, 4vw, 3rem) clamp(3rem, 6vw, 4.5rem);
}

.tm-sd-buy-title {
  margin: 0 0 1rem;
  color: var(--ui-text-headings);
  font-size: 1.15rem;
  font-weight: 800;
  line-height: 1.4;
  text-align: center;
}

/* Matched with the legacy class as well: `.single-tm_service
   .service-purchase-form` sets padding at the same specificity, and the bar
   already carries its own, so the two would otherwise stack. */
.tm-sd-buy-form,
.tm-sd-buy-form.service-purchase-form {
  width: 100%;
  margin-inline: 0;
  padding: 0;
}

.tm-sd-buy-bar {
  display: grid;
  grid-template-columns: minmax(220px, 250px) minmax(0, 1fr) minmax(240px, 285px);
  gap: clamp(1.25rem, 2.5vw, 2rem);
  align-items: start;
  padding: clamp(1.25rem, 2.5vw, 1.75rem);
  background: #fff;
  border: 1px solid var(--ui-border-light);
  border-radius: var(--pf-r-xl);
  box-shadow: var(--pf-lift);
}

/* --- Column 1: what it costs --- */

.tm-sd-buy-bar__price {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  min-width: 0;
}

.tm-sd-buy-bar__eyebrow {
  display: inline-flex;
  align-self: flex-start;
  padding: 0.25rem 0.7rem;
  color: var(--ui-primary);
  background: var(--pf-wash-1);
  border: 1px solid rgba(var(--ui-primary-rgb), var(--pf-tint-2));
  border-radius: var(--pf-r-sm);
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.7;
}

.tm-sd-buy-bar__name {
  margin: 0.35rem 0 0;
  color: var(--ui-text-headings);
  font-size: 1.05rem;
  font-weight: 800;
  line-height: 1.4;
}

.tm-sd-buy-bar__amount {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  margin-block-start: 0.35rem;
  padding-block-start: 0.75rem;
  border-block-start: 1px solid var(--ui-border-soft);
}

.tm-sd-buy-bar__amount-label {
  color: var(--ui-text-secondary);
  font-size: 0.78rem;
  font-weight: 600;
}

.tm-sd-buy-bar__amount-value {
  color: var(--ui-primary);
  font-size: clamp(1.6rem, 2.6vw, 2rem);
  font-weight: 800;
  line-height: 1.2;
  unicode-bidi: isolate;
}

.tm-sd-buy-bar__meta {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0.5rem 0 0;
  color: var(--ui-text-secondary);
  font-size: 0.82rem;
}

.tm-sd-buy-bar__meta svg {
  flex: 0 0 auto;
  color: var(--ui-accent-ink, var(--ui-accent));
}

/* --- Column 2: how to pay --- */

.tm-sd-buy-bar__options {
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

/*
 * Two columns of two rows. Four options stacked full width is what pushed the
 * card past the viewport; at this width they still read as distinct choices.
 */
.tm-sd-buy-bar__options .tm-sd-pay-options__list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.55rem;
}

.tm-sd-pay-options__title {
  display: block;
  margin-block-end: 0.55rem;
  padding: 0;
  color: var(--ui-text-headings);
  font-size: 0.85rem;
  font-weight: 700;
}

/*
 * components.css already turns `.payment-plan-option` into a bordered, padded
 * row, so the label is the box. The inner content wrapper is dissolved with
 * `display: contents` rather than given a border of its own — styling both is
 * what produced a box inside a box.
 */
.tm-sd-pay-option {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  min-height: 0;
  padding: 0.7rem 0.85rem;
  background: var(--ui-surface-primary);
  border: 1.5px solid var(--ui-border-light);
  border-radius: var(--pf-r-md);
  cursor: pointer;
  user-select: none;
  transition: border-color var(--pf-dur) var(--pf-ease),
              background-color var(--pf-dur) var(--pf-ease),
              box-shadow var(--pf-dur) var(--pf-ease);
}

.tm-sd-pay-option__box {
  display: contents;
}

.tm-sd-pay-option:hover {
  background: var(--pf-wash-1);
  border-color: rgba(var(--ui-primary-rgb), var(--pf-tint-3));
}

.tm-sd-pay-option.is-selected,
.tm-sd-pay-option:has(input:checked) {
  background: var(--pf-wash-1);
  border-color: var(--ui-primary);
  box-shadow: 0 0 0 3px rgba(var(--ui-primary-rgb), 0.12);
}

.tm-sd-pay-option:has(.payment-plan-radio:focus-visible) {
  outline: 2px solid var(--ui-primary);
  outline-offset: 3px;
}

/*
 * The radio stays in the accessibility tree and remains focusable, but the
 * visible control is `.tm-sd-pay-option__check`.
 */
.tm-sd-pay-option .payment-plan-radio {
  position: absolute;
  width: 1px;
  height: 1px;
  min-width: 0;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
  accent-color: var(--ui-primary);
}

.tm-sd-pay-option__check {
  position: relative;
  display: grid;
  place-items: center;
  flex: 0 0 18px;
  width: 18px;
  height: 18px;
  background: #fff;
  border: 1.5px solid var(--ui-border-light);
  border-radius: 50%;
  transition: border-color var(--pf-dur) var(--pf-ease),
              background-color var(--pf-dur) var(--pf-ease);
}

.tm-sd-pay-option__check > span {
  width: 9px;
  height: 9px;
  background: #fff;
  border-radius: 50%;
  opacity: 0;
  transform: scale(0.4);
  transition: opacity var(--pf-dur) var(--pf-ease),
              transform var(--pf-dur) var(--pf-ease-back);
}

.tm-sd-pay-option.is-selected .tm-sd-pay-option__check,
.tm-sd-pay-option:has(input:checked) .tm-sd-pay-option__check {
  background: var(--ui-primary);
  border-color: var(--ui-primary);
}

.tm-sd-pay-option.is-selected .tm-sd-pay-option__check > span,
.tm-sd-pay-option:has(input:checked) .tm-sd-pay-option__check > span {
  opacity: 1;
  transform: scale(1);
}

/* Name above amount: the columns are narrow, so a single line would wrap. */
.tm-sd-pay-option__text {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 0.05rem;
  min-width: 0;
  margin: 0;
}

.tm-sd-pay-option__name {
  color: var(--ui-text-headings);
  font-size: 0.9rem;
  font-weight: 700;
  line-height: 1.45;
}

.tm-sd-pay-option__amount {
  color: var(--ui-text-secondary);
  font-size: 0.8rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1.45;
}

.tm-sd-pay-option.is-selected .tm-sd-pay-option__name,
.tm-sd-pay-option:has(input:checked) .tm-sd-pay-option__name {
  color: var(--ui-primary);
}

.tm-sd-pay-option.is-selected .tm-sd-pay-option__amount,
.tm-sd-pay-option:has(input:checked) .tm-sd-pay-option__amount {
  color: var(--ui-primary);
}

/* --- Column 3: do it --- */

.tm-sd-buy-bar__action {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  min-width: 0;
}

.tm-sd-buy-bar__cta {
  min-height: 52px;
  border-radius: var(--pf-r-md);
}

.tm-sd-buy-bar__note {
  display: flex;
  align-items: flex-start;
  gap: 0.45rem;
  margin: 0;
  color: var(--ui-text-secondary);
  font-size: 0.76rem;
  line-height: 1.6;
}

.tm-sd-buy-bar__note svg {
  flex: 0 0 auto;
  margin-block-start: 0.15rem;
  color: var(--ui-accent-ink, var(--ui-accent));
}

/* Custom installment amount. */
.tm-sd-buy-bar__action .tm-custom-installment {
  padding: 0.75rem 0.85rem;
  background: var(--ui-surface-secondary);
  border: 1px solid var(--ui-border-soft);
  border-radius: var(--pf-r-md);
}

.tm-sd-buy-bar__action .tm-custom-installment > label {
  display: block;
  margin-block-end: 0.45rem;
  color: var(--ui-text-headings);
  font-size: 0.8rem;
  font-weight: 700;
}

.tm-sd-buy-bar__action .tm-custom-installment__row {
  position: relative;
  display: flex;
  align-items: center;
}

.tm-sd-buy-bar__action .tm-custom-installment__row input {
  flex: 1 1 auto;
  width: 100%;
  min-width: 0;
  padding-inline-end: 3.75rem;
  font-weight: 600;
}

.tm-sd-buy-bar__action .tm-custom-installment__currency {
  position: absolute;
  inset-inline-end: 0.75rem;
  color: var(--ui-text-secondary);
  font-size: 0.78rem;
  font-weight: 700;
  pointer-events: none;
}

.tm-sd-buy-bar__action .tm-custom-installment__row input.is-invalid {
  border-color: #c0392b;
  box-shadow: 0 0 0 3px rgba(192, 57, 43, 0.14);
}

/* The unavailable state matches the bar's measure. */
.tm-sd-buy .service-unavailable {
  max-width: 640px;
  margin-inline: auto;
  background: #fff;
  border: 1px solid var(--ui-border-light);
  border-radius: var(--pf-r-xl);
  box-shadow: var(--ui-elev-1);
}

/* Two columns until tablet. The action column spans the full width beneath
   them and keeps its own stacking — laying it out as a row overflowed the card
   once `ab-btn--full` set the CTA to width:100% beside a 100%-wide input. */
@media (max-width: 1024px) {
  .tm-sd-buy-bar {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }

  .tm-sd-buy-bar__action {
    grid-column: 1 / -1;
  }

  .tm-sd-buy-bar__cta {
    width: 100%;
  }
}

@media (max-width: 700px) {
  .tm-sd-buy-bar {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 480px) {
  .tm-sd-buy-bar__options .tm-sd-pay-options__list {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media print {
  .site-header,
  .site-footer,
  .mobile-nav,
  .tm-mobile-menu,
  .tm-pagination,
  .services-pagination {
    display: none !important;
  }

  body {
    background: #fff;
    color: #000;
  }
}
/* ==========================================================================
   17. HOME — WHY SECTION, CLIENT LOGOS, TESTIMONIAL MARKS

   The "why" section shipped a two-column grid with only the first column
   filled, so half the row was empty. Its visual markup had been dropped while
   the styles for it stayed behind, which is why `.tm-home-about__visual` and
   friends are referenced here rather than redefined.
   ========================================================================== */

/* ---------- Why: the system diagram ---------- */

/*
 * consistency.css collapsed this grid to one column as a workaround for the
 * visual being absent, which left half the row empty. With the visual restored
 * the two-column track is correct again — but capped, because a 1fr column at
 * full container width made the square panel 1280px tall.
 */
.tm-home-about__grid {
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}

.tm-home-about__visual {
  position: relative;
  width: 100%;
  max-width: 460px;
  margin-inline: auto;
}

@media (max-width: 1024px) {
  .tm-home-about__grid {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
  }

  .tm-home-about__visual {
    max-width: 420px;
    margin-block-start: 0.5rem;
  }
}

/*
 * Two slow-drifting orbs sit behind the panel. They are decoration only, so
 * they are marked aria-hidden in the markup and ignored by the motion layer.
 */
.tm-home-about__orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(46px);
  pointer-events: none;
  z-index: 0;
}

.tm-home-about__orb--a {
  width: 260px;
  height: 260px;
  inset-block-start: -60px;
  inset-inline-end: -40px;
  background: rgba(var(--ui-primary-rgb), 0.28);
  animation: tm-drift-a 17s ease-in-out infinite;
}

.tm-home-about__orb--b {
  width: 220px;
  height: 220px;
  inset-block-end: -50px;
  inset-inline-start: -30px;
  background: rgba(var(--ui-accent-rgb), 0.3);
  animation: tm-drift-b 21s ease-in-out infinite;
}

@keyframes tm-drift-a {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(-26px, 30px, 0) scale(1.12); }
}

@keyframes tm-drift-b {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(24px, -26px, 0) scale(1.08); }
}

.tm-home-about__image {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  height: auto;
  aspect-ratio: 1 / 1;
  padding: clamp(1.5rem, 4vw, 3rem);
  background:
    radial-gradient(120% 120% at 50% 0%, rgba(255, 255, 255, 0.96), rgba(247, 247, 248, 0.86));
  border: 1px solid #dedee2;
  border-radius: 22px;
  box-shadow: 0 34px 70px -44px rgba(24, 24, 27, 0.42);
  overflow: hidden;
}

.tm-sysmap__svg {
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* Gradient stops are styled here rather than in the markup, so the diagram
   follows the palette instead of carrying frozen hex values. */
.tm-sysmap__ring-stop:first-of-type {
  stop-color: var(--ui-primary);
  stop-opacity: 0.55;
}

.tm-sysmap__ring-stop:last-of-type {
  stop-color: var(--ui-accent);
  stop-opacity: 0.35;
}

/* Rings and spokes draw themselves in once, when scrolled to. */
.tm-sysmap__rings circle {
  fill: none;
  stroke: url(#tmSysRing);
  stroke-width: 1.25;
  stroke-dasharray: 3 7;
  opacity: 0;
  transform-origin: 210px 210px;
  animation: tm-ring-in 1.1s cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
}

.tm-sysmap__rings circle:nth-child(2) { animation-delay: 0.15s; }
.tm-sysmap__rings circle:nth-child(3) { animation-delay: 0.3s; }

@keyframes tm-ring-in {
  from { opacity: 0; transform: scale(0.82) rotate(-14deg); }
  to   { opacity: 1; transform: none; }
}

.tm-sysmap__spokes line {
  stroke: rgba(var(--ui-primary-rgb), 0.4);
  stroke-width: 1.25;
  stroke-dasharray: 4 6;
  opacity: 0;
  animation: tm-spoke-in 0.7s ease-out forwards;
}

.tm-sysmap__spokes line:nth-child(2) { animation-delay: 0.35s; }
.tm-sysmap__spokes line:nth-child(3) { animation-delay: 0.45s; }
.tm-sysmap__spokes line:nth-child(4) { animation-delay: 0.55s; }

@keyframes tm-spoke-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.tm-sysmap__core circle {
  fill: #fff;
  stroke: var(--ui-primary);
  stroke-width: 1.5;
  transform-origin: 210px 210px;
  animation: tm-core-pulse 4.5s ease-in-out infinite;
}

@keyframes tm-core-pulse {
  0%, 100% { transform: scale(1);    filter: drop-shadow(0 6px 14px rgba(var(--ui-primary-rgb), 0.18)); }
  50%      { transform: scale(1.045); filter: drop-shadow(0 10px 22px rgba(var(--ui-primary-rgb), 0.3)); }
}

.tm-sysmap__core-label {
  fill: #18181b;
  font-size: 15px;
  font-weight: 800;
}

.tm-sysmap__core-sub {
  fill: #8a8a92;
  font-size: 11px;
  font-weight: 600;
}

/* Each node floats on its own offset so the ring never looks rigid. */
.tm-sysmap__node circle {
  fill: #fff;
  stroke: rgba(var(--ui-primary-rgb), 0.32);
  stroke-width: 1.25;
  transform-box: fill-box;
  transform-origin: center;
  animation: tm-node-float 5.5s ease-in-out infinite;
}

.tm-sysmap__node text {
  fill: #3d3d45;
  font-size: 11px;
  font-weight: 700;
}

.tm-sysmap__node[data-node="2"] { animation-delay: 0.7s; }
.tm-sysmap__node[data-node="3"] { animation-delay: 1.4s; }
.tm-sysmap__node[data-node="4"] { animation-delay: 2.1s; }

@keyframes tm-node-float {
  0%, 100% { transform: translateY(0);    stroke: rgba(var(--ui-primary-rgb), 0.32); }
  50%      { transform: translateY(-6px); stroke: rgba(var(--ui-primary-rgb), 0.62); }
}

/* Badge overlaps the panel edge, as the original design intended. */
.tm-home-about__badge {
  position: absolute;
  inset-block-end: 26px;
  inset-inline-start: -24px;
  z-index: 2;
  width: 148px;
  padding: 18px 20px;
  background: var(--ui-primary, #0fa96b);
  color: #fff;
  border-radius: 14px;
  box-shadow: 0 18px 44px rgba(15, 169, 107, 0.28);
  animation: tm-badge-bob 6s ease-in-out infinite;
}

@keyframes tm-badge-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-9px); }
}

/* ---------- Client logo strip ---------- */

.tm-home-clients {
  padding-block: clamp(2.5rem, 5vw, 4rem);
  background: #fff;
  border-block: 1px solid #ececef;
  overflow: hidden;
}

/*
 * Space on both sides of the label: the top clears the tools grid above, the
 * bottom separates it from the logo track. The section's own padding-block is
 * applied around the container, so this margin is additive to it.
 *
 * The selector carries `.tm-home-clients` on purpose. layout.css sets
 * `.tm-homepage p { margin-top: 0 }`, which is (0,1,1) and beats a bare
 * `.tm-home-clients__label` at (0,1,0) -- the top margin was being zeroed out
 * no matter how professional.css loaded. Qualifying raises this to (0,2,0).
 */
.tm-home-clients .tm-home-clients__label {
  margin: clamp(1.5rem, 3vw, 2.5rem) 0 clamp(2rem, 3.5vw, 3rem);
  color: #8a8a92;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-align: center;
}

/*
 * The label sits inside .container while the track below it is full-bleed, so on
 * a wide screen the two centre lines do not agree and the heading reads as
 * off-centre. Matching the track's own box puts it back over the strip.
 */
[dir="rtl"] .tm-home-clients .tm-home-clients__label {
  padding-inline: clamp(0.75rem, 1.5vw, 1.25rem);
}

.tm-home-clients__viewport {
  display: flex;
  gap: 0;
  width: 100%;
  overflow: hidden;
  /* Edge fades so items enter and leave instead of being clipped. */
  -webkit-mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
}

.tm-home-clients__track {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: clamp(1rem, 3vw, 2.5rem);
  margin: 0;
  padding: 0 clamp(0.75rem, 1.5vw, 1.25rem);
  list-style: none;
  animation: tm-marquee 38s linear infinite;
}

.tm-home-clients__viewport:hover .tm-home-clients__track {
  /* Pausing on hover keeps the strip readable rather than constantly moving. */
  animation-play-state: paused;
}

@keyframes tm-marquee {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-100%, 0, 0); }
}

/*
 * In RTL the track is laid out from the right, so sliding it to -100% walks it
 * off the wrong edge and leaves a gap before the second copy arrives. The
 * pair has to travel right instead, which is the same loop mirrored: the second
 * track trails the first and hands off at the right edge.
 */
@keyframes tm-marquee-rtl {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(100%, 0, 0); }
}

[dir="rtl"] .tm-home-clients__track {
  animation-name: tm-marquee-rtl;
}

.tm-home-clients__item {
  margin: 0;
  flex: 0 0 auto;
}

.tm-home-clients__logo {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.6rem 1.1rem;
  color: #6b6b73;
  background: #fafafb;
  border: 1px solid #ececef;
  border-radius: 999px;
  white-space: nowrap;
  transition: color 220ms ease, border-color 220ms ease, background-color 220ms ease;
}

/* The generated marks carry their own wordmark, so the pill is only a frame. */
.tm-home-clients__logo img {
  display: block;
  width: auto;
  height: 42px;
  object-fit: contain;
}

@media (hover: hover) and (pointer: fine) {
  .tm-home-clients__item:hover .tm-home-clients__logo {
    color: var(--ui-primary, #0fa96b);
    background: #fff;
    border-color: rgba(var(--ui-primary-rgb), 0.35);
  }
}

/* ---------- Testimonial company marks ---------- */

.tm-home-testimonial {
  position: relative;
  display: flex;
  flex-direction: column;
}

.tm-home-testimonial__mark {
  display: block;
  width: 56px;
  height: 56px;
  margin-block-end: 1.1rem;
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 10px 24px -14px rgba(24, 24, 27, 0.5);
}

.tm-home-testimonial__mark img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The generated portrait fills the tile, so no overlay is needed any more. */
.tm-home-testimonial__mark img {
  border-radius: 0;
}

/* ==========================================================================
   Reduced motion

   The loops above run forever, so they are stopped outright here rather than
   left to the JS layer, which only governs the scroll reveals.
   ========================================================================== */

/* The badge is meant to break the panel edge, but a negative offset pushes it
   past a narrow viewport. `inset-inline-start` is the right edge in RTL, so a
   positive value tucks it inward while keeping the overlap. This must sit
   AFTER the base rule above: at equal specificity a later rule wins, and
   placed before it this block was silently overridden. */
@media (max-width: 640px) {
  .tm-home-about__badge {
    inset-inline-start: 14px;
    inset-block-end: 14px;
    width: 132px;
    padding: 14px 16px;
  }

  .tm-home-about__badge strong {
    font-size: 26px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .tm-home-about__orb,
  .tm-sysmap__rings circle,
  .tm-sysmap__spokes line,
  .tm-sysmap__core circle,
  .tm-sysmap__node circle,
  .tm-home-about__badge,
  .tm-home-clients__track {
    animation: none !important;
  }

  .tm-sysmap__rings circle,
  .tm-sysmap__spokes line {
    opacity: 1 !important;
    transform: none !important;
  }

  .tm-home-clients__viewport {
    overflow-x: auto;
    -webkit-mask-image: none;
    mask-image: none;
  }
}

/* ==========================================================================
   18. ABOUT — built-in artwork

   The figures use images generated by tools/generate-assets.py and resolved
   through trendmix_theme_image(), so no file path is written into the template.
   ========================================================================== */

.ab-figure {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}

.ab-figure__img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--pf-r-lg);
  background: var(--ui-surface-tertiary);
  box-shadow: var(--pf-lift);
}

.ab-figure--tall {
  margin-block-end: 1.25rem;
}

.ab-figure--tall .ab-figure__img {
  aspect-ratio: 1 / 1;
  max-height: 320px;
}

.ab-figure__caption {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.ab-figure__caption strong {
  color: var(--ui-text-headings);
  font-size: 1rem;
  font-weight: 800;
}

.ab-figure__caption span {
  color: var(--ui-text-secondary);
  font-size: 0.9rem;
  line-height: 1.75;
}

/* --- Gallery grid --- */

.ab-gallery {
  padding-block: clamp(3rem, 6vw, 5rem);
}

.ab-gallery__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.5rem, 3vw, 2.5rem);
}

/* The wide tile carries the team board and spans the full row. */
.ab-figure--wide {
  grid-column: 1 / -1;
}

.ab-figure--wide .ab-figure__img {
  aspect-ratio: 21 / 9;
}

/* --- People --- */

.ab-people {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1rem;
  margin: clamp(2rem, 4vw, 3rem) 0 0;
  padding: 0;
  list-style: none;
}

.ab-person {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  margin: 0;
  padding: 0.85rem 1rem;
  background: var(--ui-surface-primary);
  border: 1px solid var(--ui-border-light);
  border-radius: var(--pf-r-lg);
}

.ab-person__photo {
  display: block;
  flex: 0 0 46px;
  width: 46px;
  height: 46px;
  border-radius: 12px;
  overflow: hidden;
}

.ab-person__photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.ab-person__role {
  color: var(--ui-text-headings);
  font-size: 0.9rem;
  font-weight: 700;
  line-height: 1.5;
}

@media (max-width: 900px) {
  .ab-gallery__grid {
    grid-template-columns: minmax(0, 1fr);
  }

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

@media (max-width: 520px) {
  .ab-people {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ==========================================================================
   19. SECTION HEADINGS

   Most headings on the page already split the line and accent the phrase that
   carries the meaning (`<span class="text-accent">`). The testimonials heading
   was a single 40px string in the heading token, which reads as one heavy black
   block next to a small green eyebrow.

   `.text-accent` resolves to --color-accent, so the accent phrase follows the
   palette automatically.
   ========================================================================== */

.tm-home-testimonials__title .text-accent {
  color: var(--ui-primary);
}

/*
 * The audit panel's list inherited the light-on-dark text colour from the page
 * default. Its <li> children set their own colour, so nothing was visibly
 * wrong, but any text added directly to the list would have been invisible on
 * the dark surface.
 */
.tm-home-audit__points {
  color: rgba(255, 255, 255, 0.9);
}
