/*
Theme Name: DealerPro
Theme URI: https://dealerpro.theme
Author: DealerPro
Author URI: https://dealerpro.theme
Description: Professional dealership WordPress theme supporting Heavy Equipment, Modern Cars and Classic & Collector Cars via a one-time industry choice in the setup wizard. Fully tokenised stylesheet with three swappable visual skins, built-in inventory management, shipping pages, CF7 integration, 5-step setup wizard with industry switch.
Version: 3.7.7
Requires at least: 6.0
Tested up to: 6.7
Requires PHP: 8.0
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: dealerpro
Tags: dark, automotive, dealer, listings, one-page, custom-logo
*/

/* ══════════════════════════════════════════════
   CSS VARIABLES
   ══════════════════════════════════════════════ */
:root {
  /* ─── Accent / CTA (admin-customisable in the real theme) ─── */
  --dp-accent: #49b857;
  --dp-accent-dark: #2e7d32;
  --dp-accent-soft: color-mix(in srgb, var(--dp-accent) 10%, transparent);
  --dp-accent-border: color-mix(in srgb, var(--dp-accent) 28%, transparent);
  --dp-accent-glow: color-mix(in srgb, var(--dp-accent) 12%, transparent);
  --dp-accent-text: #ffffff;
  --dp-accent-fg: #ffffff;
  --dp-cta: #ff6f00;
  --dp-cta-dark: #e55d00;
  --dp-cta-soft: color-mix(in srgb, var(--dp-cta) 10%, transparent);
  --dp-cta-fg: #ffffff;

  /* ─── Form rhythm — the ONE place the vertical spacing of every form on
         the site is set. --dp-form-label-gap must stay SMALLER than
         --dp-form-gap: a label has to sit closer to the field it names than
         to the field above it, which is the defect the client reported.
         These are layout, not paint, so the skins must not redefine them. ─── */
  --dp-form-gap: 18px;        /* one field block → the next */
  --dp-form-label-gap: 6px;   /* a label → the field it names */

  /* ─── Surfaces & text ─── */
  --dp-bg: #050505;
  --dp-bg-card: #101010;
  --dp-bg-card-2: #0b0b0b;
  --dp-bg-input: #0d0d0d;
  --dp-text: #ffffff;
  --dp-text-soft: rgba(255, 255, 255, 0.76);
  --dp-text-muted: rgba(255, 255, 255, 0.58);
  --dp-text-faint: rgba(255, 255, 255, 0.38);
  --dp-border: rgba(255, 255, 255, 0.07);
  --dp-border-input: rgba(255, 255, 255, 0.10);

  /* ─── Typography ─── */
  --dp-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans,
             Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
  --dp-font-heading: var(--dp-font);
  --dp-font-ui: var(--dp-font);
  --dp-font-numeric: var(--dp-font);
  --dp-font-quote: var(--dp-font);
  --dp-font-feature-settings: normal;
  --dp-font-variant-numeric: normal;

  --dp-fw-medium: 500;
  --dp-fw-semibold: 600;
  --dp-fw-bold: 700;
  --dp-fw-extrabold: 800;
  --dp-fw-black: 900;

  /* ─── Shell / radii / motion ─── */
  --dp-shell: 1240px;
  --dp-transition: 0.25s ease;
  --dp-radius: 26px;
  --dp-radius-xs: 8px;          /* was declared twice (14px then 8px) — once now */
  --dp-radius-sm: 12px;         /* was declared twice (18px then 12px) — once now */
  --dp-radius-md: 16px;
  --dp-radius-lg: 24px;
  --dp-radius-input: 10px;
  --dp-radius-full: 999px;
  --dp-shadow: 0 24px 52px rgba(0, 0, 0, 0.34);
  --dp-shadow-hover: 0 24px 52px rgba(0, 0, 0, 0.40);

  /* ─── Global chrome ─── */
  --dp-skip-bg: var(--dp-accent);
  --dp-skip-fg: #ffffff;
  --dp-skip-radius: 0 0 8px 8px;
  --dp-skip-fs: 14px;
  --dp-skip-fw: var(--dp-fw-bold);
  --dp-skip-lh: 24px;                   /* 10 + 24 + 10 padding = 44px target */
  /* Focus indicator. It is an INSET ring, not an outline: outline paints
     outside the border box and skin-heavy.css puts a chamfer clip-path on
     .dp-btn--primary / .wpcf7-submit / .dp-header__call / .dp-mobile-nav__call /
     .dp-sl-reserve / .dp-btt, and clip-path discards
     everything painted outside that box — those controls had no visible
     keyboard focus indicator at all. Two concentric inset bands — one light,
     one dark — keep the indicator above 3:1 against ANY fill a skin can set
     (#ffffff in modern, #F2B705 in heavy, #1B1A17 / #6E2B2B in classic, the
     green gradient here): for any colour, the contrast of white against it
     multiplied by the contrast of black against it is 21, so at least one
     band always clears 4.5:1, and the two bands clear 21:1 against each other.
     Nothing paints an `outline` for focus any more. The old --dp-skip-outline
     / --dp-focus-outline / --dp-focus-outline-btn / --dp-focus-outline-cta /
     --dp-focus-radius / --dp-qvt-outline / --dp-btt-outline tokens had no
     consumer left after the conversion and were removed from this block and
     from all three skins with the rest of the unconsumed set.
     A skin that wants to tint the ring overrides --dp-focus-ring-color /
     --dp-focus-ring-color2 (or --dp-focus-ring outright). */
  --dp-focus-ring-w: 2px;               /* light band, measured from the edge  */
  --dp-focus-ring-w2: 4px;              /* dark band, ends here                */
  --dp-focus-ring-color: #ffffff;
  --dp-focus-ring-color2: #000000;
  --dp-focus-ring:
      inset 0 0 0 var(--dp-focus-ring-w)  var(--dp-focus-ring-color),
      inset 0 0 0 var(--dp-focus-ring-w2) var(--dp-focus-ring-color2);
  --dp-focus-ring-btn: var(--dp-focus-ring);
  --dp-focus-ring-cta: var(--dp-focus-ring);

  /* ─── Interaction states the theme never declared ─── */
  --dp-disabled-opacity: 0.55;
  --dp-disabled-grayscale: 0.35;
  --dp-pressed-opacity: 0.78;

  /* ── The hover veil ──
     3.2.0: two of the most-seen controls on the site — the sticky bar's Call
     and Request Info, which every phone visitor sees on every page — changed
     NOTHING at all on :hover, in all three skins. So did the hamburger.

     The veil is one translucent wash of the control's OWN ink, laid over
     whatever the control is painted with. currentColor is the reason it needs
     no per-skin tuning: a control's foreground is by definition legible
     against its own background, so a wash of it is by definition visible
     there too — on heavy's amber Call half (ink #14161A), on modern's near
     black Request Info half (ink #f4f6fb) and on classic's paper header
     alike, from ONE number. A fixed rgba(255,255,255,…) would vanish on the
     amber half; filter: brightness() has to be re-aimed per skin, which is
     the divergence --dp-pressed-opacity was introduced to remove.

     It is delivered as an INSET box-shadow with a flooding spread rather than
     as a background, because --dp-sticky-call-bg is a flat colour on heavy
     and classic and a linear-gradient on modern: a background-color would sit
     UNDER the gradient and never show. An inset shadow paints over any
     background, of any type, and over a background-image. It cannot move a
     box.

     Because it is a box-shadow it would otherwise replace the keyboard ring
     on a control that is both focused and hovered, exactly as the comment on
     :focus-visible warns. The two controls it reaches are therefore added to
     the :focus-visible list with their :focus-visible:hover twins. */
  --dp-hover-veil: color-mix(in srgb, currentColor 14%, transparent);
  --dp-hover-veil-shadow: inset 0 0 0 999px var(--dp-hover-veil);

  /* ─── Header ─── */
  --dp-header-bg: rgba(5, 5, 5, 0.96);
  --dp-header-border: 1px solid rgba(255, 255, 255, 0.07);
  --dp-header-blur: blur(12px);
  --dp-header-logo-color: #ffffff;
  --dp-header-logo-fs: 20px;
  --dp-header-logo-fw: var(--dp-fw-extrabold);
  --dp-header-logo-ls: -0.5px;
  --dp-header-link: rgba(255, 255, 255, 0.82);
  --dp-header-link-fs: 16px;
  --dp-header-link-fw: var(--dp-fw-semibold);
  --dp-header-link-ls: 0.2px;
  --dp-header-link-radius: 8px;
  --dp-header-link-hover: #ffffff;
  --dp-header-link-hover-bg: rgba(255, 255, 255, 0.06);
  --dp-header-link-active: var(--dp-accent);
  --dp-header-link-active-bg: color-mix(in srgb, var(--dp-accent) 8%, transparent);
  --dp-header-call-bg: linear-gradient(135deg, var(--dp-cta), var(--dp-cta-dark));
  --dp-header-call-fg: var(--dp-cta-fg);
  --dp-header-call-fs: 16px;
  --dp-header-call-fw: var(--dp-fw-extrabold);
  --dp-header-call-ls: 0.2px;
  --dp-header-call-icon: #ffffff;
  --dp-header-call-shadow: 0 8px 24px color-mix(in srgb, var(--dp-cta-dark) 34%, transparent);
  --dp-header-call-shadow-hover: 0 14px 32px color-mix(in srgb, var(--dp-cta-dark) 46%, transparent);
  --dp-hamburger-bar: #ffffff;
  --dp-hamburger-bar-radius: var(--dp-radius-full);

  /* ─── Mobile drawer ─── */
  --dp-mnav-bg: rgba(5, 5, 5, 0.98);
  --dp-mnav-border: 1px solid rgba(255, 255, 255, 0.07);
  --dp-mnav-blur: blur(12px);
  --dp-mnav-link: rgba(255, 255, 255, 0.82);
  --dp-mnav-link-hover: var(--dp-accent);
  --dp-mnav-link-fs: 16px;
  --dp-mnav-link-fw: var(--dp-fw-semibold);
  --dp-mnav-divider: 1px solid rgba(255, 255, 255, 0.04);
  --dp-mnav-call-bg: linear-gradient(135deg, var(--dp-cta), var(--dp-cta-dark));
  --dp-mnav-call-fg: var(--dp-cta-fg);
  --dp-mnav-call-shadow: 0 8px 24px color-mix(in srgb, var(--dp-cta-dark) 34%, transparent);

  /* ─── Sticky bar ─── */
  --dp-sticky-shadow: 0 -4px 24px rgba(0, 0, 0, 0.5);
  --dp-sticky-fg: #ffffff;
  --dp-sticky-fs: 16px;
  --dp-sticky-fs-sm: 15px;
  --dp-sticky-fw: var(--dp-fw-extrabold);
  --dp-sticky-ls: 0.3px;
  --dp-sticky-call-bg: var(--dp-accent);
  --dp-sticky-info-bg: #111111;
  --dp-sticky-info-border: 1px solid rgba(255, 255, 255, 0.08);

  /* ─── Page wash / section rhythm ─── */
  --dp-home-wash:
    radial-gradient(circle at 50% 0%,
      color-mix(in srgb, var(--dp-accent) 6%, transparent) 0%,
      color-mix(in srgb, var(--dp-accent) 2%, transparent) 16%,
      transparent 40%),
    linear-gradient(180deg, var(--dp-bg) 0%, var(--dp-bg) 30%, var(--dp-bg) 100%);
  --dp-hairline: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.05) 50%, transparent 100%);
  --dp-hairline-opacity: 0.55;

  /* ─── Panels ─── */
  --dp-card-bg: linear-gradient(180deg, var(--dp-bg-card) 0%, var(--dp-bg-card-2) 100%);
  --dp-card-border: 1px solid var(--dp-border);
  --dp-card-glow: radial-gradient(circle at top, var(--dp-accent-glow), transparent 62%);
  --dp-card-glow-opacity: 0.5;
  --dp-wrapper-bg: var(--dp-card-bg);
  --dp-wrapper-border: 1px solid var(--dp-border);
  --dp-wrapper-glow: radial-gradient(circle at top center, var(--dp-accent-glow), transparent 62%);
  --dp-wrapper-glow-opacity: 0.55;

  /* ─── Headings ─── */
  --dp-kicker-bg: var(--dp-accent-soft);
  --dp-kicker-border: 1px solid var(--dp-accent-border);
  --dp-kicker-color: #ffffff;
  --dp-kicker-fs: 12px;
  --dp-kicker-fw: var(--dp-fw-extrabold);
  --dp-kicker-ls: 1.7px;
  --dp-kicker-transform: uppercase;
  --dp-kicker-radius: var(--dp-radius-full);
  --dp-title-color: var(--dp-text);
  --dp-title-fs: clamp(34px, 5vw, 60px);
  --dp-title-fs-md: clamp(24px, 3.5vw, 38px);
  --dp-title-fs-sm: 30px;
  --dp-title-fs-section: clamp(28px, 4vw, 48px);
  --dp-title-fw: var(--dp-fw-black);
  --dp-title-lh: 1.02;
  --dp-title-lh-sm: 1.08;
  --dp-title-ls: -1.8px;
  --dp-title-ls-md: -1px;
  --dp-title-ls-sm: -0.9px;
  --dp-title-accent-color: var(--dp-accent);
  --dp-line-bg: linear-gradient(90deg, var(--dp-accent), var(--dp-accent-dark));
  --dp-line-radius: var(--dp-radius-full);
  --dp-line-shadow: 0 0 18px color-mix(in srgb, var(--dp-accent) 16%, transparent);
  --dp-subtitle-color: var(--dp-text-soft);
  --dp-subtitle-fs: 18px;
  --dp-subtitle-fs-md: 17px;
  --dp-subtitle-fs-sm: 15px;
  --dp-subtitle-lh: 1.85;
  --dp-subtitle-lh-sm: 1.78;
  --dp-note-color: var(--dp-text-muted);
  --dp-note-fs: 14px;
  --dp-note-lh: 1.7;
  --dp-highlight-color: var(--dp-accent);
  --dp-highlight-fw: var(--dp-fw-extrabold);

  /* ─── Buttons ─── */
  --dp-btn-radius: var(--dp-radius-full);
  --dp-btn-fs: 15px;
  --dp-btn-fs-sm: 14px;
  --dp-btn-fw: var(--dp-fw-extrabold);
  --dp-btn-ls: 0.2px;
  --dp-btn-border: none;
  --dp-btn-transition: transform .22s ease, box-shadow .22s ease, background .22s ease,
                       border-color .22s ease, color .22s ease;
  --dp-btn-primary-bg: linear-gradient(135deg, var(--dp-accent), var(--dp-accent-dark));
  --dp-btn-primary-fg: var(--dp-accent-fg);
  --dp-btn-primary-shadow: 0 14px 34px color-mix(in srgb, var(--dp-accent-dark) 34%, transparent);
  --dp-btn-primary-shadow-hover: 0 20px 44px color-mix(in srgb, var(--dp-accent-dark) 48%, transparent);
  --dp-btn-cta-bg: linear-gradient(135deg, var(--dp-cta), var(--dp-cta-dark));
  --dp-btn-cta-fg: var(--dp-cta-fg);
  --dp-btn-cta-shadow: 0 14px 34px color-mix(in srgb, var(--dp-cta) 32%, transparent);
  --dp-btn-cta-shadow-hover: 0 20px 44px color-mix(in srgb, var(--dp-cta) 46%, transparent);
  --dp-btn-ghost-bg: rgba(255, 255, 255, 0.04);
  --dp-btn-ghost-fg: #ffffff;
  --dp-btn-ghost-border: 1px solid rgba(255, 255, 255, 0.18);
  --dp-btn-ghost-blur: blur(6px);
  --dp-btn-ghost-bg-hover: rgba(255, 255, 255, 0.10);
  --dp-btn-ghost-border-hover: color-mix(in srgb, var(--dp-accent) 40%, rgba(255, 255, 255, 0.25));
  --dp-btn-shine: linear-gradient(120deg, transparent, rgba(255, 255, 255, 0.28), transparent);

  /* ─── Hero ─── */
  --dp-hero-overlay: linear-gradient(180deg, rgba(0, 0, 0, 0.78) 0%, rgba(0, 0, 0, 0.88) 100%);
  --dp-hero-title-color: #ffffff;
  --dp-hero-title-fs: clamp(38px, 5vw, 72px);
  --dp-hero-title-fw: var(--dp-fw-black);
  --dp-hero-title-ls: -2px;
  --dp-hero-title-lh: 1.0;
  --dp-hero-title-span-color: var(--dp-accent);
  --dp-hero-sub-color: rgba(255, 255, 255, 0.78);
  --dp-hero-sub-fs: clamp(16px, 1.6vw, 19px);
  --dp-hero-sub-lh: 1.7;
  --dp-hero-pill-bg: rgba(255, 255, 255, 0.06);
  --dp-hero-pill-border: 1px solid rgba(255, 255, 255, 0.14);
  --dp-hero-pill-color: rgba(255, 255, 255, 0.92);
  --dp-hero-pill-radius: var(--dp-radius-full);
  --dp-hero-pill-fs: 13px;
  --dp-hero-pill-fw: var(--dp-fw-bold);
  --dp-hero-pill-ls: 0.2px;
  --dp-hero-pill-bg-hover: rgba(255, 255, 255, 0.10);
  --dp-hero-pill-border-hover: color-mix(in srgb, var(--dp-accent) 40%, rgba(255, 255, 255, 0.20));
  --dp-hero-reveal: dpHeroReveal .7s cubic-bezier(.2, .8, .2, 1) backwards;
  --dp-hero-zoom: dpHeroZoom 8s ease-out forwards;

  /* ─── Stats band (full-bleed strip) ─── */
  --dp-statsband-bg: rgba(0, 0, 0, 0.35);
  --dp-statsband-border-top: 1px solid rgba(255, 255, 255, 0.06);
  --dp-statsband-border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  --dp-statsband-num-color: var(--dp-accent);
  --dp-statsband-num-fs: 42px;
  --dp-statsband-num-fs-sm: 34px;
  --dp-statsband-num-fw: var(--dp-fw-extrabold);
  --dp-statsband-num-ls: -0.5px;
  --dp-statsband-label-color: rgba(255, 255, 255, 0.55);
  --dp-statsband-label-fs: 11px;
  --dp-statsband-label-fw: var(--dp-fw-bold);
  --dp-statsband-label-ls: 1.5px;
  --dp-statsband-label-transform: uppercase;

  /* ─── Featured card ─── */
  --dp-fcard-bg: linear-gradient(180deg, rgba(16, 16, 16, 0.98) 0%, rgba(10, 10, 10, 0.98) 100%);
  --dp-fcard-border: 1px solid var(--dp-border);
  --dp-fcard-radius: var(--dp-radius-lg);
  --dp-fcard-media-radius: 24px 24px 0 0;
  --dp-fcard-transition: all .35s ease;
  --dp-fcard-border-hover: color-mix(in srgb, var(--dp-accent) 24%, transparent);
  --dp-fcard-shadow-hover: var(--dp-shadow-hover);
  --dp-fcard-img-bg: var(--dp-bg-card-2);
  --dp-fcard-img-transition: transform .5s ease;
  --dp-fcard-ph-color: rgba(255, 255, 255, 0.20);
  --dp-fcard-overlay: linear-gradient(180deg, transparent 50%, rgba(0, 0, 0, 0.75) 100%);
  --dp-fcard-badge-radius: var(--dp-radius-full);
  --dp-fcard-badge-fs: 11px;
  --dp-fcard-badge-fw: var(--dp-fw-extrabold);
  --dp-fcard-badge-ls: 0.8px;
  --dp-fcard-badge-transform: uppercase;
  --dp-fcard-year-bg: var(--dp-accent-soft);
  --dp-fcard-year-border: 1px solid color-mix(in srgb, var(--dp-accent) 22%, transparent);
  --dp-fcard-year-color: var(--dp-accent-text);
  --dp-fcard-year-radius: var(--dp-radius-full);
  --dp-fcard-year-fs: 11px;
  --dp-fcard-year-fw: var(--dp-fw-extrabold);
  --dp-fcard-title-color: #ffffff;
  --dp-fcard-title-fs: 18px;
  --dp-fcard-title-fw: var(--dp-fw-black);
  --dp-fcard-title-lh: 1.2;
  --dp-fcard-specs-color: rgba(255, 255, 255, 0.55);
  --dp-fcard-specs-fs: 12px;
  --dp-fcard-footer-border: 1px solid var(--dp-border);
  --dp-fcard-price-color: var(--dp-accent);
  --dp-fcard-price-fs: 22px;
  --dp-fcard-price-fw: var(--dp-fw-black);
  --dp-fcard-arrow-bg: var(--dp-accent-soft);
  --dp-fcard-arrow-radius: 50%;
  --dp-fcard-arrow-border: 1px solid color-mix(in srgb, var(--dp-accent) 22%, transparent);
  --dp-fcard-arrow-color: var(--dp-accent);
  --dp-fcard-arrow-transition: all .25s ease;
  --dp-fcard-arrow-bg-hover: var(--dp-accent);
  --dp-fcard-arrow-fg-hover: var(--dp-accent-fg);

  /* ─── Listing badges (six fixed variants) ─── */
  --dp-badge-hot-deal-bg: rgba(220, 38, 38, 0.90);
  --dp-badge-hot-deal-fg: #ffffff;
  --dp-badge-just-arrived-bg: color-mix(in srgb, var(--dp-accent) 90%, transparent);
  --dp-badge-just-arrived-fg: var(--dp-accent-fg);
  --dp-badge-featured-bg: rgba(37, 99, 235, 0.90);
  --dp-badge-featured-fg: #ffffff;
  --dp-badge-price-drop-bg: rgba(234, 179, 8, 0.90);
  --dp-badge-price-drop-fg: #000000;
  --dp-badge-pending-sale-bg: rgba(245, 158, 11, 0.95);
  --dp-badge-pending-sale-fg: #000000;
  --dp-badge-sold-bg: rgba(107, 114, 128, 0.90);
  --dp-badge-sold-fg: #ffffff;
  /* The seventh status, plus a fallback plate for any slug the variant rules
     do not name. The modifier is built free-form from the `badge` post meta
     (archive-listing.php, front-page.php, single-listing.php all
     do strtolower(str_replace(' ','-',$badge))), so anything outside the six
     above resolved to background-color rgba(0,0,0,0) and painted bare label
     ink straight onto the photograph. #7c3aed is the colour the admin badge
     map at inc/custom-fields.php already assigns to Reserved, and the hue
     of --dp-sl-reserved-bg, so the chip and the full-card RESERVED stamp read
     as one mark. */
  --dp-badge-reserved-bg: rgba(124, 58, 237, 0.90);
  --dp-badge-reserved-fg: #ffffff;
  /* --dp-badge-default-bg / -fg are deliberately NOT aliased here. An alias
     `var(--dp-badge-sold-bg)` in :root substitutes on <html>, where only this
     block is visible, so heavy and modern — which re-scope --dp-badge-sold-*
     at body.dp-skin--KEY — would fall back to THIS file's grey instead of
     their own sold plate. The consumer rule carries the chain instead, so it
     resolves on the badge and sees the skin's value. A skin that wants a
     distinct fallback declares --dp-badge-default-* in its own body scope
     (classic does) and that wins. */

  /* ─── Quick-view trigger ─── */
  --dp-qvt-bg: rgba(255, 255, 255, 0.96);
  --dp-qvt-fg: #111111;
  --dp-qvt-radius: var(--dp-radius-full);
  --dp-qvt-fs: 13px;
  --dp-qvt-fw: var(--dp-fw-extrabold);
  --dp-qvt-ls: 0.3px;
  --dp-qvt-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
  --dp-qvt-bg-hover: #ffffff;
  --dp-qvt-shadow-hover: 0 12px 32px rgba(0, 0, 0, 0.55);

  /* ─── Stat cards ─── */
  --dp-stat-transition: all .35s ease;
  --dp-stat-border-hover: color-mix(in srgb, var(--dp-accent) 24%, transparent);
  --dp-stat-shadow-hover: var(--dp-shadow-hover);
  --dp-stat-num-color: #ffffff;
  --dp-stat-num-fs: 46px;
  --dp-stat-num-fs-sm: 34px;
  --dp-stat-num-fw: var(--dp-fw-black);
  --dp-stat-suf-color: var(--dp-accent);
  --dp-stat-suf-fs: 40px;
  --dp-stat-suf-fs-sm: 28px;
  --dp-stat-suf-fw: var(--dp-fw-black);
  --dp-stat-label-color: rgba(255, 255, 255, 0.70);
  --dp-stat-label-fs: 14px;
  --dp-stat-label-fs-sm: 12px;
  --dp-stat-label-lh-sm: 1.4;

  /* ─── Story ─── */
  --dp-story-media-bg: var(--dp-bg-card-2);
  --dp-story-media-border: 1px solid var(--dp-border);
  --dp-story-media-radius: var(--dp-radius);
  --dp-story-media-shadow: var(--dp-shadow);
  --dp-story-quote-bg: linear-gradient(135deg,
      color-mix(in srgb, var(--dp-accent) 8%, transparent),
      color-mix(in srgb, var(--dp-accent) 2%, transparent));
  --dp-story-quote-border: 1px solid color-mix(in srgb, var(--dp-accent) 18%, transparent);
  --dp-story-quote-border-left: 3px solid var(--dp-accent);
  --dp-story-quote-radius: 0 14px 14px 0;
  --dp-story-quote-color: #ffffff;
  --dp-story-quote-fs: 20px;
  --dp-story-quote-lh: 1.6;
  --dp-story-quote-style: italic;
  --dp-story-quote-fw: var(--dp-fw-medium);
  --dp-story-quote-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%2349b857' opacity='0.8'%3E%3Cpath d='M7.17 4.73C4.9 5.76 3 7.94 3 10.5v7.75c0 1.24 1 2.25 2.25 2.25h5.5c1.24 0 2.25-1 2.25-2.25v-4.5c0-1.24-1-2.25-2.25-2.25H6.5c-.15-1.73 1.05-3.5 3.17-4.5L7.17 4.73zM17.17 4.73c-2.27 1.03-4.17 3.21-4.17 5.77v7.75c0 1.24 1 2.25 2.25 2.25h5.5c1.24 0 2.25-1 2.25-2.25v-4.5c0-1.24-1-2.25-2.25-2.25H16.5c-.15-1.73 1.05-3.5 3.17-4.5L17.17 4.73z'/%3E%3C/svg%3E");
  --dp-story-feat-color: #ffffff;
  --dp-story-feat-fs: 17px;
  --dp-story-feat-fw: var(--dp-fw-semibold);
  --dp-story-feat-icon-bg: var(--dp-accent-soft);
  --dp-story-feat-icon-radius: 50%;
  --dp-story-feat-icon-border: 1px solid color-mix(in srgb, var(--dp-accent) 18%, transparent);
  --dp-story-feat-icon-fs: 18px;
  --dp-story-feat-icon-sw: 2;   /* 36 / 18px -> a 1.5px keyline at this size */

  /* ─── Feature cards (Why Choose Us) ─── */
  --dp-feature-bg: var(--dp-bg-card);
  --dp-feature-border: 1px solid rgba(255, 255, 255, 0.06);
  --dp-feature-radius: var(--dp-radius-md);
  --dp-feature-transition: border-color .3s ease, transform .3s ease;
  --dp-feature-border-hover: color-mix(in srgb, var(--dp-accent) 28%, transparent);
  --dp-feature-glow: radial-gradient(circle at top, var(--dp-accent-glow), transparent 60%);
  --dp-feature-icon-bg: var(--dp-accent-soft);
  --dp-feature-icon-border: 1px solid var(--dp-accent-border);
  /* 3.2.0 repair — the feature-card icon is DECORATION, so it takes the ink
     ladder and not the action colour. This declaration was dead code until
     3.2.0: the box held a colour emoji, and a colour emoji ignores `color`
     completely. Replacing the emoji with an SVG brought it to life and printed
     nineteen decorative marks per page in the owner's action colour, which is
     the one thing the 3.2.0 rule forbids. --dp-text-soft is the rung the modern
     skin had already chosen for this token by hand. */
  --dp-feature-icon-color: var(--dp-text-soft);
  --dp-feature-icon-radius: var(--dp-radius-md);
  --dp-feature-icon-fs: 32px;
  --dp-feature-icon-sw: 1.125;   /* 36 / 32px -> a 1.5px keyline at this size */
  --dp-feature-title-color: #ffffff;
  --dp-feature-title-fs: 18px;
  --dp-feature-title-fw: var(--dp-fw-extrabold);
  --dp-feature-text-color: rgba(255, 255, 255, 0.65);
  --dp-feature-text-fs: 14px;
  --dp-feature-text-lh: 1.7;

  /* ─── Shipping ─── */
  --dp-ship-title-fs: clamp(32px, 4vw, 52px);
  --dp-ship-sub2-color: rgba(255, 255, 255, 0.60);
  --dp-ship-sub2-fs: 16px;
  --dp-ship-sub2-fs-sm: 15px;
  --dp-ship-sub2-lh: 1.8;
  --dp-ship-pill-bg: color-mix(in srgb, var(--dp-accent) 10%, transparent);
  --dp-ship-pill-border: 1px solid color-mix(in srgb, var(--dp-accent) 25%, transparent);
  --dp-ship-pill-color: var(--dp-accent-text);
  --dp-ship-pill-radius: var(--dp-radius-full);
  --dp-ship-pill-fs: 14px;
  --dp-ship-pill-fw: var(--dp-fw-bold);
  --dp-ship-pill-transition: all .25s;
  --dp-ship-pill-bg-hover: color-mix(in srgb, var(--dp-accent) 16%, transparent);
  --dp-ship-pill-border-hover: color-mix(in srgb, var(--dp-accent) 38%, transparent);
  --dp-ship-pill-icon: var(--dp-accent);
  --dp-ship-counter-color: var(--dp-accent);
  --dp-ship-counter-fs: clamp(52px, 7vw, 80px);
  --dp-ship-counter-fs-md: 52px;
  --dp-ship-counter-fw: var(--dp-fw-black);
  --dp-ship-counter-ls: -3px;
  --dp-ship-counter-lbl-color: rgba(255, 255, 255, 0.50);
  --dp-ship-counter-lbl-fs: 15px;
  --dp-ship-counter-lbl-fw: var(--dp-fw-medium);
  --dp-ship-step-bg: rgba(255, 255, 255, 0.02);
  --dp-ship-step-border: 1px solid var(--dp-border);
  --dp-ship-step-radius: var(--dp-radius-sm);
  --dp-ship-step-transition: all var(--dp-transition);
  --dp-ship-step-border-hover: color-mix(in srgb, var(--dp-accent) 28%, transparent);
  --dp-ship-step-bg-hover: color-mix(in srgb, var(--dp-accent) 4%, transparent);
  --dp-ship-step-icon-fs: 32px;
  /* The step-icon block's height. It used to have none: the block was the
     emoji's line box, and pinning it to what it already measured is what let
     the emoji be replaced without the card below it moving.
     42px is a MEASUREMENT, not a guess -- what this block renders at with NO
     skin file loaded (style.css alone, the emoji still in place), at 1440x900
     and at 390x844, three instances, same number every time. A site whose
     industry is still unset loads no skin, so this base value is reachable;
     without it that site's block would collapse to the SVG's 32px content box,
     10px shorter than before. Each skin overrides this with its own measured
     number. The rule that reads it also centres the SVG with display:flex --
     with the height pinned in every configuration that changes no box. */
  --dp-ship-step-icon-h: 42px;
  --dp-ship-step-icon-sw: 1.125;   /* 36 / 32px -> a 1.50px keyline at this size */
  --dp-ship-step-title-color: #ffffff;
  --dp-ship-step-title-fs: 20px;
  --dp-ship-step-title-fw: var(--dp-fw-black);
  --dp-ship-step-text-color: rgba(255, 255, 255, 0.65);
  --dp-ship-step-text-fs: 15px;
  --dp-ship-step-text-lh: 1.8;
  --dp-ship-note-color: rgba(255, 255, 255, 0.35);
  --dp-ship-note-fs: 13px;

  /* ─── Reviews ─── */
  --dp-review-bg: var(--dp-card-bg);
  --dp-review-border: 1px solid rgba(255, 255, 255, 0.07);
  --dp-review-radius: var(--dp-radius);
  --dp-review-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  --dp-review-transition: all .3s ease;
  --dp-review-glow: radial-gradient(circle at top, color-mix(in srgb, var(--dp-accent) 10%, transparent), transparent 60%);
  --dp-review-border-hover: color-mix(in srgb, var(--dp-accent) 28%, transparent);
  --dp-review-shadow-hover: 0 18px 38px rgba(0, 0, 0, 0.32);
  --dp-review-star-color: var(--dp-accent);
  --dp-review-star-shadow: drop-shadow(0 2px 4px color-mix(in srgb, var(--dp-accent) 40%, transparent));
  --dp-review-text-color: rgba(255, 255, 255, 0.82);
  --dp-review-text-fs: 15px;
  --dp-review-text-lh: 1.7;
  --dp-review-text-style: italic;
  --dp-review-foot-border: 1px solid rgba(255, 255, 255, 0.06);
  --dp-review-av-bg: var(--dp-accent);
  --dp-review-av-radius: 50%;
  --dp-review-av-fg: var(--dp-accent-fg);
  --dp-review-av-fs: 13px;
  --dp-review-av-fw: var(--dp-fw-extrabold);
  --dp-review-name-color: #ffffff;
  --dp-review-name-fs: 14px;
  --dp-review-name-fw: var(--dp-fw-extrabold);
  --dp-review-role-color: rgba(255, 255, 255, 0.5);
  --dp-review-role-fs: 12px;

  /* ─── Contact ─── */
  --dp-contact-item-bg: rgba(255, 255, 255, 0.02);
  --dp-contact-item-border: 1px solid rgba(255, 255, 255, 0.05);
  --dp-contact-item-radius: var(--dp-radius-sm);
  --dp-contact-item-transition: all .25s ease;
  --dp-contact-item-border-hover: color-mix(in srgb, var(--dp-accent) 24%, transparent);
  --dp-contact-item-bg-hover: color-mix(in srgb, var(--dp-accent) 5%, transparent);
  --dp-contact-icon-bg: var(--dp-accent-soft);
  --dp-contact-icon-border: 1px solid color-mix(in srgb, var(--dp-accent) 18%, transparent);
  --dp-contact-icon-radius: var(--dp-radius-xs);
  --dp-contact-icon-fs: 20px;
  --dp-contact-icon-sw: 1.8;   /* 36 / 20px -> a 1.5px keyline at this size */
  --dp-contact-label-color: var(--dp-accent-text);
  --dp-contact-label-fs: 12px;
  --dp-contact-label-fw: var(--dp-fw-extrabold);
  --dp-contact-label-ls: 1.4px;
  --dp-contact-label-transform: uppercase;
  --dp-contact-value-color: #ffffff;
  --dp-contact-value-fs: 16px;
  --dp-contact-value-fw: var(--dp-fw-bold);
  --dp-contact-value-hover: var(--dp-accent-text);
  --dp-contact-trust-bg: rgba(255, 255, 255, 0.02);
  --dp-contact-trust-border: 1px solid rgba(255, 255, 255, 0.05);
  --dp-contact-trust-radius: var(--dp-radius-lg);
  --dp-contact-trust-title-color: #ffffff;
  --dp-contact-trust-title-fs: 24px;
  --dp-contact-trust-title-fw: var(--dp-fw-black);
  --dp-contact-trust-pill-bg: color-mix(in srgb, var(--dp-accent) 8%, transparent);
  --dp-contact-trust-pill-border: 1px solid color-mix(in srgb, var(--dp-accent) 22%, transparent);
  --dp-contact-trust-pill-color: #ffffff;
  --dp-contact-trust-pill-radius: var(--dp-radius-full);
  --dp-contact-trust-pill-fs: 13px;
  --dp-contact-trust-pill-fw: var(--dp-fw-bold);
  --dp-contact-trust-pill-ls: 0.2px;
  --dp-contact-trust-pill-transition: all .25s ease;
  --dp-contact-trust-pill-bg-hover: color-mix(in srgb, var(--dp-accent) 14%, transparent);
  --dp-contact-trust-pill-tick: var(--dp-accent);
  --dp-contact-form-title-color: #ffffff;
  --dp-fs-contact-form-title: 28px;
  --dp-contact-form-sub-color: rgba(255, 255, 255, 0.68);
  --dp-fs-contact-form-sub: 16px;

  /* ─── Forms ─── */
  --dp-form-bg: var(--dp-bg-card);
  --dp-form-border: 1px solid rgba(255, 255, 255, 0.06);
  --dp-form-radius: var(--dp-radius-md);
  --dp-field-bg: #0a0a0a;
  --dp-field-border: 1px solid rgba(255, 255, 255, 0.10);
  /* Width half of --dp-field-border, so a label can be padded to the field's
     text edge. Any skin that changes the field border width must change this. */
  --dp-field-border-w: 1px;
  --dp-field-radius: var(--dp-radius-sm);
  --dp-field-color: #ffffff;
  --dp-field-fs: 15px;
  --dp-field-transition: border-color .2s ease, background .2s ease;
  --dp-field-border-focus: var(--dp-accent);
  --dp-field-bg-focus: #050505;
  --dp-label-color: rgba(255, 255, 255, 0.72);
  --dp-label-fs: 15px;   /* was 13; a field label is an instruction, not a caption. 15px is --dp-text-base and equals --dp-field-fs, so the label matches the answer it names. */
  --dp-label-fw: var(--dp-fw-bold);
  --dp-label-ls: 0.2px;
  --dp-submit-bg: linear-gradient(135deg, var(--dp-accent), var(--dp-accent-dark));
  --dp-submit-fg: var(--dp-accent-fg);
  --dp-submit-radius: var(--dp-radius-full);
  --dp-submit-shadow: 0 14px 34px color-mix(in srgb, var(--dp-accent-dark) 34%, transparent);

  /* ─── Quick-view modal ─── */
  --dp-qv-backdrop: rgba(0, 0, 0, 0.82);
  --dp-qv-backdrop-blur: blur(4px);
  --dp-qv-dialog-bg: #111111;                     /* live value (base.css mock-up used --dp-card-bg) */
  --dp-qv-dialog-border: 1px solid rgba(255, 255, 255, 0.10);  /* live value */
  --dp-qv-dialog-radius: var(--dp-radius);
  --dp-qv-close-bg: rgba(255, 255, 255, 0.10);    /* live value */
  --dp-qv-close-radius: 50%;
  --dp-qv-close-fg: #ffffff;
  --dp-qv-nav-bg: rgba(0, 0, 0, 0.55);
  --dp-qv-nav-radius: 50%;
  --dp-qv-nav-fg: #ffffff;
  --dp-qv-title-color: #ffffff;
  --dp-qv-title-fw: var(--dp-fw-black);
  --dp-qv-price-color: #ffffff;                   /* live value */
  --dp-qv-price-fs: 26px;
  --dp-qv-price-fw: var(--dp-fw-black);
  --dp-qv-desc-color: rgba(255, 255, 255, 0.55);  /* live value */
  --dp-qv-note-color: rgba(255, 255, 255, 0.25);  /* live value */
  --dp-qv-counter-bg: rgba(0, 0, 0, 0.62);
  --dp-qv-counter-fg: #ffffff;
  /* The two top corners took DIFFERENT radii - var(--dp-radius) on the left,
     a hard-coded 20px on the right - which is not something any skin asks for.
     Both now take the skin's own radius. Dormant today: all three skins set
     this token themselves, so nothing on this install reads the default; it is
     corrected so the fallback is not wrong for the next skin that does. */
  --dp-qv-sheet-radius: var(--dp-radius) var(--dp-radius) 0 0;

  /* ─── CF7 submit overlay ─── */
  --dp-overlay-bg: rgba(0, 0, 0, 0.75);
  --dp-overlay-blur: blur(6px);
  --dp-overlay-spinner-track: 4px solid rgba(255, 255, 255, 0.12);
  --dp-overlay-spinner-head: var(--dp-accent);
  --dp-overlay-spinner-radius: 50%;
  --dp-overlay-text-color: #ffffff;
  --dp-overlay-text-fs: 17px;
  --dp-overlay-text-fw: var(--dp-fw-bold);
  --dp-overlay-text-ls: 0.3px;
  --dp-overlay-title-color: #ffffff;
  --dp-overlay-title-fs: 22px;
  --dp-overlay-title-fs-sm: 19px;
  --dp-overlay-title-fw: var(--dp-fw-extrabold);
  --dp-overlay-msg-color: rgba(255, 255, 255, 0.85);
  --dp-overlay-msg-fs: 15px;
  --dp-overlay-msg-fs-sm: 14px;
  --dp-overlay-btn-radius: var(--dp-radius-input);
  --dp-overlay-btn-fs: 16px;
  --dp-overlay-btn-fs-sm: 15px;
  --dp-overlay-btn-fw: var(--dp-fw-bold);
  --dp-overlay-btn-call-bg: var(--dp-accent);
  --dp-overlay-btn-call-fg: #ffffff;
  --dp-overlay-btn-email-bg: var(--dp-cta);
  --dp-overlay-btn-email-fg: #ffffff;
  --dp-overlay-close-color: rgba(255, 255, 255, 0.7);
  --dp-overlay-close-hover: #ffffff;
  --dp-overlay-close-fs: 14px;
  --dp-overlay-close-fw: var(--dp-fw-semibold);
  --dp-overlay-title-ls: 0.2px;
  --dp-overlay-title-lh: 1.25;
  --dp-overlay-msg-lh: 1.5;
  --dp-overlay-btn-hover-filter: brightness(1.08);

  /* ─── Footer ─── */
  --dp-footer-bg: var(--dp-bg);
  --dp-footer-fg: #ffffff;
  --dp-footer-border-image: linear-gradient(90deg,
      transparent 0%,
      color-mix(in srgb, var(--dp-accent) 45%, transparent) 30%,
      color-mix(in srgb, var(--dp-accent) 45%, transparent) 70%,
      transparent 100%) 1;
  --dp-footer-divider: 1px solid color-mix(in srgb, var(--dp-accent) 10%, transparent);
  --dp-footer-divider-sm: 1px solid rgba(255, 255, 255, 0.05);
  --dp-footer-logo-opacity: 0.85;
  --dp-footer-logo-color: #ffffff;
  --dp-footer-logo-fs: 22px;
  --dp-footer-logo-fw: var(--dp-fw-extrabold);
  --dp-footer-desc-color: rgba(255, 255, 255, 0.52);
  --dp-footer-desc-fs: 14px;
  --dp-footer-desc-lh: 1.9;
  --dp-footer-title-color: #ffffff;
  --dp-footer-title-fs: 16px;
  --dp-footer-title-fw: var(--dp-fw-extrabold);
  --dp-footer-title-ls: 0.2px;
  --dp-footer-title-border: 2px solid var(--dp-accent);
  --dp-footer-link-color: rgba(255, 255, 255, 0.62);
  --dp-footer-link-fs: 15px;
  --dp-footer-link-fw: var(--dp-fw-medium);
  --dp-footer-link-hover: #ffffff;
  /* THIS ARROW STAYS A CHARACTER, AND HERE IS THE WORKING THAT SAYS SO.
     CSS `content` cannot hold an SVG, so the only way to draw this from
     inc/icons.php is mask-image + background-color. The question was whether
     such a mask could use THE TABLE'S OWN path data rather than a second copy
     of it in a data: URI. IT CAN: a data: URI built at render time from
     dp_icon_table()['arrow-right'] works, and it is geometry-neutral - with
     the ::after box pinned to the measured advance and line box of U+2192
     (10.875x15 modern, 12x15 classic, 14x17 heavy) every one of the seven
     footer links, every .dp-footer__links row, the footer box and
     document.body.scrollHeight came back byte-identical on all three skins.
     IT IS STILL NOT DONE, for a reason a geometry diff cannot see: the two
     arrows are not the same drawing. U+2192 in IBM Plex Sans, Lato and Barlow
     is long, thin and sits on the baseline; the table's arrow-right is short
     and heavy and is centred in a square box. Photographed side by side at 4x
     on all three skins, the swap plainly changes what a visitor sees in the
     footer of every page. Matching it would mean drawing a SECOND, long-thin
     arrow, which is the opposite of one-drawing-per-meaning.
     And the reason the icon table exists does not apply here anyway: U+2192
     is a text arrow, not a colour emoji. It already obeys CSS `color` and it
     already takes the token below, which is the whole thing an emoji could
     not do.
     (The other CSS content arrow, .dp-step-card__list li::before, has a
     shorter answer still - see the note there.) */
  --dp-footer-link-arrow: "→";
  --dp-footer-link-arrow-color: var(--dp-accent);
  --dp-footer-link-arrow-fs: 13px;
  --dp-footer-icon-bg: color-mix(in srgb, var(--dp-accent) 10%, transparent);
  --dp-footer-icon-border: 1px solid color-mix(in srgb, var(--dp-accent) 20%, transparent);
  --dp-footer-icon-radius: var(--dp-radius-input);
  --dp-footer-icon-fill: var(--dp-accent);
  --dp-footer-icon-bg-hover: color-mix(in srgb, var(--dp-accent) 18%, transparent);
  --dp-footer-icon-border-hover: color-mix(in srgb, var(--dp-accent) 40%, transparent);
  --dp-footer-contact-color: rgba(255, 255, 255, 0.72);
  --dp-footer-contact-fs: 14px;
  --dp-footer-contact-lh: 1.6;
  --dp-footer-contact-fw: var(--dp-fw-medium);
  --dp-footer-contact-hover: var(--dp-accent);
  --dp-footer-bottom-border: 1px solid rgba(255, 255, 255, 0.06);
  --dp-footer-copy-color: rgba(255, 255, 255, 0.38);
  --dp-footer-copy-fs: 14px;
  --dp-footer-dot-radius: 50%;
  --dp-footer-dot-bg: var(--dp-accent);

  /* ─── Reveal motion ─── */
  --dp-scroll-reveal-transition: all 0.9s cubic-bezier(0.22, 0.61, 0.36, 1);
  --dp-reveal-anim: dpRevealUp 0.9s cubic-bezier(0.22, 0.61, 0.36, 1) backwards;

  /* ══════════════════════════════════════════════════════════════════════
     LIVE-THEME-ONLY TOKENS — type scale.
     These exist in the shipped theme but not in base.css. The 17 companions
     here (--dp-space-1..20, --dp-text-xl..4xl, --dp-section-padding[-mobile])
     had no consumer, directly or through any var() chain, and were spacing and
     section-padding values a skin is not allowed to own, so they were deleted
     rather than wired. The five below are consumed and stay.
     ══════════════════════════════════════════════════════════════════════ */

  --dp-text-xs: 11px;
  --dp-text-sm: 13px;
  --dp-text-base: 15px;
  --dp-text-md: 16px;
  --dp-text-lg: 18px;

  /* ══════════════════════════════════════════════════════════════════════
     COMPONENT TOKENS ADDED WHILE TOKENISING style.css
     Every one carries the literal value the theme renders today.
     ══════════════════════════════════════════════════════════════════════ */

  /* ─── Button: dark / white variants ─── */
  --dp-btn-dark-bg: #1a1a1a;
  --dp-btn-dark-fg: #ffffff;
  --dp-btn-dark-border: 1px solid rgba(255, 255, 255, 0.12);
  --dp-btn-dark-bg-hover: #242424;
  --dp-btn-dark-border-hover: rgba(255, 255, 255, 0.22);
  /* 3.2.0 — .dp-btn--dark's keyline, as a box-shadow rather than a border.
     .dp-btn--dark is worn by exactly one control in the whole theme, the
     listing sidebar's "Make Inquiry", and that control also carries
     .dp-sl-btn-v2, whose `border: none` is declared later and wins — so
     --dp-btn-dark-border has never painted anything on the only element that
     has the class. An inset shadow reaches it, cannot be cancelled by
     `border: none`, and cannot move the box. `none` here: the unskinned base
     already separates dark (#1a1a1a) from cta (the accent gradient), so it
     needs no keyline. The two skins where the two collapsed do. */
  --dp-btn-dark-keyline: none;
  --dp-btn-white-bg: #ffffff;
  --dp-btn-white-bg-hover: #f5f5f5;
  --dp-btn-white-shadow-hover: 0 8px 24px rgba(255, 255, 255, 0.20);

  /* ─── Bare CF7 fields (.wpcf7-form, outside .dp-form-wrap) ─── */
  --dp-input-color: #ffffff;
  --dp-input-placeholder: rgba(255, 255, 255, 0.50);
  --dp-input-option-color: rgba(255, 255, 255, 0.85);
  --dp-input-option-empty-color: rgba(255, 255, 255, 0.50);
  --dp-input-shadow-focus: 0 0 0 3px var(--dp-accent-soft);
  --dp-input-bg-focus: #0f0f0f;
  --dp-input-option-bg: #111111;
  --dp-input-option-fg: #ffffff;
  --dp-input-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='rgba(255,255,255,0.5)' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  /* the bare CF7 submit hover uses 46%, .dp-form-wrap's uses 48% — two tokens */
  --dp-submit-shadow-hover: 0 20px 44px color-mix(in srgb, var(--dp-accent-dark) 46%, transparent);
  --dp-invalid-color: #f87171;
  --dp-error-bg: rgba(255, 107, 107, 0.10);
  --dp-error-color: #ffaaaa;
  --dp-error-border: 1px solid rgba(255, 107, 107, 0.20);
  --dp-spinner-border-color: rgba(255, 255, 255, 0.3) rgba(255, 255, 255, 0.3) rgba(255, 255, 255, 0.3) #ffffff;

  /* ─── Testimonial card ─── */
  --dp-testimonial-border: 1px solid rgba(255, 255, 255, 0.06);
  --dp-testimonial-radius: var(--dp-radius-lg);
  --dp-testimonial-text-color: rgba(255, 255, 255, 0.82);
  --dp-testimonial-foot-border: 1px solid rgba(255, 255, 255, 0.06);
  --dp-testimonial-av-radius: 50%;
  --dp-testimonial-av-fg: #ffffff;
  --dp-testimonial-name-color: #ffffff;
  --dp-testimonial-role-color: rgba(255, 255, 255, 0.5);

  /* ─── FAQ accordion (.dp-faq-q / .dp-faq-a markup) ─── */
  --dp-accordion-item-bg: rgba(255, 255, 255, 0.02);
  --dp-accordion-q-color: #ffffff;

  /* ─── Quick view: parts base.css does not cover ─── */
  --dp-qv-close-border: 1px solid rgba(255, 255, 255, 0.15);
  --dp-qv-close-bg-hover: rgba(255, 255, 255, 0.22);
  --dp-qv-gallery-bg: #0a0a0a;
  --dp-qv-skeleton-bg: linear-gradient(90deg, #1a1a1a 25%, #252525 50%, #1a1a1a 75%);
  --dp-qv-badge-radius: var(--dp-radius-full);
  --dp-qv-badge-fg: var(--dp-accent-fg);
  --dp-qv-counter-radius: var(--dp-radius-full);
  --dp-qv-nav-border: 1px solid rgba(255, 255, 255, 0.15);
  --dp-qv-nav-bg-hover: rgba(0, 0, 0, 0.82);
  --dp-qv-thumbs-bg: #0d0d0d;
  --dp-qv-thumb-radius: 6px;
  --dp-qv-scrollbar-color: rgba(255, 255, 255, 0.10) transparent;
  --dp-qv-spec-bg: rgba(255, 255, 255, 0.04);
  --dp-qv-spec-border: 1px solid rgba(255, 255, 255, 0.09);
  --dp-qv-spec-radius: var(--dp-radius-full);
  --dp-qv-spec-color: rgba(255, 255, 255, 0.72);
  /* ── 3.3.1 QUICK VIEW RESKIN — the tokens the modal did not have ──────────
     The dialog had NO box-shadow at all: a panel floating over a blurred
     backdrop with nothing under it, which is why it read as a flat cut-out
     rather than a raised surface. It also had no top-edge light line, no
     glass hook of its own, and its motion was three hard-coded durations
     (.22s / .18s / .28s) with a generic `ease`, none of which any skin could
     reach. All five are tokens now and every skin sets its own.
     --dp-qv-motion-ms IS READ BY assets/js/quick-view.js for the hide timer
     that runs after the close animation: the two used to be independent
     numbers (CSS .18s, JS 180ms) and would have drifted apart the moment a
     skin changed one. Keep them one value. */
  --dp-qv-dialog-shadow: 0 32px 80px -24px rgba(0, 0, 0, 0.70), 0 8px 24px -12px rgba(0, 0, 0, 0.50);
  --dp-qv-dialog-edge: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.14) 12%, rgba(255, 255, 255, 0.14) 88%, transparent);
  --dp-qv-dialog-blur: none;
  /* The gallery's prev/next buttons DO sit on a photograph, so glass reads
     there on every skin that has any. */
  --dp-qv-nav-blur: none;
  --dp-qv-motion: 0.3s cubic-bezier(0.22, 0.61, 0.36, 1);
  --dp-qv-motion-ms: 300;
  /* DECORATION, not action. The five spec marks are SVG now and an SVG obeys
     `color`, so this is the first time these rows have had a colour at all —
     the emoji they replace ignored it completely. The colour rule puts the
     saturated accent only where something happens; a mileage mark is a label,
     so it takes a neutral ink rung, set one step below the pill's own text so
     the figure stays the thing you read first. */
  --dp-qv-spec-ic-color: rgba(255, 255, 255, 0.52);
  --dp-qv-spec-gap: 6px;

  /* ─── Inventory trust strip ─── */
  --dp-trust-bg: rgba(255, 255, 255, 0.02);
  --dp-trust-border: 1px solid rgba(255, 255, 255, 0.06);
  --dp-trust-pill-color: rgba(255, 255, 255, 0.65);

  /* ─── Section heading block ─── */
  --dp-heading-title-color: #ffffff;
  --dp-heading-divider-radius: var(--dp-radius-full);
  --dp-heading-sub-color: rgba(255, 255, 255, 0.65);

  /* ─── CTA banner ─── */
  --dp-cta-banner-radius: var(--dp-radius-lg);
  --dp-cta-banner-shadow: 0 20px 60px color-mix(in srgb, var(--dp-cta) 35%, transparent);
  --dp-cta-banner-btn-bg: #ffffff;
  --dp-cta-banner-btn-radius: var(--dp-radius-full);
  --dp-cta-banner-btn-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  --dp-cta-banner-btn-shadow-hover: 0 14px 32px rgba(0, 0, 0, 0.28);
  --dp-cta-banner-btn-ghost-shadow: none;
  --dp-cta-banner-btn-ghost-bg-hover: rgba(255, 255, 255, 0.1);
  --dp-cta-banner-content-color: var(--dp-cta-fg);
  --dp-cta-banner-title-color: var(--dp-cta-fg);
  --dp-cta-banner-sub-color: var(--dp-cta-fg);

  /* ─── Step card ─── */
  --dp-step-border: 1px solid rgba(255, 255, 255, 0.06);
  --dp-step-radius: var(--dp-radius-md);
  --dp-step-title-color: #ffffff;
  --dp-step-text-color: rgba(255, 255, 255, 0.65);
  --dp-step-list-color: rgba(255, 255, 255, 0.55);
  --dp-step-num-radius: 50%;

  /* ─── FAQ item (.dp-faq-item__q markup) ─── */
  --dp-faq-item-border: 1px solid rgba(255, 255, 255, 0.07);
  --dp-faq-item-radius: 14px;
  --dp-faq-q-color: #ffffff;
  /* 3.2.0 — the OPEN question's own plate. Measured before this existed: the
     trigger's fg, bg and border were byte-identical open and closed on all
     three skins, so the only thing that told a visitor which question was
     open was the answer appearing and a 1px border on the item. Same
     currentColor wash as --dp-hover-veil and for the same reason, one step
     lighter so an open row reads as a state and a hovered row as a pointer. */
  --dp-faq-q-bg-open: color-mix(in srgb, currentColor 8%, transparent);
  --dp-faq-a-color: rgba(255, 255, 255, 0.72);

  /* ─── Form wrapper chrome ─── */
  --dp-form-title-color: #ffffff;
  --dp-form-sub-color: rgba(255, 255, 255, 0.50);
  --dp-form-note-color: rgba(255, 255, 255, 0.35);
  --dp-form-response-radius: var(--dp-radius-input);
  --dp-form-invalid-color: #ff6b6b;

  /* ─── Hero ─── */
  --dp-hero-note-color: rgba(255, 255, 255, 0.55);

  /* ═══ merged from tokens-chrome.css — front-page.php / header.php / footer.php  (chrome) ═══ */
  --dp-home-hero-sub-color: rgba(255, 255, 255, 0.82);
  --dp-home-hero-pills-color: rgba(255, 255, 255, 0.72);
  --dp-home-hero-pill-bg: rgba(255, 255, 255, 0.04);
  --dp-home-hero-pill-border: 1px solid rgba(255, 255, 255, 0.08);
  --dp-fcard-arrow-border-hover: var(--dp-accent);
  --dp-overlay-close-bg: transparent;
  --dp-footer-logo-opacity-hover: 1;
  --dp-footer-bottom-link-color: rgba(255, 255, 255, 0.38);
  --dp-footer-bottom-link-hover: var(--dp-accent);
  --dp-field-invalid-border: #dc2626;
  --dp-field-invalid-shadow: 0 0 0 3px rgba(220, 38, 38, 0.12);
  --dp-field-error-color: #dc2626;

  /* ═══ merged from tokens-content.css — page-about.php / page-shipping.php / page-contact.php  (content) ═══ */
  --dp-page-wrapper-bg: rgba(255,255,255,0.015);
  --dp-page-wrapper-border: 1px solid rgba(255,255,255,0.05);
  --dp-page-wrapper-border-hover: rgba(255,255,255,0.09);
  --dp-page-subtitle-color: rgba(255,255,255,0.65);
  --dp-page-body-color: rgba(255,255,255,0.72);
  --dp-page-card-border: 1px solid rgba(255,255,255,0.06);
  --dp-page-card-border-hover: color-mix(in srgb, var(--dp-accent) 22%, transparent);
  --dp-page-card-title-color: #ffffff;
  --dp-page-card-text-color: rgba(255,255,255,0.58);
  --dp-page-card-icon-bg: color-mix(in srgb, var(--dp-accent) 8%, transparent);
  --dp-page-card-icon-border: 1px solid color-mix(in srgb, var(--dp-accent) 16%, transparent);
  --dp-page-intro-color: rgba(255,255,255,0.55);
  --dp-page-ci-icon-bg: color-mix(in srgb, var(--dp-accent) 8%, transparent);
  --dp-page-ci-label-color: rgba(255,255,255,0.45);
  --dp-page-ci-value-color: #ffffff;
  --dp-page-trust-item-color: color-mix(in srgb, var(--dp-accent) 85%, transparent);
  --dp-faq-item-border-open: color-mix(in srgb, var(--dp-accent) 24%, transparent);
  --dp-page-faq-a-color: rgba(255,255,255,0.65);
  --dp-abt-check-bg: linear-gradient(180deg,var(--dp-bg-card),var(--dp-bg-card-2));
  --dp-abt-check-border-hover: color-mix(in srgb, var(--dp-accent) 28%, transparent);
  --dp-abt-check-shadow-hover: 0 6px 20px rgba(0,0,0,0.18);
  --dp-abt-check-icon-bg: color-mix(in srgb, var(--dp-accent) 14%, transparent);
  --dp-abt-check-icon-border: 1px solid color-mix(in srgb, var(--dp-accent) 28%, transparent);
  --dp-abt-check-desc-color: rgba(255,255,255,0.65);
  --dp-abt-check-meta-color: rgba(255,255,255,0.55);
  --dp-abt-timeline-line-bg: color-mix(in srgb, var(--dp-accent) 20%, transparent);
  --dp-abt-tl-year-radius: 50%;
  --dp-abt-tl-dot-radius: 50%;
  --dp-abt-tl-badge-bg: color-mix(in srgb, var(--dp-accent) 12%, transparent);
  --dp-abt-tl-badge-border: 1px solid color-mix(in srgb, var(--dp-accent) 25%, transparent);
  --dp-abt-tl-text-color: rgba(255,255,255,0.60);
  --dp-abt-val-border-hover: color-mix(in srgb, var(--dp-accent) 24%, transparent);
  --dp-abt-val-icon-border: 1px solid color-mix(in srgb, var(--dp-accent) 18%, transparent);
  --dp-abt-val-text-color: rgba(255,255,255,0.70);
  --dp-shp-line-shadow: 0 0 16px color-mix(in srgb, var(--dp-accent) 16%, transparent);
  --dp-shp-trailer-list-color: rgba(255,255,255,0.72);
  --dp-shp-trailer-price-border: 1px solid rgba(255,255,255,0.08);
  --dp-shp-trailer-price-strong-color: #ffffff;
  --dp-shp-tbl-head-bg: color-mix(in srgb, var(--dp-accent) 8%, transparent);
  --dp-shp-tbl-head-border: 1px solid color-mix(in srgb, var(--dp-accent) 20%, transparent);
  --dp-shp-tbl-td-color: rgba(255,255,255,0.75);
  --dp-shp-tbl-td-border: 1px solid rgba(255,255,255,0.05);
  --dp-shp-tbl-val-color: #ffffff;
  --dp-shp-tbl-feat-bg: color-mix(in srgb, var(--dp-accent) 6%, transparent);
  --dp-shp-tbl-feat-border-color: color-mix(in srgb, var(--dp-accent) 15%, transparent);
  --dp-shp-tbl-note-color: rgba(255,255,255,0.30);
  --dp-shp-step-text-color: rgba(255,255,255,0.60);
  --dp-shp-step-num-border: 2px solid color-mix(in srgb, var(--dp-accent) 30%, transparent);
  --dp-shp-trust-badge-bg: color-mix(in srgb, var(--dp-accent) 8%, transparent);
  --dp-shp-trust-badge-border: 1px solid color-mix(in srgb, var(--dp-accent) 22%, transparent);

  /* ═══ merged from tokens-listing.css — single-listing.php / archive-listing.php  (listing) ═══ */
  --dp-error: #dc3545;
  --dp-sl-back-color: rgba(255,255,255,0.55);
  --dp-sl-muted: rgba(255,255,255,0.55);
  --dp-sl-panel-border: 1px solid #1a1a1a;
  --dp-sl-box-divider: 1px solid #1a1a1a;
  --dp-sl-srow-divider: 1px solid rgba(255,255,255,0.05);
  --dp-sl-sidebar-border: 1px solid #1e1e1e;
  --dp-sl-sidebar-head-radius: var(--dp-radius-xs) var(--dp-radius-xs) 0 0;
  --dp-sl-sidebar-radius: 0 0 var(--dp-radius-xs) var(--dp-radius-xs);
  --dp-sl-ghost-bg: rgba(255,255,255,0.04);
  --dp-sl-ghost-bg-hover: rgba(255,255,255,0.08);
  --dp-sl-ghost-border: 1px solid rgba(255,255,255,0.12);
  --dp-sl-ghost-border-sm: 1px solid rgba(255,255,255,0.1);
  --dp-sl-share-color: rgba(255,255,255,0.65);
  --dp-sl-share-border-hover: rgba(255,255,255,0.22);
  --dp-sl-share-sm-color: rgba(255,255,255,0.6);
  --dp-sl-share-sm-border-hover: rgba(255,255,255,0.2);
  --dp-sl-share-icon-opacity: 0.7;
  --dp-sl-gal-btn-radius: 50%;
  --dp-sl-gal-btn-bg: rgba(0,0,0,0.55);
  --dp-sl-gal-btn-border: 1px solid rgba(255,255,255,0.15);
  --dp-sl-gal-btn-bg-hover: rgba(0,0,0,0.75);
  --dp-sl-cnt-bg: rgba(0,0,0,0.55);
  --dp-sl-no-img-color: rgba(255,255,255,0.30);
  --dp-sl-thumb-radius: 7px;
  --dp-sl-thumb-border: 2px solid transparent;
  --dp-sl-desc-color: rgba(255,255,255,0.78);
  --dp-sl-specs-toggle-bg: color-mix(in srgb, var(--dp-accent) 8%, transparent);
  --dp-sl-specs-toggle-border: 1px solid color-mix(in srgb, var(--dp-accent) 25%, transparent);
  --dp-sl-specs-toggle-bg-hover: color-mix(in srgb, var(--dp-accent) 16%, transparent);
  --dp-sl-specs-toggle-border-hover: color-mix(in srgb, var(--dp-accent) 45%, transparent);
  --dp-sl-reserve-bg: linear-gradient(135deg,var(--dp-reserve),var(--dp-reserve-dark));
  --dp-sl-reserve-border: 1px solid color-mix(in srgb,var(--dp-reserve) 50%,transparent);
  --dp-sl-reserve-shadow: 0 8px 28px color-mix(in srgb,var(--dp-reserve) 38%,transparent);
  --dp-sl-reserve-shadow-pulse: 0 8px 28px color-mix(in srgb,var(--dp-reserve) 38%,transparent),0 0 0 8px color-mix(in srgb,var(--dp-reserve) 22%,transparent);
  --dp-sl-reserve-shadow-hover: 0 14px 36px color-mix(in srgb,var(--dp-reserve) 55%,transparent);
  --dp-sl-reserve-icon-bg: rgba(255,255,255,0.18);
  --dp-sl-reserve-arrow-opacity: 0.9;
  --dp-sl-reserve-color: var(--dp-reserve-fg);
  --dp-sl-reserve-color-hover: var(--dp-reserve-fg);
  --dp-sl-noobl-color: #555;
  --dp-sl-reserve-sub-color: #555;
  --dp-sl-inq-icon-bg: color-mix(in srgb,var(--dp-accent) 12%,transparent);
  --dp-sl-inq-icon-border: 1px solid color-mix(in srgb,var(--dp-accent) 22%,transparent);
  --dp-sl-noform-border: 1px dashed rgba(255,255,255,0.1);
  --dp-sl-noform-color: rgba(255,255,255,0.4);
  --dp-sl-inq-hours-color-hover: rgba(255,255,255,0.75);
  --dp-sl-lb-overlay-bg: rgba(0,0,0,0.92);
  --dp-sl-lb-overlay-blur: blur(8px);
  --dp-sl-lb-btn-radius: 50%;
  --dp-sl-lb-close-bg: rgba(255,255,255,0.08);
  --dp-sl-lb-close-border: 1px solid rgba(255,255,255,0.15);
  --dp-sl-lb-close-bg-hover: rgba(255,255,255,0.15);
  --dp-sl-lb-nav-bg: rgba(255,255,255,0.06);
  --dp-sl-lb-nav-border: 1px solid rgba(255,255,255,0.12);
  --dp-sl-lb-nav-bg-hover: color-mix(in srgb, var(--dp-accent) 15%, transparent);
  --dp-sl-lb-nav-border-hover: color-mix(in srgb, var(--dp-accent) 40%, transparent);
  --dp-sl-lb-counter-bg: rgba(0,0,0,0.5);
  --dp-sl-lb-counter-color: rgba(255,255,255,0.6);
  --dp-sl-notice-text-color: rgba(255,255,255,0.65);
  --dp-sl-sold-overlay-bg: rgba(0,0,0,0.75);
  --dp-sl-sold-shadow: 0 4px 24px rgba(220,53,69,0.4);
  --dp-sl-sold-notice-bg: rgba(220,53,69,0.08);
  --dp-sl-sold-notice-border: 1px solid rgba(220,53,69,0.25);
  --dp-sl-reserved-overlay-bg: rgba(0,0,0,0.70);
  --dp-sl-reserved-bg: #7c3aed;
  --dp-sl-reserved-shadow: 0 4px 24px rgba(124,58,237,0.45);
  --dp-sl-reserved-notice-bg: rgba(124,58,237,0.10);
  --dp-sl-reserved-notice-border: 1px solid rgba(124,58,237,0.35);
  --dp-sl-reserved-notice-color: #a78bfa;
  --dp-sl-pending-overlay-bg: rgba(0,0,0,0.45);
  --dp-sl-pending-bg: #f59e0b;
  --dp-sl-pending-fg: #000;
  --dp-sl-pending-shadow: 0 4px 24px rgba(245,158,11,0.45);
  --dp-sl-pending-notice-bg: rgba(245,158,11,0.10);
  --dp-sl-pending-notice-border: 1px solid rgba(245,158,11,0.35);
  --dp-sl-pending-notice-color: #f59e0b;
  --dp-sl-rel-bg: linear-gradient(180deg,var(--dp-bg-card),var(--dp-bg-card-2));
  --dp-sl-rel-shadow-hover: 0 20px 40px rgba(0,0,0,0.4);
  --dp-inv-features-bg: linear-gradient(180deg,var(--dp-bg) 0%,var(--dp-bg) 100%);
  --dp-inv-features-divider: 1px solid rgba(255,255,255,0.05);
  --dp-inv-feat-border-hover: color-mix(in srgb, var(--dp-accent) 20%, transparent);
  --dp-inv-feat-shadow-hover: 0 18px 38px rgba(0,0,0,0.3);
  --dp-inv-feat-num-border: 1px solid color-mix(in srgb, var(--dp-accent) 20%, transparent);
  --dp-inv-feat-text-color: rgba(255,255,255,0.60);
  --dp-inv-search-icon-color: rgba(255,255,255,0.42);
  --dp-inv-count-color: rgba(255,255,255,0.52);
  --dp-inv-loading-opacity: 0.4;
  --dp-inv-loading-blur: blur(2px);
  --dp-inv-skeleton-radius: 4px;
  --dp-inv-skeleton-bg: linear-gradient(90deg,rgba(255,255,255,0.03) 0%,rgba(255,255,255,0.08) 50%,rgba(255,255,255,0.03) 100%);
  --dp-inv-card-scrim: rgba(0,0,0,0);
  --dp-inv-card-scrim-hover: rgba(0,0,0,0.45);
  --dp-inv-photocount-bg: rgba(0,0,0,0.62);
  --dp-inv-photocount-blur: blur(3px);
  --dp-inv-card-dot: rgba(255,255,255,0.28);
  --dp-inv-card-arrow-fg-hover: var(--dp-accent-fg);
  --dp-inv-empty-color: rgba(255,255,255,0.60);
  --dp-inv-showing-color: rgba(255,255,255,0.42);
  --dp-inv-page-btn-border: 1px solid rgba(255,255,255,0.10);
  --dp-inv-page-btn-bg: rgba(255,255,255,0.04);
  --dp-inv-page-btn-color: rgba(255,255,255,0.70);
  --dp-inv-page-btn-color-active: var(--dp-accent-fg);
  --dp-inv-page-btn-bg-hover: color-mix(in srgb,var(--dp-accent) 8%,transparent);
  --dp-inv-page-btn-disabled-opacity: 0.35;

  /* ═══ merged from tokens-tail.css — 404.php / page-privacy-policy.php / page-thank-you.php / functions.php  (tail) ═══ */
  --dp-404-sub-color: rgba(255,255,255,0.60);
  --dp-404-or-color: rgba(255,255,255,0.35);
  --dp-404-phone-opacity-hover: 0.8;
  --dp-404-links-border-top: 1px solid rgba(255,255,255,0.06);
  --dp-404-links-title-color: rgba(255,255,255,0.40);
  --dp-404-link-border: 1px solid rgba(255,255,255,0.06);
  --dp-404-link-color: rgba(255,255,255,0.70);
  --dp-404-link-border-hover: color-mix(in srgb, var(--dp-accent) 30%, transparent);
  --dp-404-link-bg-hover: color-mix(in srgb, var(--dp-accent) 6%, transparent);
  --dp-legal-updated-color: rgba(255,255,255,0.40);
  --dp-legal-body-bg: rgba(255,255,255,0.015);
  --dp-legal-body-border: 1px solid rgba(255,255,255,0.05);
  --dp-legal-divider: 1px solid rgba(255,255,255,0.05);
  --dp-legal-text-color: rgba(255,255,255,0.72);
  --dp-ty-panel-bg: rgba(255,255,255,0.015);
  --dp-ty-panel-border: 1px solid rgba(255,255,255,0.05);
  --dp-ty-sub-color: rgba(255,255,255,0.65);
  --dp-ty-countdown-border: 1px solid rgba(255,255,255,0.06);
  --dp-ty-countdown-label-color: rgba(255,255,255,0.45);
  --dp-ty-countdown-unit-color: rgba(255,255,255,0.40);
  --dp-ty-countdown-sep-color: rgba(255,255,255,0.20);
  --dp-ty-countdown-bar-bg: rgba(255,255,255,0.06);
  --dp-ty-countdown-fill-bg: linear-gradient(90deg,var(--dp-accent),var(--dp-accent-dark));
  --dp-ty-feature-text-color: rgba(255,255,255,0.70);
  --dp-ty-contact-note-color: rgba(255,255,255,0.50);
  --dp-ty-contact-item-color: rgba(255,255,255,0.75);
  --dp-ty-trust-bg: color-mix(in srgb, var(--dp-accent) 7%, transparent);
  --dp-ty-trust-border: 1px solid color-mix(in srgb, var(--dp-accent) 20%, transparent);
  --dp-ty-trust-color: rgba(255,255,255,0.85);
  --dp-ty-trust-bg-hover: color-mix(in srgb, var(--dp-accent) 12%, transparent);
  --dp-ty-trust-border-hover: color-mix(in srgb, var(--dp-accent) 32%, transparent);
  --dp-ty-sec-head-sub-color: rgba(255,255,255,0.55);
  --dp-ty-review-border: 1px solid rgba(255,255,255,0.06);
  --dp-ty-review-border-hover: color-mix(in srgb, var(--dp-accent) 22%, transparent);
  --dp-ty-review-text-color: rgba(255,255,255,0.72);
  --dp-ty-review-foot-border: 1px solid rgba(255,255,255,0.06);
  --dp-ty-review-role-color: rgba(255,255,255,0.40);
  --dp-ty-inv-card-border: 1px solid rgba(255,255,255,0.06);
  --dp-ty-inv-card-border-hover: color-mix(in srgb, var(--dp-accent) 22%, transparent);
  --dp-ty-inv-img-bg: #111;
  --dp-ty-inv-type-color: rgba(255,255,255,0.40);
  --dp-ty-inv-price-call-color: rgba(255,255,255,0.55);
  --dp-ty-inv-btn-shadow-hover: 0 6px 18px color-mix(in srgb, var(--dp-accent) 35%, transparent);
  --dp-btt-panel-bg: rgba(16,16,16,0.95);
  --dp-btt-panel-border: 1px solid color-mix(in srgb, var(--dp-accent) 40%, transparent);
  --dp-btt-panel-shadow: 0 4px 20px rgba(0,0,0,0.4);
  --dp-btt-panel-blur: blur(10px);
  --dp-btt-panel-bg-hover: color-mix(in srgb, var(--dp-accent) 15%, transparent);
  --dp-btt-panel-border-hover: color-mix(in srgb, var(--dp-accent) 70%, transparent);
  --dp-btt-panel-shadow-hover: 0 8px 28px color-mix(in srgb, var(--dp-accent) 20%, transparent);
  --dp-bc-color: rgba(255,255,255,0.45);
  --dp-bc-link-color: rgba(255,255,255,0.55);
  --dp-bc-sep-color: rgba(255,255,255,0.25);

  /* ═══ merged from tokens-transaction.css — page-reserve.php (transaction) ═══ */
  --dp-rv-wrapper-bg: rgba(255, 255, 255, 0.015);
  --dp-rv-wrapper-border: 1px solid rgba(255, 255, 255, 0.05);
  --dp-rv-wrapper-border-hover: rgba(255, 255, 255, 0.09);
  --dp-rv-wrapper-glow: radial-gradient(circle, color-mix(in srgb, var(--dp-accent) 3%, transparent), transparent 70%);
  --dp-rv-wrapper-glow-opacity: 0.5;
  --dp-rv-subtitle-color: rgba(255, 255, 255, 0.50);
  --dp-rv-sub-color: rgba(255, 255, 255, 0.55);
  --dp-rv-step-border: 1px solid rgba(255, 255, 255, 0.06);
  --dp-rv-step-active-bg: color-mix(in srgb, var(--dp-accent) 8%, transparent);
  --dp-rv-step-active-border: color-mix(in srgb, var(--dp-accent) 20%, transparent);
  --dp-rv-step-current-border: color-mix(in srgb, var(--dp-cta) 30%, transparent);
  --dp-rv-step-num-radius: 50%;
  --dp-rv-step-num-bg: rgba(255, 255, 255, 0.06);
  --dp-rv-step-num-color: rgba(255, 255, 255, 0.40);
  --dp-rv-step-num-color-active: var(--dp-accent-fg);
  --dp-rv-step-num-color-current: var(--dp-cta-fg);
  --dp-rv-step-lbl-color: rgba(255, 255, 255, 0.45);
  --dp-rv-step-line-bg: rgba(255, 255, 255, 0.10);
  --dp-rv-card-border: 1px solid #1e1e1e;
  --dp-rv-card-border-hover: #333;
  --dp-rv-card-shadow-hover: 0 8px 40px rgba(0, 0, 0, 0.4);
  --dp-rv-card-note-color: rgba(255, 255, 255, 0.45);
  --dp-rv-card-img-bg: #0a0a0a;
  --dp-rv-fallback-border: 1px solid #1e1e1e;
  --dp-rv-fallback-color: rgba(255, 255, 255, 0.55);
  --dp-rv-trust-pill-border: 1px solid rgba(255, 255, 255, 0.08);
  --dp-rv-trust-pill-color: rgba(255, 255, 255, 0.72);
  --dp-rv-form-border: 1px solid rgba(255, 255, 255, 0.08);
  --dp-rv-form-shadow: 0 20px 50px rgba(0, 0, 0, 0.25);
  --dp-rv-form-glow: radial-gradient(circle at top center, color-mix(in srgb, var(--dp-cta) 5%, transparent), transparent 50%);
  --dp-rv-form-border-hover: color-mix(in srgb, var(--dp-cta) 18%, transparent);
  --dp-rv-form-head-border: 1px solid rgba(255, 255, 255, 0.06);
  --dp-rv-form-icon-radius: 50%;
  --dp-rv-form-icon-bg: linear-gradient(135deg, var(--dp-cta), var(--dp-cta-dark));
  --dp-rv-form-icon-fg: var(--dp-cta-fg);
  --dp-rv-form-icon-shadow: 0 12px 32px color-mix(in srgb, var(--dp-cta) 40%, transparent);
  --dp-rv-form-sub-color: rgba(255, 255, 255, 0.55);
  --dp-rv-form-h3-dot-radius: 50%;
  --dp-rv-form-h3-dot-shadow: 0 0 12px var(--dp-accent);
  --dp-rv-file-border: 1px dashed rgba(255, 255, 255, 0.15);
  --dp-rv-file-color: rgba(255, 255, 255, 0.6);
  --dp-rv-file-border-hover: color-mix(in srgb, var(--dp-accent) 40%, transparent);
  --dp-rv-submit-bg: linear-gradient(135deg, var(--dp-cta), var(--dp-cta-dark));
  --dp-rv-submit-shadow: 0 14px 34px color-mix(in srgb, var(--dp-cta-dark) 38%, transparent);
  --dp-rv-submit-shadow-hover: 0 20px 44px color-mix(in srgb, var(--dp-cta-dark) 50%, transparent);
  --dp-rv-submit-fg: var(--dp-cta-fg);
  --dp-rv-review-border: 1px solid rgba(255, 255, 255, 0.06);
  --dp-rv-review-border-hover: color-mix(in srgb, var(--dp-accent) 22%, transparent);
  --dp-rv-review-text-color: rgba(255, 255, 255, 0.7);
  --dp-rv-review-av-bg: linear-gradient(135deg, var(--dp-accent), var(--dp-accent-dark));
  --dp-rv-review-av-fg: var(--dp-accent-fg);
  --dp-rv-review-role-color: rgba(255, 255, 255, 0.4);
  --dp-rv-faq-bg-hover: color-mix(in srgb, var(--dp-accent) 3%, var(--dp-bg-card));
  --dp-rv-faq-border-open: color-mix(in srgb, var(--dp-accent) 35%, transparent);
  --dp-rv-faq-bg-open: color-mix(in srgb, var(--dp-accent) 5%, var(--dp-bg-card));
  --dp-rv-faq-a-color: rgba(255, 255, 255, 0.65);

  /* ═══ reserve family: referenced by single-listing/archive/front-page but only
         ever declared by the wp_head colour block in functions.php (prio 20,
         !important). These static values are that block's own defaults, so the
         runtime stamp still wins and nothing rendered changes — they just stop
         the bare var() references resolving to nothing if the block is absent. ═══ */
  --dp-reserve: #fbbf24;
  --dp-reserve-dark: #e2a60b;
  --dp-reserve-fg: #000000;

  /* ══ TYPOGRAPHY TOKENS — merged from work/type-*.css ══ */

  /* -- style -- */
  --dp-fw-light: 300;
  --dp-btn-white-fw: var(--dp-fw-black);
  --dp-cf7-label-fs: 11px;
  /* --dp-cf7-label-color is deliberately NOT declared here, and its consumer
     fallback is `var(--dp-accent)`, not `var(--dp-label-color)`.

     Two separate reasons, and both matter:

     1. UNSKINNED FIDELITY. 2.9.4 shipped `.wpcf7-form label { color:
        var(--dp-accent) }`. With no dp-skin--* class the fallback is what
        renders, so it has to be the value 2.9.4 rendered — the wizard accent
        that functions.php stamps on `:root,:root body` — or every live site
        that upgrades in place repaints its form labels. A `--dp-label-color`
        fallback printed rgba(255,255,255,0.72) there instead.

     2. THE ALIAS CANNOT LIVE IN :root. A custom property substitutes at the
        element where it is DECLARED. `--dp-cf7-label-color: var(--dp-...)` in
        :root substitutes on <html>, where only this block's tokens are
        visible; every skin re-declares its tokens at body.dp-skin--KEY scope,
        a descendant, so such an alias would freeze all three skins to the
        base value. Carrying the fallback on the consumer resolves it on the
        label element, where the skin's declaration is in scope.

     A skin that wants its own CF7 label colour declares --dp-cf7-label-color
     in its own body scope and it wins. All three do. */
  --dp-cf7-label-fw: var(--dp-fw-extrabold);
  --dp-cf7-label-ls: 1px;
  --dp-cf7-label-transform: uppercase;
  --dp-input-fs: 16px;
  --dp-input-lh: 1.5;
  /* 3.2.0 — ONE submit token set. The submit used to be claimed by two
     parallel families, --dp-cf7-submit-* (6) and --dp-submit-* (7),
     overlapping on fg/fs/fw/shadow-hover; which one reached the button was
     decided by a single attribute selector rather than by anyone's
     decision, and four tokens reached it never. The merged set keeps the
     value that ACTUALLY RENDERED in every case, so nothing about the
     button changes. What each name now means is written once, here. */
  --dp-submit-fs: 16px;
  --dp-submit-fw: var(--dp-fw-extrabold);
  --dp-submit-transform: uppercase;
  --dp-submit-ls: 0.5px;
  --dp-invalid-fs: 12px;
  --dp-cf7-response-fs: 14px;
  --dp-cf7-response-fw: var(--dp-fw-semibold);
  --dp-testimonial-stars-fs: 16px;
  --dp-testimonial-stars-ls: 3px;
  --dp-testimonial-text-fs: 15px;
  --dp-testimonial-text-lh: 1.7;
  --dp-testimonial-text-fs-sm: 15px;
  --dp-testimonial-av-fs: 13px;
  --dp-testimonial-av-fw: var(--dp-fw-extrabold);
  --dp-testimonial-name-fs: 14px;
  --dp-testimonial-name-fw: var(--dp-fw-extrabold);
  --dp-testimonial-role-fs: 12px;
  --dp-accordion-q-fs: 16px;
  --dp-accordion-q-fw: var(--dp-fw-bold);
  --dp-accordion-icon-fs: 22px;
  --dp-accordion-icon-fw: var(--dp-fw-light);
  --dp-accordion-a-fs: 15px;
  --dp-accordion-a-lh: 1.8;
  --dp-qv-close-modal-fs: 22px;
  --dp-qv-close-lh: 1;
  --dp-qv-badge-fs: 11px;
  --dp-qv-badge-fw: var(--dp-fw-extrabold);
  --dp-qv-badge-transform: uppercase;
  --dp-qv-badge-ls: 0.08em;
  --dp-qv-counter-fs: 12px;
  --dp-qv-counter-fw: var(--dp-fw-bold);
  --dp-qv-counter-ls: 0.5px;
  --dp-qv-nav-fs: 22px;
  --dp-qv-title-modal-fs: 21px;
  --dp-qv-title-lh: 1.2;
  --dp-qv-price-ls: -0.5px;
  --dp-qv-spec-fs: 12px;
  --dp-qv-spec-fw: var(--dp-fw-bold);
  --dp-qv-desc-modal-fs: 13px;
  --dp-qv-desc-modal-lh: 1.75;
  --dp-qv-note-modal-fs: 11px;
  --dp-trust-pill-fs: 13px;
  --dp-trust-pill-fw: var(--dp-fw-bold);
  --dp-trust-pill-ls: 0.2px;
  --dp-trust-pill-fs-sm: 12px;
  --dp-heading-title-fs: clamp(28px,4vw,48px);
  --dp-heading-title-fw: var(--dp-fw-black);
  --dp-heading-title-lh: 1.15;
  --dp-heading-title-ls: -1px;
  --dp-heading-sub-fs: clamp(16px,1.8vw,18px);
  --dp-heading-sub-lh: 1.7;
  --dp-cta-banner-title-fs: clamp(24px,3vw,36px);
  --dp-cta-banner-title-fw: var(--dp-fw-black);
  --dp-cta-banner-title-lh: 1.15;
  --dp-cta-banner-sub-fs: 15px;
  --dp-cta-banner-sub-lh: 1.6;
  --dp-cta-banner-btn-fs: 16px;
  --dp-cta-banner-btn-fw: var(--dp-fw-extrabold);
  --dp-feature-icon-lh: 1;
  --dp-step-title-fs: 17px;
  --dp-step-title-fw: var(--dp-fw-extrabold);
  --dp-step-text-fs: 14px;
  --dp-step-text-lh: 1.65;
  --dp-step-list-fs: 13px;
  --dp-step-list-lh: 1.65;
  --dp-step-list-tick-fw: var(--dp-fw-extrabold);
  --dp-step-num-fs: 20px;
  --dp-step-num-fw: var(--dp-fw-black);
  --dp-faq-q-fs: var(--dp-text-base);
  --dp-faq-q-fw: var(--dp-fw-bold);
  --dp-faq-icon-fs: 22px;
  --dp-faq-icon-fw: var(--dp-fw-light);
  --dp-faq-a-fs: 14px;
  --dp-faq-a-lh: 1.75;
  --dp-form-title-fs: var(--dp-text-lg);
  --dp-form-title-fw: var(--dp-fw-extrabold);
  --dp-form-sub-fs: 14px;
  --dp-form-note-fs: 12px;
  --dp-form-response-fs: 14px;
  --dp-form-invalid-fs: 12px;
  --dp-form-invalid-fw: var(--dp-fw-semibold);
  --dp-hero-note-fs: 13px;
  --dp-hero-note-ls: 0.3px;
  --dp-hero-title-ls-sm: -1px;

  /* -- chrome -- */
  --dp-overlay-msg-fw: var(--dp-fw-medium);
  --dp-overlay-btn-lh: 1;
  --dp-mnav-call-fs: 16px;
  --dp-mnav-call-fw: var(--dp-fw-extrabold);
  --dp-footer-bottom-link-fs: 14px;
  --dp-field-error-fs: 12px;
  --dp-field-error-fw: var(--dp-fw-semibold);
  --dp-statsband-num-lh: 1;
  --dp-stat-num-lh: 1;
  --dp-stat-suf-lh: 1;
  --dp-ship-counter-lh: 1;
  --dp-contact-trust-pill-tick-fw: var(--dp-fw-black);
  --dp-home-hero-title-lh: 1.02;
  --dp-home-hero-title-lh-md: 1.02;
  --dp-home-hero-sub-fs: 18px;
  --dp-home-hero-sub-lh: 1.85;
  --dp-home-hero-sub-fs-sm: 15px;
  --dp-home-hero-pills-fs: 13px;
  --dp-home-hero-pills-fw: var(--dp-fw-semibold);
  --dp-home-hero-pills-fs-sm: 12px;

  /* -- listing -- */
  --dp-sl-share-confirm-inline-fs: 12px;
  --dp-sl-notice-icon-fs: 24px;
  --dp-sl-pending-notice-icon-fs: 22px;
  --dp-sl-share-sm-fs: 12px;
  --dp-sl-share-sm-fw: var(--dp-fw-bold);
  --dp-sl-yr-fs: 13px;
  --dp-sl-stitle-fs: 26px;
  --dp-sl-stitle-fw: var(--dp-fw-black);
  --dp-sl-stitle-lh: 1.15;
  --dp-sl-sprice-fs: 34px;
  --dp-sl-sprice-fw: var(--dp-fw-black);
  --dp-sl-sprice-ls: -1px;
  --dp-sl-gal-btn-fs: 24px;
  --dp-sl-cnt-fs: 13px;
  --dp-sl-cnt-fw: var(--dp-fw-semibold);
  --dp-sl-no-img-fs: 18px;
  --dp-sl-trust-icon-fs: 20px;
  --dp-sl-trust-title-fs: 13px;
  --dp-sl-trust-title-fw: var(--dp-fw-bold);
  --dp-sl-trust-text-fs: 12px;
  --dp-sl-tab-fs: 14px;
  --dp-sl-tab-fw: var(--dp-fw-extrabold);
  --dp-sl-desc-lh: 1.85;
  --dp-sl-specs-toggle-fs: 13.5px;
  --dp-sl-specs-toggle-fw: var(--dp-fw-extrabold);
  --dp-sl-specs-toggle-ls: 0.3px;
  --dp-sl-slbl-fs: 14px;
  --dp-sl-sval-fs: 14px;
  --dp-sl-sval-fw: var(--dp-fw-bold);
  --dp-sl-reserve-main-fs: 15px;
  --dp-sl-reserve-main-fw: var(--dp-fw-black);
  --dp-sl-reserve-main-lh: 1.2;
  --dp-sl-reserve-main-ls: 0.2px;
  --dp-sl-noobl-fs: 11.5px;
  --dp-sl-reserve-sub-fs: 11.5px;
  --dp-sl-inq-title-fs: 20px;
  --dp-sl-inq-title-fw: var(--dp-fw-black);
  --dp-sl-inq-title-lh: 1.2;
  --dp-sl-inq-sub-fs: 14px;
  --dp-sl-inq-noform-fs: 14px;
  --dp-sl-lb-close-fs: 20px;
  --dp-sl-lb-nav-fs: 28px;
  --dp-sl-lb-counter-fs: 14px;
  --dp-sl-lb-counter-fw: var(--dp-fw-semibold);
  --dp-sl-lb-nav-fs-sm: 22px;
  --dp-sl-sold-fs: 28px;
  --dp-sl-sold-fw: var(--dp-fw-black);
  --dp-sl-sold-ls: 6px;
  --dp-sl-sold-transform: uppercase;
  --dp-sl-sold-notice-title-fs: 15px;
  --dp-sl-sold-notice-text-fs: 13px;
  --dp-sl-reserved-fs: 26px;
  --dp-sl-reserved-fw: var(--dp-fw-black);
  --dp-sl-reserved-ls: 5px;
  --dp-sl-reserved-transform: uppercase;
  --dp-sl-pending-fs: 26px;
  --dp-sl-pending-fw: var(--dp-fw-black);
  --dp-sl-pending-ls: 5px;
  --dp-sl-pending-transform: uppercase;
  --dp-sl-notice-title-fs: 14px;
  --dp-sl-notice-title-fw: var(--dp-fw-extrabold);
  --dp-sl-notice-title-ls: 0.3px;
  --dp-sl-notice-text-fs: 12.5px;
  --dp-sl-notice-text-lh: 1.5;
  --dp-sl-related-title-fs: clamp(24px,3vw,36px);
  --dp-sl-related-title-fw: var(--dp-fw-extrabold);
  --dp-sl-rel-title-fs: 15px;
  --dp-sl-rel-title-fw: var(--dp-fw-bold);
  --dp-sl-rel-title-lh: 1.3;
  --dp-sl-rel-price-fs: 18px;
  --dp-sl-rel-price-fw: var(--dp-fw-black);
  --dp-sl-share-fs: 13px;
  --dp-sl-share-fw: var(--dp-fw-bold);
  --dp-sl-share-ls: 0.2px;
  --dp-sl-share-confirm-fs: 13px;
  --dp-sl-share-confirm-fw: var(--dp-fw-bold);
  --dp-inv-feat-num-fs: 13px;
  --dp-inv-feat-num-fw: var(--dp-fw-black);
  --dp-inv-feat-title-fs: 17px;
  --dp-inv-feat-title-fw: var(--dp-fw-extrabold);
  --dp-inv-feat-text-fs: 14px;
  --dp-inv-feat-text-lh: 1.8;
  --dp-inv-search-fs: 16px;
  --dp-inv-select-fs: 14px;
  --dp-inv-select-fw: var(--dp-fw-semibold);
  --dp-inv-count-fs: 14px;
  --dp-inv-count-fw: var(--dp-fw-medium);
  --dp-inv-photocount-fs: 11px;
  --dp-inv-photocount-fw: var(--dp-fw-bold);
  --dp-inv-photocount-ls: 0.3px;
  --dp-inv-card-year-fs: 12px;
  --dp-inv-card-title-fs: 22px;
  --dp-inv-card-title-ls: -0.4px;
  --dp-inv-card-specs-fs: 13px;
  --dp-inv-card-specs-fw: var(--dp-fw-medium);
  --dp-inv-card-price-fs: 26px;
  --dp-inv-card-price-ls: -0.5px;
  --dp-inv-card-title-fs-sm: 20px;
  --dp-inv-card-price-fs-sm: 22px;
  --dp-inv-empty-icon-fs: 48px;
  /* Same shape as --dp-ship-step-icon-h above, and the same reasoning.
     63px is what this block renders at with NO skin file loaded (style.css
     alone, the emoji still in place), measured on the inventory page with the
     empty state forced visible -- this install has 22 listings, so it never
     paints by itself -- at 1440x900 and at 390x844. Without it a skinless site
     would collapse the block to the SVG's 48px content box. Each skin
     overrides it. */
  --dp-inv-empty-icon-h: 63px;
  --dp-inv-empty-icon-sw: 0.75;   /* 36 / 48px -> a 1.50px keyline at this size */
  --dp-inv-empty-title-fs: 24px;
  --dp-inv-empty-title-fw: var(--dp-fw-extrabold);
  --dp-inv-showing-fs: 14px;
  --dp-inv-showing-fw: var(--dp-fw-medium);
  --dp-inv-page-btn-fs: 14px;
  --dp-inv-page-btn-fw: var(--dp-fw-bold);

  /* -- content -- */
  --dp-page-title-fs: var(--dp-title-fs-section);
  --dp-page-title-fw: var(--dp-fw-black);
  --dp-page-title-ls: -1.5px;
  --dp-page-title-lh: 1.05;
  --dp-page-title-fs-sm: 28px;
  --dp-page-subtitle-fs: 17px;
  --dp-page-subtitle-lh: 1.8;
  --dp-page-body-fs: var(--dp-text-base);
  --dp-page-body-lh: 1.85;
  --dp-page-card-icon-fs: 36px;
  --dp-page-card-icon-sw: 1;   /* 36 / 36px -> a 1.5px keyline at this size */
  --dp-page-card-title-fs: 17px;
  --dp-page-card-title-fw: var(--dp-feature-title-fw);
  --dp-page-card-text-fs: var(--dp-feature-text-fs);
  --dp-page-card-text-lh: 1.75;
  --dp-page-panel-title-fs: 20px;
  --dp-page-panel-title-fw: var(--dp-fw-extrabold);
  --dp-page-intro-fs: 14px;
  --dp-page-ci-icon-fs: var(--dp-contact-icon-fs);
  --dp-page-ci-icon-sw: var(--dp-contact-icon-sw);   /* follows the contact icon, as its fs does */
  --dp-page-ci-label-fs: var(--dp-text-xs);
  --dp-page-ci-label-fw: var(--dp-fw-bold);
  --dp-page-ci-label-ls: 0.5px;
  --dp-page-ci-label-transform: var(--dp-contact-label-transform);
  --dp-page-ci-value-fs: 14px;
  --dp-page-ci-value-fw: var(--dp-contact-value-fw);
  --dp-page-trust-item-fs: var(--dp-text-sm);
  --dp-page-trust-item-fw: var(--dp-fw-semibold);
  --dp-page-faq-a-fs: 14px;
  --dp-page-faq-a-lh: 1.75;
  --dp-abt-quote-fs: 20px;
  --dp-abt-quote-fw: var(--dp-fw-extrabold);
  --dp-abt-check-icon-fs: 18px;
  --dp-abt-check-icon-sw: 2;   /* 36 / 18px -> a 1.5px keyline at this size */
  --dp-abt-check-icon-fw: var(--dp-fw-black);
  --dp-abt-check-title-fs: var(--dp-text-base);
  --dp-abt-check-title-fw: var(--dp-fw-extrabold);
  --dp-abt-check-desc-fs: 14px;
  --dp-abt-check-desc-lh: 1.6;
  --dp-abt-check-meta-fs: var(--dp-text-sm);
  --dp-abt-check-meta-lh: 1.6;
  --dp-abt-tl-badge-fs: 12px;
  --dp-abt-tl-badge-fw: var(--dp-fw-extrabold);
  --dp-abt-tl-title-fs: var(--dp-text-lg);
  --dp-abt-tl-title-fw: var(--dp-fw-extrabold);
  --dp-abt-tl-text-fs: 14px;
  --dp-abt-tl-text-lh: 1.75;
  --dp-abt-val-icon-fs: 28px;
  --dp-abt-val-icon-sw: 1.2857;   /* 36 / 28px -> a 1.5px keyline at this size */
  --dp-abt-val-icon-lh: 1;
  --dp-abt-val-title-fs: 20px;
  --dp-abt-val-title-fw: var(--dp-fw-extrabold);
  --dp-abt-val-text-fs: var(--dp-text-base);
  --dp-abt-val-text-lh: 1.75;
  --dp-abt-hero-pill-fs-sm: 11.5px;
  --dp-shp-trailer-list-fs: var(--dp-text-sm);
  --dp-shp-trailer-price-fs: var(--dp-text-sm);
  --dp-shp-trailer-price-fw: var(--dp-fw-semibold);
  --dp-shp-trailer-price-transform: uppercase;
  --dp-shp-trailer-price-ls: 1px;
  --dp-shp-trailer-price-strong-fs: var(--dp-text-base);
  --dp-shp-tbl-head-fs: var(--dp-text-xs);
  --dp-shp-tbl-head-fw: var(--dp-fw-extrabold);
  --dp-shp-tbl-head-ls: 1.5px;
  --dp-shp-tbl-head-transform: uppercase;
  --dp-shp-tbl-td-fs: 14px;
  --dp-shp-tbl-val-fw: var(--dp-fw-bold);
  --dp-shp-tbl-tag-fs: 10px;
  --dp-shp-tbl-tag-fw: var(--dp-fw-extrabold);
  --dp-shp-tbl-tag-color: var(--dp-accent-fg);
  --dp-shp-tbl-note-fs: 12px;
  --dp-shp-step-num-fs: 20px;
  --dp-shp-step-num-fw: var(--dp-fw-black);
  --dp-shp-step-title-fs: var(--dp-text-lg);
  --dp-shp-step-title-fw: var(--dp-fw-extrabold);
  --dp-shp-step-text-fs: 14px;
  --dp-shp-step-text-lh: 1.75;
  --dp-shp-trust-badge-fs: var(--dp-text-sm);
  --dp-shp-trust-badge-fw: var(--dp-fw-bold);
  --dp-shp-trust-badge-color: var(--dp-accent-text);
  --dp-ty-title-fs: clamp(28px,4vw,42px);
  --dp-ty-title-fw: var(--dp-fw-black);
  --dp-ty-title-ls: -1px;
  --dp-ty-sub-fs: var(--dp-text-md);
  --dp-ty-sub-lh: 1.8;
  --dp-ty-countdown-label-fs: 12px;
  --dp-ty-countdown-label-fw: var(--dp-fw-bold);
  --dp-ty-countdown-label-ls: 1px;
  --dp-ty-countdown-label-transform: uppercase;
  --dp-ty-countdown-val-fs: 36px;
  --dp-ty-countdown-val-fw: var(--dp-fw-black);
  --dp-ty-countdown-val-lh: 1;
  --dp-ty-countdown-unit-fs: var(--dp-text-xs);
  --dp-ty-countdown-unit-fw: var(--dp-fw-semibold);
  --dp-ty-countdown-unit-transform: uppercase;
  --dp-ty-countdown-unit-ls: 1px;
  --dp-ty-countdown-sep-fs: 28px;
  --dp-ty-countdown-sep-fw: 300;
  --dp-ty-next-title-fs: var(--dp-text-lg);
  --dp-ty-next-title-fw: var(--dp-fw-extrabold);
  --dp-ty-feature-title-fs: 17px;
  --dp-ty-feature-title-fw: var(--dp-feature-title-fw);
  --dp-ty-feature-text-fs: var(--dp-feature-text-fs);
  --dp-ty-feature-text-lh: var(--dp-feature-text-lh);
  --dp-ty-contact-note-fs: var(--dp-text-sm);
  --dp-ty-contact-item-fs: 14px;
  --dp-ty-contact-item-fw: var(--dp-fw-semibold);
  --dp-ty-trust-fs: 12px;
  --dp-ty-trust-fw: var(--dp-fw-bold);
  --dp-ty-trust-ls: 0.2px;
  --dp-ty-sec-head-title-fs: 24px;
  --dp-ty-sec-head-title-fw: var(--dp-fw-black);
  --dp-ty-sec-head-sub-fs: 14px;
  --dp-ty-review-text-fs: var(--dp-text-sm);
  --dp-ty-review-text-lh: 1.75;
  --dp-ty-review-av-fs: 12px;
  --dp-ty-review-av-fw: var(--dp-review-av-fw);
  --dp-ty-review-av-fg: var(--dp-accent-fg);
  --dp-ty-review-name-fs: var(--dp-text-sm);
  --dp-ty-review-role-fs: var(--dp-text-xs);
  --dp-ty-inv-badge-fs: var(--dp-fcard-badge-fs);
  --dp-ty-inv-badge-fw: var(--dp-fcard-badge-fw);
  --dp-ty-inv-badge-color: var(--dp-accent-fg);
  --dp-ty-inv-type-fs: var(--dp-text-xs);
  --dp-ty-inv-type-fw: var(--dp-fw-bold);
  --dp-ty-inv-type-ls: 0.5px;
  --dp-ty-inv-type-transform: uppercase;
  --dp-ty-inv-title-fs: var(--dp-text-md);
  --dp-ty-inv-title-fw: var(--dp-fw-extrabold);
  --dp-ty-inv-price-fs: var(--dp-fcard-price-fs);
  --dp-ty-inv-price-fw: var(--dp-fcard-price-fw);
  --dp-ty-inv-price-lh: 1;
  --dp-ty-inv-price-call-fs: var(--dp-text-md);
  --dp-ty-inv-price-call-fw: var(--dp-fw-bold);
  --dp-ty-inv-price-call-ls: 0.3px;
  --dp-ty-inv-btn-fs: var(--dp-text-sm);
  --dp-ty-inv-btn-fw: var(--dp-fw-extrabold);
  --dp-ty-inv-btn-ls: 0.3px;
  --dp-404-icon-fs: clamp(36px,6vw,64px);
  --dp-404-title-fs: clamp(36px,5vw,56px);
  --dp-404-title-fw: var(--dp-fw-black);
  --dp-404-title-ls: -1px;
  --dp-404-sub-fs: 17px;
  --dp-404-sub-lh: 1.8;
  --dp-404-or-fs: var(--dp-text-sm);
  --dp-404-phone-fs: 24px;
  --dp-404-phone-fw: var(--dp-fw-black);
  --dp-404-links-title-fs: 14px;
  --dp-404-links-title-fw: var(--dp-fw-extrabold);
  --dp-404-links-title-ls: 1px;
  --dp-404-links-title-transform: uppercase;
  --dp-404-link-fs: 14px;
  --dp-404-link-fw: var(--dp-fw-semibold);
  --dp-legal-title-fs: clamp(32px,4vw,48px);
  --dp-legal-title-fw: var(--dp-fw-black);
  --dp-legal-title-ls: -1px;
  --dp-legal-updated-fs: var(--dp-text-sm);
  --dp-legal-h2-fs: 20px;
  --dp-legal-h2-fw: var(--dp-fw-extrabold);
  --dp-legal-text-fs: var(--dp-text-base);
  --dp-legal-text-lh: 1.85;
  --dp-btt-label-fs: 9px;
  --dp-btt-label-fw: var(--dp-fw-extrabold);
  --dp-btt-label-ls: 1.2px;
  --dp-btt-label-lh: 1;
  --dp-bc-fs: var(--dp-text-sm);

  /* -- transaction -- */
  --dp-rv-kicker-ls: 2.5px;
  --dp-rv-heading-fs: 30px;
  --dp-rv-heading-fw: var(--dp-fw-black);
  --dp-rv-subtitle-fs: var(--dp-text-base);
  --dp-rv-step-num-fs: 13px;
  --dp-rv-step-num-fw: var(--dp-fw-extrabold);
  --dp-rv-step-lbl-fs: var(--dp-text-sm);
  --dp-rv-step-lbl-fw: var(--dp-fw-semibold);
  --dp-rv-title-fs: 36px;
  --dp-rv-title-fw: var(--dp-fw-black);
  --dp-rv-title-ls: -0.5px;
  --dp-rv-sub-fs: 17px;
  --dp-rv-card-title-fs: 21px;
  --dp-rv-card-title-fw: var(--dp-fw-extrabold);
  --dp-rv-card-title-lh: 1.3;
  --dp-rv-card-final-fs: 28px;
  --dp-rv-card-final-fw: var(--dp-fw-black);
  --dp-rv-card-note-fs: var(--dp-text-sm);
  --dp-rv-fallback-fs: var(--dp-text-base);
  --dp-rv-trust-pill-fs: var(--dp-text-sm);
  --dp-rv-trust-pill-fw: var(--dp-fw-bold);
  --dp-rv-trust-pill-ls: 0.2px;
  --dp-rv-trust-pill-icon-fs: 15px;
  --dp-rv-trust-pill-icon-lh: 1;
  --dp-rv-form-title-fs: 28px;
  --dp-rv-form-title-fw: var(--dp-fw-black);
  --dp-rv-form-title-ls: -0.5px;
  --dp-rv-form-sub-fs: var(--dp-text-base);
  --dp-rv-form-sub-lh: 1.6;
  --dp-rv-req-fw: var(--dp-fw-black);
  --dp-rv-form-h3-fs: 18px;
  --dp-rv-form-h3-fw: var(--dp-fw-black);
  --dp-rv-form-h3-ls: -0.2px;
  --dp-rv-file-btn-fw: var(--dp-fw-bold);
  --dp-rv-file-btn-fs: 13px;
  --dp-rv-file-btn-color: var(--dp-accent-fg);
  --dp-rv-review-text-fs: 14px;
  --dp-rv-review-av-fs: 14px;
  --dp-rv-faq-q-fs: var(--dp-text-base);
  --dp-rv-faq-q-fw: var(--dp-fw-bold);
  --dp-rv-faq-icon-fs: 22px;
  --dp-rv-faq-icon-fw: 300;
  --dp-rv-faq-a-fs: 14px;
  --dp-rv-faq-a-lh: 1.75;
  --dp-rv-cf7-notice-fs: 14px;
  --dp-rv-title-fs-sm: 28px;
  --dp-rv-heading-fs-sm: 24px;
  --dp-rv-card-title-fs-sm: 20px;
  --dp-rv-card-final-fs-sm: 26px;
  --dp-rv-step-num-fs-sm: 11px;
  --dp-rv-step-lbl-fs-sm: 11.5px;
  --dp-rv-step-lbl-fw-sm: var(--dp-fw-bold);
  --dp-rv-step-lbl-lh-sm: 1.2;
  --dp-rv-trust-pill-fs-xs: 11.5px;
  --dp-rv-trust-pill-icon-fs-xs: 13px;

  /* ══ sweep pass: component tokens for declarations the earlier colour/type
        passes could not reach (inline style="" attributes and a few rules).
        Every value is the literal the theme renders today, verbatim. ══ */
  --dp-home-featured-empty-color: rgba(255,255,255,0.4);   /* front-page.php  featured empty-state wrapper */
  --dp-home-featured-empty-fs: 15px;                       /* front-page.php  featured empty-state <p> */
  --dp-home-featured-empty-sub-fs: 14px;                   /* front-page.php  featured empty-state second <p> */
  --dp-ty-next-empty-color: rgba(255,255,255,0.5);         /* page-thank-you.php  random-inventory empty state */
  --dp-sl-noimg-icon-color: rgba(255,255,255,0.18);        /* single-listing.php  no-image placeholder svg */
  --dp-con-cf7-notice-fs: 14px;                            /* page-contact.php  "CF7 not configured" notice */
  --dp-con-cf7-notice-border: 1px solid rgba(255,255,255,0.08);
  --dp-con-cf7-notice-color: rgba(255,255,255,0.45);
  --dp-shp-cf7-notice-fs: 14px;                            /* page-shipping.php  same notice */
  --dp-shp-cf7-notice-border: 1px solid rgba(255,255,255,0.08);
  --dp-shp-cf7-notice-color: rgba(255,255,255,0.45);
  --dp-rv-cf7-notice-border: 1px solid rgba(255,255,255,0.08);  /* page-reserve.php  (-fs already existed) */
  --dp-rv-cf7-notice-color: rgba(255,255,255,0.45);

  /* The last four inline style="" paints that still read a wizard property or
     a hard literal. A skin cannot reach an inline attribute at all, so each is
     routed through a token here; every default below is the literal the theme
     rendered before, so an unskinned page is byte-identical. */
  --dp-cf7-notice-link-color: var(--dp-accent);            /* the "Set up forms" link in all four CF7 notices */
  --dp-home-featured-empty-link-color: var(--dp-accent);   /* front-page.php  "Contact us" in the empty state */
  --dp-legal-inline-link-color: var(--dp-accent);          /* page-terms.php  inline "Privacy Policy" link */
  --dp-fcard-specs-sep-color: rgba(255,255,255,0.25);      /* front-page.php  · separator between spec items */
  --dp-cf7-ok-bg: color-mix(in srgb, var(--dp-accent) 12%, transparent);    /* style.css .wpcf7-mail-sent-ok */
  --dp-cf7-ok-border: 1px solid color-mix(in srgb, var(--dp-accent) 24%, transparent);
  --dp-cf7-ok-color: var(--dp-accent-text);                /* style.css .wpcf7-mail-sent-ok */
  --dp-testimonial-border-hover: color-mix(in srgb, var(--dp-accent) 24%, transparent); /* style.css .dp-testimonial:hover */
  --dp-faq-item-border-hover: color-mix(in srgb, var(--dp-accent) 22%, transparent);    /* style.css .dp-faq-item:hover */
  --dp-step-card-border-hover: color-mix(in srgb, var(--dp-accent) 24%, transparent);   /* style.css .dp-step-card:hover */
  --dp-qv-thumb-border: 2px solid transparent;             /* style.css .dp-qv-thumb resting border */
  --dp-cta-banner-ghost-bg: transparent;                   /* style.css .dp-cta-banner__btn--ghost */
  /* The ink the ghost button's rule is drawn from. It defaults to --dp-cta-fg,
     so unskinned rendering is unchanged, but --dp-cta-fg is one of the wizard's
     seventeen !important properties and no skin can move it. Routing the resting
     border and the hover border through this one component token lets a skin set
     the ghost rule to its own ink — the label beside it (--dp-cta-banner-ghost-color)
     is already skin-ownable, and the two have to agree. */
  --dp-cta-banner-ghost-ink: var(--dp-cta-fg);
  --dp-cta-banner-ghost-border: 2px solid color-mix(in srgb, var(--dp-cta-banner-ghost-ink) 70%, transparent);
  --dp-cta-banner-ghost-border-color-hover: var(--dp-cta-banner-ghost-ink);
  --dp-cta-banner-ghost-color: var(--dp-cta-fg);
  --dp-footer-border-top: 1px solid transparent;           /* footer.php .dp-footer */
}

/* ══════════════════════════════════════════════
   RESET & BASE
   ══════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  padding: 0;
  background: var(--dp-bg);
  color: var(--dp-text);
  font-family: var(--dp-font);
  font-feature-settings: var(--dp-font-feature-settings);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Every skin declares a display face in --dp-font-heading, but nothing in the
   theme consumed it, so every heading fell through to body's --dp-font. This
   is the base consumer: any real heading element takes the display face, and
   the title/kicker classes below (many of which sit on divs and spans) name
   the token explicitly. Unskinned this changes nothing — :root derives
   --dp-font-heading from --dp-font, which is exactly what these elements
   inherited from body before. */
h1, h2, h3, h4, h5, h6 { font-family: var(--dp-font-heading); }

a { color: inherit; }
img { max-width: 100%; height: auto; display: block; }

/* ══════════════════════════════════════════════
   LAYOUT
   ══════════════════════════════════════════════ */
.dp-shell {
  width: min(100% - 32px, var(--dp-shell));
  margin: 0 auto;
}

.dp-section {
  position: relative;
  padding: 80px 0;
}

.dp-section::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: min(92%, 1320px);
  height: 1px;
  background: var(--dp-hairline);
  opacity: var(--dp-hairline-opacity);
  pointer-events: none;
}

/* ══════════════════════════════════════════════
   CARDS & SECTION WRAPPERS
   ══════════════════════════════════════════════ */
.dp-card {
  position: relative;
  background: var(--dp-card-bg);
  border: var(--dp-card-border);
  border-radius: var(--dp-radius);
  box-shadow: var(--dp-shadow);
  overflow: hidden;
}

.dp-card::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--dp-card-glow);
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
}

.dp-card:hover::before {
  opacity: var(--dp-card-glow-opacity);
}

.dp-section-wrapper {
  position: relative;
  padding: 64px 54px;
  text-align: center;
  background: var(--dp-wrapper-bg);
  border: var(--dp-wrapper-border);
  border-radius: var(--dp-radius);
  box-shadow: var(--dp-shadow);
  overflow: hidden;
}

.dp-section-wrapper::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--dp-wrapper-glow);
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
}

.dp-section-wrapper:hover::before {
  opacity: var(--dp-wrapper-glow-opacity);
}

/* ══════════════════════════════════════════════
   TYPOGRAPHY
   ══════════════════════════════════════════════ */
.dp-kicker {
  font-family: var(--dp-font-heading);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 18px;
  border-radius: var(--dp-kicker-radius);
  background: var(--dp-kicker-bg);
  border: var(--dp-kicker-border);
  color: var(--dp-kicker-color);
  font-size: var(--dp-kicker-fs);
  font-weight: var(--dp-kicker-fw);
  letter-spacing: var(--dp-kicker-ls);
  text-transform: var(--dp-kicker-transform);
}

/* NOTE: .dp-section-head is declared once, further down this file (the
   "SECTION HEAD (kicker + title + subtitle)" block). A second, earlier
   declaration used to sit here with max-width:920px / margin-bottom:52px;
   it had the same specificity and lost to the later one, so it never
   rendered and only made the file contradict itself. Removed. */

.dp-title {
  font-family: var(--dp-font-heading);
  margin: 0;
  color: var(--dp-text);
  font-size: var(--dp-title-fs);
  line-height: var(--dp-title-lh);
  font-weight: var(--dp-title-fw);
  letter-spacing: var(--dp-title-ls);
}

.dp-title--accent {
  display: block;
  color: var(--dp-title-accent-color);
}

.dp-line {
  width: 96px;
  height: 4px;
  margin: 22px auto 24px;
  border-radius: var(--dp-line-radius);
  background: linear-gradient(90deg, var(--dp-accent), var(--dp-accent-dark));
  box-shadow: var(--dp-line-shadow);
}

.dp-line--left {
  margin-left: 0;
  margin-right: 0;
}

.dp-subtitle {
  color: var(--dp-subtitle-color);
  font-size: var(--dp-subtitle-fs);
  line-height: var(--dp-subtitle-lh);
}

.dp-body {
  color: var(--dp-text-soft);
  font-size: var(--dp-subtitle-fs);
  line-height: var(--dp-subtitle-lh);
  margin: 0 0 22px;
}

.dp-note {
  color: var(--dp-note-color);
  font-size: var(--dp-note-fs);
  line-height: var(--dp-note-lh);
  text-align: center;
}

.dp-highlight {
  color: var(--dp-highlight-color);
  font-weight: var(--dp-highlight-fw);
}

/* ══════════════════════════════════════════════
   BUTTONS
   ══════════════════════════════════════════════ */
.dp-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 56px;
  padding: 0 28px;
  border-radius: var(--dp-btn-radius);
  text-decoration: none;
  font-size: var(--dp-btn-fs);
  font-weight: var(--dp-btn-fw);
  font-family: var(--dp-font-ui);
  letter-spacing: var(--dp-btn-ls);
  border: var(--dp-btn-border);
  cursor: pointer;
  transition: var(--dp-btn-transition);
  overflow: hidden;
  white-space: nowrap;
}
.dp-btn:hover { transform: translateY(-2px); }
/* ── Pressed state ──
   The only :active declaration the theme shipped was the translateY(0) below,
   which merely cancels the hover lift — so a control activated without a
   hover first (i.e. every touch) gave no feedback at all: forcing :active
   changed nothing on 27 of 27 controls on /reserve/. Opacity rather than a
   background or box-shadow step, for two reasons: it reads on a dark plate
   and a light one alike, and .dp-btn:active setting box-shadow would outrank
   .dp-btn:focus-visible and take the keyboard ring away for the length of an
   Enter press. .dp-btt is listed via its --visible class because the base
   shows that button with opacity (functions.php, (0,2,0)) and a bare
   .dp-btt:active at (0,1,1) would lose to it. */
.dp-btn:active,
.dp-sticky-btn:active,
.dp-header__call:active,
.dp-mobile-nav__call:active,
.dp-btt--visible:active,
.wpcf7-form input[type="submit"]:active,
.wpcf7-form button[type="submit"]:active,
/* 3.2.0 — the fourteen controls below reached this audit with NO pressed state
   at all. They are added to this existing list rather than given a rule of
   their own, so there stays exactly ONE definition of what "pressed" means.
   opacity composites and cannot move anything. translateY(0) CANCELS a hover
   lift where one exists, which is a deliberate "pressed" affordance — but it is
   a real movement, not a no-op: a control that lifts 5px on hover returns to 0
   on press. The original wording here claimed neither declaration could move a
   box; that was wrong, and it is corrected rather than deleted so the next
   reader knows the claim was checked. The resting layout is untouched, which is
   what the geometry freeze measures, but anyone adding a control to this list
   should first check whether it has a hover transform. */
.dp-cta-banner__btn:active,
.dp-sl-gal-btn:active,
.dp-sl-lb-trigger:active,
.dp-sl-reserve:active,
.dp-sl-share__btn:active,
.dp-sl-thumb:active,
.dp-sl-back:active,
.dp-404-phone:active,
.dp-abt-ci:active,
.dp-con-ci:active,
.dp-ty-contact__item:active,
.dp-inv-page-btn:active,
.dp-faq-item__q:active,
.dp-header__hamburger:active,
/* 3.2.0 buttons pass — the eight below are the rest of what the inventory
   found with no pressed state. They join THIS list rather than getting rules
   of their own, so "pressed" still has exactly one definition.
     .dp-qv-trigger      — 12 per inventory page, and 3.2.0's colour rule
                           names the quick-view trigger as an action.
     .dp-sl-specs-toggle — pressed on modern only before this.
   The six card links are added as a FAMILY. The brief named
   .dp-home-fcard__body-link alone, but pressing one card link and not the
   eleven identical ones beside it on /inventory/ is a worse inconsistency
   than the missing state was; they all press now, or none would.
   .dp-ty-inv-card is the ancestor of .dp-ty-inv-card__btn: that "button" is
   a <span> inside an <a>, so it cannot take a press of its own (see §7 of
   the report) — the card it lives in takes it, which is the control the
   visitor is actually activating. */
/* .dp-qv-trigger IS NOT IN THIS LIST, AND THE REASON IS MEASURED, NOT
   THEORETICAL. It was, for about an hour. This rule's second declaration is
   `transform: translateY(0)`, which is a no-op for every control here
   because none of them carries a transform at rest — except that one, which
   is absolutely positioned and centred by `transform: translate(-50%,-50%)`.
   Adding it here replaced the centring with translateY(0) and the button
   jumped +70.52px in x and +19.50px in y the instant it was pressed, on all
   three skins at both widths (heavy 141.05x39 at x=228.13 -> x=298.66;
   modern 151.61x38 at 222.85 -> 298.66; classic 154.52x38 at 221.40 ->
   298.66). A press that moves a button 70px is worse than a press that does
   nothing, and a geometry diff of resting pages cannot see it. Its press is
   opacity-only and lives beside the reveal rule that forces its opacity —
   see .dp-inv-card__media:hover .dp-qv-trigger:active in the QUICK VIEW
   section. */
.dp-sl-specs-toggle:active,
.dp-home-fcard__body-link:active,
.dp-home-fcard__img-link:active,
.dp-inv-card__body-link:active,
.dp-inv-card__img-link:active,
.dp-sl-rel-card:active,
/* Listed twice for the same reason .dp-btt is listed via --visible: the
   related-listing cards carry .dp-scroll-reveal, and `.dp-scroll-reveal
   .is-visible { opacity: 1 }` is (0,2,0) declared LATER in this file, so the
   bare .dp-sl-rel-card:active at (0,2,0) loses to it the moment the reveal
   script runs — measured: opacity stayed 1 on heavy and classic. The
   .is-visible twin is (0,3,0) and reaches it. The bare selector stays for the
   case the reveal never runs, where .dp-scroll-reveal alone is (0,1,0) and
   the press already wins. Same rule, same token, one definition. */
.dp-sl-rel-card.is-visible:active,
.dp-ty-inv-card:active {
  transform: translateY(0);
  opacity: var(--dp-pressed-opacity);
}

/* ── The hover veil, applied ──
   One shared list, the same shape as the pressed list above, so "hovered"
   has one definition for the controls that had none. See --dp-hover-veil.
   Paint only: an inset box-shadow composites over the control's own
   background and cannot change its box. */
.dp-sticky-btn:hover,
.dp-header__hamburger:hover {
  box-shadow: var(--dp-hover-veil-shadow);
}

/* ── PRIMARY — accent color (main action) ── */
.dp-btn--primary {
  background: linear-gradient(135deg, var(--dp-accent), var(--dp-accent-dark));
  color: var(--dp-btn-primary-fg);
  box-shadow: var(--dp-btn-primary-shadow);
}
.dp-btn--primary:hover {
  box-shadow: var(--dp-btn-primary-shadow-hover);
}

/* ── CTA — urgent action (call, buy) ── */
.dp-btn--cta,
.dp-btn--call {
  background: linear-gradient(135deg, var(--dp-cta), var(--dp-cta-dark));
  color: var(--dp-btn-cta-fg);
  box-shadow: var(--dp-btn-cta-shadow);
}
.dp-btn--cta:hover,
.dp-btn--call:hover {
  box-shadow: var(--dp-btn-cta-shadow-hover);
  color: var(--dp-btn-cta-fg);
}
.dp-btn--call .dp-btn-icon,
.dp-btn--cta .dp-btn-icon {
  width: 18px; height: 18px; flex-shrink: 0;
  fill: none; stroke: currentColor;
  /* 3.2.0 keyline unification — was 2.5, which paints 2.5 * 18/24 = 1.875px.
     36/18 = 2 paints 1.50px, the same keyline the icons in inc/icons.php
     paint at every size. stroke-width cannot move a box: the svg is 18x18 by
     the two declarations above and it clips its own content. */
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}

/* ── GHOST — transparent with border (secondary action) ── */
.dp-btn--ghost,
.dp-btn--secondary {
  color: var(--dp-btn-ghost-fg);
  background: var(--dp-btn-ghost-bg);
  border: var(--dp-btn-ghost-border);
  backdrop-filter: var(--dp-btn-ghost-blur);
}
.dp-btn--ghost:hover,
.dp-btn--secondary:hover {
  background: var(--dp-btn-ghost-bg-hover);
  border-color: var(--dp-btn-ghost-border-hover);
  color: var(--dp-btn-ghost-fg);
}

/* ── DARK — the secondary of the listing sidebar's two actions ──
   3.2.0 hierarchy repair. On modern and classic --dp-btn-dark-bg and
   --dp-btn-cta-bg were the SAME colour and --dp-btn-dark-fg and
   --dp-btn-cta-fg were the same ink (modern #1c2133 on #f4f6fb for both,
   classic #1B1A17 on #F7F3EC for both), so "Call Now" and "Make Inquiry"
   sat side by side in the sidebar as two identical plates. The one thing
   that would have told them apart, --dp-btn-dark-border, never painted:
   .dp-sl-btn-v2 declares `border: none` and is declared later.

   Which one keeps the plate is not a taste call. 3.2.0's rule is that the
   saturated action colour goes where something happens, and of these two
   the higher-intent action is the phone call. So --cta is untouched — not
   one declaration of it changes — and --dark becomes the secondary: each
   skin points --dp-btn-dark-* at the ghost family it already defines for
   exactly this job, and the keyline arrives as a box-shadow, which
   `border: none` cannot cancel and which cannot move the box. Same box,
   different paint, which is the whole boundary of this round. */
.dp-btn--dark {
  background: var(--dp-btn-dark-bg);
  color: var(--dp-btn-dark-fg);
  border: var(--dp-btn-dark-border);
  box-shadow: var(--dp-btn-dark-keyline);
}
.dp-btn--dark:hover {
  background: var(--dp-btn-dark-bg-hover);
  border-color: var(--dp-btn-dark-border-hover);
}

/* ── WHITE — inverted, for use on colored backgrounds like CTA banner ── */
.dp-btn--white {
  background: var(--dp-btn-white-bg);
  color: var(--dp-cta);
  font-weight: var(--dp-btn-white-fw);
}
.dp-btn--white:hover {
  background: var(--dp-btn-white-bg-hover);
  box-shadow: var(--dp-btn-white-shadow-hover);
}

/* ─── SIDEBAR BUTTON LAYOUT (single-listing sidebar) ───
   3.2.0 consolidation. This class was declared TWICE — here, and again in an
   inline <style> in single-listing.php that the browser sees later and that
   therefore won every property the two shared. The box a visitor actually
   measured was assembled out of both files: padding from the template,
   min-height from here. Two of the declarations that stood here were dead:
     padding: 0 20px            — the template's 14px 16px won on every page.
     font-size: --dp-sl-btn-v2-fs — the template's var(--dp-btn-fs) won.
   Modern is the proof for the second one: its --dp-sl-btn-v2-fs is 14px
   while both sidebar buttons measure 15px at 1440. On heavy and classic the
   two tokens are equal, so only modern can tell them apart.

   The template's block is now deleted and its WINNING values are written
   here, so there is one declaration of this box. --dp-sl-btn-v2-fs is
   deleted from all four files; nothing else referenced it.

   THE ORDER OF THIS BLOCK IS LOAD-BEARING. `border: none` used to arrive
   after style.css and is what stops --dp-btn-dark-border painting on "Make
   Inquiry". This block sits AFTER .dp-btn--cta / --dark / --ghost above, so
   `border: none` still wins over all three exactly as it did from the
   template. Moving it above them would put a border back on the button. */
.dp-sl-btn-v2 {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 52px;
  padding: 14px 16px;
  width: 100%;
  border: none;
  border-radius: var(--dp-radius-xs);
  font-family: var(--dp-font-ui);
  font-size: var(--dp-btn-fs);
  font-weight: var(--dp-btn-fw);
  letter-spacing: var(--dp-btn-ls);
  text-decoration: none;
  cursor: pointer;
  transition: all .25s ease;
}
.dp-sl-btn-v2 svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

.dp-btn__shine {
  position: absolute;
  top: 0;
  left: -120%;
  width: 70%;
  height: 100%;
  background: var(--dp-btn-shine);
  transform: skewX(-20deg);
}

.dp-btn--primary:hover .dp-btn__shine,
.dp-btn--call:hover .dp-btn__shine,
.dp-btn--cta:hover .dp-btn__shine,
.dp-btn--dark:hover .dp-btn__shine {
  left: 145%;
  transition: left 0.7s ease;
}

.dp-btn__arrow {
  transition: transform 0.25s ease;
}

.dp-btn:hover .dp-btn__arrow {
  transform: translateX(3px);
}

/* ══════════════════════════════════════════════
   STICKY BAR (universal)
   ══════════════════════════════════════════════ */
.dp-sticky-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 99999;
  display: none;
  /* Was grid-template-columns:1fr 1fr. Auto columns instead, so the bar still
     splits in half with both buttons but fills the width correctly when a
     template omits one — e.g. when the Contact page is missing and the
     "Request Info" half is not rendered (see dp_page_link()). */
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  box-shadow: var(--dp-sticky-shadow);
}

.dp-sticky-btn {
  min-height: 58px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  text-decoration: none !important;
  font-size: var(--dp-sticky-fs);
  font-weight: var(--dp-sticky-fw);
  color: var(--dp-sticky-fg) !important;
  border: none;
  outline: none;
  cursor: pointer;
  /* Was `filter 0.2s`. Nothing on this control has animated a filter since
     --dp-sticky-active-filter was retired (see the note below), so the
     declaration was transitioning a property that never changes. It now
     carries the hover veil in and out. */
  transition: box-shadow 0.2s;
  letter-spacing: var(--dp-sticky-ls);
}

/* ── The sticky bar's pressed state is the site-wide one, above ─────────────
   2.9.4 pressed this one control with `filter: var(--dp-sticky-active-filter)`
   while nothing else on the site had a pressed state at all. Once the rule
   above gave the seven canonical controls `opacity: var(--dp-pressed-opacity)`
   the two stacked on .dp-sticky-btn on every skin, and the press measured
   roughly twice the size of every other control's: at 375 on
   /inventory/dpfx-available-full/ the rest-to-pressed luminance step was
   1.99x unskinned, 1.98x classic, 2.19x heavy and 2.44x modern, against
   1.43x/1.91x/1.55x for .dp-header__call under the opacity rule alone.

   So the filter rule is gone and the sticky button presses the way every
   other control does. Opacity rather than brightness for the whole site
   because opacity is self-aiming: it blends the control toward whatever is
   behind it, so a dark button on classic's paper page lightens and a light
   button on modern's black page darkens, with one number. brightness() has to
   be re-aimed per skin — classic had to invert it to 1.18 — which is the
   per-skin divergence this pass exists to remove. Measured opacity-only
   steps: 1.58x / 1.73x / 1.54x / 1.64x, tighter than filter-only's
   1.29x / 1.21x / 1.48x / 1.52x and in the same band as the rest of the site.

   A skin retunes the press through --dp-pressed-opacity and may extend the
   selector list to controls the base does not reach. It may not add a second
   property to a control the base already presses.

   Unskinned cost, recorded deliberately: a 2.9.4 site's sticky button presses
   at 1.58x instead of 1.29x. Nothing moves, and the state is invisible until
   a finger is down. --dp-sticky-active-filter is retired from this file and
   from all three skins. */

.dp-sticky-btn svg {
  flex-shrink: 0;
}

.dp-sticky-btn--call {
  background: var(--dp-sticky-call-bg);
}

.dp-sticky-btn--info {
  background: var(--dp-sticky-info-bg);
  border-left: var(--dp-sticky-info-border);
}

/* ── Reserve the sticky bar's own height on the scrolling document ──────────
   FIX: .dp-sticky-bar is position:fixed at bottom:0 and 58px tall (its two
   buttons carry min-height:58px), and it is displayed at every width up to
   960px. Nothing reserved that space, so the last 58px of EVERY page sat
   permanently underneath it: the footer copyright was sliced in half and the
   Privacy / Terms links in the footer bottom bar could not be tapped at all
   on phones, tablets and small laptops.

   The reserve has to go on the scrolling document, i.e. <body>. The theme
   used to put a 70px padding-bottom on #dp-main-content (front-page.php's
   .dp-home) instead — but #dp-main-content is a block ABOVE the footer, so
   padding there only pushed the footer further down the page and left the
   footer itself occluded exactly as before. Padding on <body> lengthens the
   document, so the page can scroll those 58px further and the footer clears
   the bar.

   Kept in step with the two `display:grid` rules below: the padding is
   applied at exactly the widths where the bar is on screen, and nothing is
   reserved above 960px where the bar is display:none.

   (The two 1024px figures in this comment were the stale leftovers of the
   earlier breakpoint. The bar itself moved to max-width:960px in the same
   pass that added this reserve — see the RESPONSIVE section — so the rule
   was right and only the prose was wrong. 1024px is now nothing but the
   typography breakpoint, and no sticky-bar rule fires there.) */
:root {
  --dp-sticky-h: 58px;   /* == .dp-sticky-btn min-height */
}

@media (max-width: 960px) {
  body { padding-bottom: var(--dp-sticky-h); }
}

/* ── In-page anchors must clear the fixed header ────────────────────────────
   FIX: .dp-header is position:fixed, so an element scrolled to by an in-page
   anchor lands under it. The inventory hero's primary button sends the
   visitor to #dpInvFilters and the filter bar ended up at top:-32px — the
   thing they were sent to was behind the header. Every in-page anchor and
   every scrollIntoView() call in the theme had the same problem.

   scroll-padding-top on the scroll container (the root element) is the one
   place that fixes all of them at once: the browser applies it to fragment
   navigation, to scrollIntoView() and to focus scrolling, so no per-anchor
   scroll-margin and no JS offset maths is needed.

   --dp-header-h tracks the real header height at each breakpoint — the same
   numbers .dp-header__inner sets and <body> already reserves as padding-top
   in header.php (100px, 80px from 960px down). --dp-anchor-gap is breathing
   room so the target does not sit flush against the header's bottom edge.

   The admin bar: WordPress puts .admin-bar on <body>, not on <html>, and
   scroll-padding has to be set on the scroll container, so the admin-bar
   cases are matched with :has(). The bar is 32px, 46px below 782px, and
   below 600px it scrolls away with the page (header.php sets
   body.admin-bar .dp-header{top:0} there), so nothing extra is added. */
:root {
  --dp-header-h: 100px;
  --dp-anchor-gap: 16px;
  --dp-admin-bar-h: 0px;
}

html {
  scroll-padding-top: calc(var(--dp-header-h) + var(--dp-admin-bar-h) + var(--dp-anchor-gap));
}

html:has(body.admin-bar) { --dp-admin-bar-h: 32px; }

@media (max-width: 960px) {
  :root { --dp-header-h: 80px; }
}

@media screen and (max-width: 782px) {
  html:has(body.admin-bar) { --dp-admin-bar-h: 46px; }
}

@media screen and (max-width: 600px) {
  html:has(body.admin-bar) { --dp-admin-bar-h: 0px; }
}

/* ══════════════════════════════════════════════
   LEGAL PAGES (Privacy Policy + Terms of Service)
   ══════════════════════════════════════════════
   FIX: this block used to live in a <style> tag inside
   page-privacy-policy.php. page-terms.php uses exactly the same .dp-legal-*
   markup but shipped no CSS of its own, so the Terms of Service page rendered
   as raw full-width prose with a 0px gutter — at 375px the text touched both
   bezels. The rules are shared markup, so they belong in the shared
   stylesheet, where both templates (and any future legal template) get them.
   Values are unchanged; every colour and size is still a token, so all three
   skins repaint this page exactly as they did the Privacy Policy. */
.dp-legal {
  background: var(--dp-bg);
  color: var(--dp-text);
  padding: 20px 0 100px;
}

/* FIX (uniformity audit): nav.dp-breadcrumbs always wraps its content in
   .dp-shell. That is right when the breadcrumb is a top-level sibling, but on
   the listing and legal templates it sits INSIDE .dp-sl-con / .dp-legal-con,
   which already establish the page's content column — so the gutter was
   charged twice and the breadcrumb text started 16px right of the back link
   or page title directly beneath it. */
.dp-sl-con .dp-breadcrumbs .dp-shell,
.dp-legal-con .dp-breadcrumbs .dp-shell {
  width: 100%;
}

.dp-legal-con {
  width: min(100% - 32px, 860px);
  margin: 0 auto;
}

.dp-legal-title {
  font-family: var(--dp-font-heading);
  font-size: var(--dp-legal-title-fs);
  font-weight: var(--dp-legal-title-fw);
  margin: 16px 0 8px;
  letter-spacing: var(--dp-legal-title-ls);
}

.dp-legal-updated {
  color: var(--dp-legal-updated-color);
  font-size: var(--dp-legal-updated-fs);
  margin: 0 0 32px;
}

.dp-legal-body {
  background: var(--dp-legal-body-bg);
  border: var(--dp-legal-body-border);
  border-radius: var(--dp-radius);
  padding: 40px;
}

.dp-legal-body h2 {
  font-family: var(--dp-font-heading);
  color: var(--dp-accent);
  font-size: var(--dp-legal-h2-fs);
  font-weight: var(--dp-legal-h2-fw);
  margin: 32px 0 12px;
  padding-top: 20px;
  border-top: var(--dp-legal-divider);
}

.dp-legal-body h2:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

.dp-legal-body p {
  color: var(--dp-legal-text-color);
  font-size: var(--dp-legal-text-fs);
  line-height: var(--dp-legal-text-lh);
  margin: 0 0 14px;
}

/* FIX (audit low): the inline "Privacy Policy" link carried its colour in a
   style="" attribute on the <a> in page-terms.php, which no stylesheet rule
   could ever override — and it had no hover or focus treatment at all, the
   only link on the site that did not respond to the pointer. The colour now
   lives here with the rest of the paint, and the hover thickens the underline
   so it does not depend on colour alone. */
.dp-legal-body a {
  color: var(--dp-legal-inline-link-color);
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color .2s ease, text-decoration-thickness .2s ease;
}
.dp-legal-body a:hover,
.dp-legal-body a:focus-visible {
  color: var(--dp-legal-inline-link-hover, var(--dp-text));
  text-decoration-thickness: 2px;
}

@media (max-width: 768px) {
  .dp-legal-body { padding: 24px 18px; }
}

/* ══════════════════════════════════════════════
   GENERIC PAGE BODY (page.php)
   ══════════════════════════════════════════════
   page.php is the fallback for a page nobody designed a template for — the
   file that stops WordPress answering such a URL with a 200 and an empty
   body. It reuses .dp-legal-body for the column, the panel and the h2/p/a
   rules, and adds ONLY the elements the legal templates never needed: they
   hand-write their markup, and the block editor does not. Nothing here is a
   new design decision — every value is a token or a number the rest of this
   stylesheet already uses, and headings, lists and quotes take the same
   colours and sizes as the paragraphs they sit with, so one page body is one
   component. No page in the theme uses this block today; it exists so the
   next one the dealer adds is not a white screen. */
.dp-page-body > *:first-child { margin-top: 0; }
.dp-page-body > *:last-child  { margin-bottom: 0; }

.dp-page-body h3,
.dp-page-body h4 {
  font-family: var(--dp-font-heading);
  color: var(--dp-text);
  font-weight: var(--dp-legal-h2-fw);
  margin: 24px 0 12px;
}
.dp-page-body h3 { font-size: var(--dp-legal-h2-fs); }
.dp-page-body h4 { font-size: var(--dp-legal-text-fs); }

.dp-page-body ul,
.dp-page-body ol {
  color: var(--dp-legal-text-color);
  font-size: var(--dp-legal-text-fs);
  line-height: var(--dp-legal-text-lh);
  margin: 0 0 14px;
  padding-left: 22px;
}
.dp-page-body li { margin-bottom: 6px; }
.dp-page-body li:last-child { margin-bottom: 0; }

.dp-page-body blockquote {
  border-left: 2px solid var(--dp-accent);
  color: var(--dp-legal-text-color);
  margin: 0 0 14px;
  padding-left: 16px;
}

/* max-width on every embeddable element: the one thing an editor can paste
   that would otherwise scroll the whole page sideways on a phone. */
.dp-page-body img,
.dp-page-body iframe,
.dp-page-body video {
  max-width: 100%;
  height: auto;
  border-radius: var(--dp-radius-sm);
}
.dp-page-body figure { margin: 0 0 14px; }
.dp-page-body figcaption {
  color: var(--dp-legal-updated-color);
  font-size: var(--dp-legal-updated-fs);
  margin-top: 8px;
}
.dp-page-body pre {
  overflow-x: auto;
  font-size: var(--dp-legal-text-fs);
  margin: 0 0 14px;
}

.dp-page-body table {
  width: 100%;
  border-collapse: collapse;
  color: var(--dp-legal-text-color);
  font-size: var(--dp-legal-text-fs);
  margin: 0 0 14px;
}
.dp-page-body th,
.dp-page-body td {
  border-bottom: var(--dp-legal-divider);
  padding: 8px 12px;
  text-align: left;
}
.dp-page-body th { color: var(--dp-text); }

.dp-page-body hr {
  border: 0;
  border-top: var(--dp-legal-divider);
  margin: 24px 0;
}

.dp-page-pages {
  color: var(--dp-legal-updated-color);
  font-size: var(--dp-legal-updated-fs);
  margin: 14px 0 0;
  text-align: center;
}

/* ══════════════════════════════════════════════
   CF7 FORMS (unified styling)
   ══════════════════════════════════════════════ */
/* FIX (the client's screenshot, vertical half): one <p> per field, and the
   gap between fields declared here rather than produced by a <br> line box.
   The form definitions in inc/theme-setup.php now put a label and its control
   on one source line and a blank line between fields, so Contact Form 7's
   autop emits <p><label></label><span><input></span></p> per field instead of
   a single <p> holding the whole form with ten <br> in it. Nothing was added
   to or removed from the design: the <p> that already wrapped the form now
   wraps one field. dp_reflow_cf7_field_blocks() applies the same shape to
   sites that were set up before this release. */
.wpcf7-form p {
  margin: 0 0 var(--dp-form-gap);
}

/* The label's margin-bottom only becomes a real gap once the control's wrapper
   is a block; while the wrapper was inline the spacing came from the <br>
   above it. .dp-form-wrap has carried this declaration for years — the bare
   CF7 path never did, which is why the two paths drifted apart. */
.wpcf7-form .wpcf7-form-control-wrap {
  display: block;
}

/* The two-column row is one grid and must stay one grid, so its cells keep
   their own paragraph margin at zero and the row itself carries the field
   rhythm. Wins over both .wpcf7-form p and .dp-form-wrap p on specificity. */
.wpcf7-form .dp-form-row p,
.dp-form-wrap .dp-form-row p {
  margin: 0;
}

/* A CHECKBOX LABEL IS NOT A FIELD LABEL. CF7's use_label_element renders the
   history-report checkbox as a <label> too, so it matches the rule below and
   would inherit the uppercase, letter-spaced, 15px field-label register — for
   a 46-character sentence ("Send me the vehicle history report for this car").
   It reads as ordinary sentence text instead. Repeated in each skin because
   the skins set the uppercase and win on specificity. */
.wpcf7-form .wpcf7-list-item label {
  text-transform: none;
  letter-spacing: normal;
  font-size: var(--dp-field-fs, 15px);
  font-weight: var(--dp-fw-normal, 400);
  display: inline-flex;
  align-items: flex-start;
  gap: 9px;
}

/* ONE TOKEN FOR ONE ROLE (3.7.4). This read var(--dp-cf7-label-fs) while the
   identical element under .dp-form-wrap read var(--dp-label-fs) — the same
   field label wearing two class paths because the theme has two form wrappers.
   Nobody ever compared them, so they drifted to four values: 10px on modern
   and classic, 11px on heavy, 13px in the base, and a parallel 11px everywhere
   for the cf7 name. Three skin files carry comments about patching the same
   split for COLOUR. It is one token now. */
.wpcf7-form label {
  display: block;
  font-size: var(--dp-label-fs);
  font-weight: var(--dp-cf7-label-fw);
  letter-spacing: var(--dp-cf7-label-ls);
  color: var(--dp-cf7-label-color, var(--dp-accent));
  text-transform: var(--dp-cf7-label-transform);
  margin-bottom: var(--dp-form-label-gap);
  /* FIX (uniformity audit): the label sat on the field's BOX edge while the
     field's own text sat 16px padding + 1px border further in, so no label on
     the site shared a left edge with the input it names. Pad the label by the
     field's total left inset instead of unpadding the field (which would put
     the input text against its own border). Bare .wpcf7-form fields always
     carry a 1px border (literal at the rule below); the .dp-form-wrap path
     below tracks --dp-field-border-w because heavy sets a 2px field border. */
  padding-left: calc(16px + 1px);
}

.wpcf7-form input[type="text"],
.wpcf7-form input[type="email"],
.wpcf7-form input[type="tel"],
.wpcf7-form input[type="url"],
.wpcf7-form input[type="number"],
.wpcf7-form select,
.wpcf7-form textarea {
  /* Block-level for the same reason as the submit: inline-level controls in
     a <p> leave baseline slack under themselves, and that slack is what made
     the gap above the submit differ from form to form. */
  display: block;
  width: 100%;
  background: var(--dp-bg-input);
  border: 1px solid var(--dp-border-input);
  border-radius: var(--dp-radius-input);
  color: var(--dp-input-color);
  padding: 14px 16px;
  font-size: var(--dp-input-fs); /* 16px prevents iOS auto-zoom on focus */
  font-family: var(--dp-font-ui);
  line-height: var(--dp-input-lh);
  transition: border-color 0.25s ease, box-shadow 0.25s ease;
  outline: none;
}

.wpcf7-form textarea {
  min-height: 120px;
  resize: vertical;
}

/* FIX v1.3.9: Improved placeholder contrast for better readability */
.wpcf7-form input::placeholder,
.wpcf7-form textarea::placeholder {
  color: var(--dp-input-placeholder);
  opacity: 1;
}
/* FIX v1.3.20: Select dropdown with default option color */
.wpcf7-form select,
.wpcf7-form select option {
  color: var(--dp-input-option-color);
}
.wpcf7-form select:invalid,
.wpcf7-form select option[value=""] {
  color: var(--dp-input-option-empty-color);
}

.wpcf7-form input:not([type="submit"]):not([type="button"]):focus,
.wpcf7-form select:focus,
.wpcf7-form textarea:focus {
  border-color: var(--dp-accent);
  box-shadow: var(--dp-input-shadow-focus);
  background: var(--dp-input-bg-focus);
}

/* FIX v1.3.39: Forțat cu !important ca submit-ul CF7 să păstreze mereu gradientul accent
   pe toate paginile (Contact, Shipping, Listing Inquiry), indiferent de state
   (normal, hover, focus, active). Anterior se înnegrea pe :focus/:active în unele browsers. */
.wpcf7-form input[type="submit"],
.wpcf7-form input[type="submit"]:hover,
.wpcf7-form input[type="submit"]:focus,
.wpcf7-form input[type="submit"]:active,
.wpcf7-form input[type="submit"]:focus-visible,
.wpcf7-form button[type="submit"],
.wpcf7-form button[type="submit"]:hover,
.wpcf7-form button[type="submit"]:focus,
.wpcf7-form button[type="submit"]:active,
.wpcf7-form button[type="submit"]:focus-visible {
  background: linear-gradient(135deg, var(--dp-accent), var(--dp-accent-dark)) !important;
  color: var(--dp-submit-fg) !important;
  border: none !important;
}

.wpcf7-form select {
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background-image: var(--dp-input-arrow);
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 44px;
}

.wpcf7-form select option {
  background: var(--dp-input-option-bg);
  color: var(--dp-input-option-fg);
}

/* ── ONE SUBMIT BOX ──
   The submit had two implementations — this one (no display, so the UA's
   inline-block) and `.dp-form-wrap .wpcf7-submit` below (inline-flex) — and
   BOTH were inline-level. An inline-level control inside Contact Form 7's
   <p> generates a line box, so the paragraph measured 76.95px tall for a
   56px button: 20.95px of baseline descender hanging underneath it on all
   seven rendered forms. The full-width fields were inline-level for the same
   reason, which is what made the gap between the last field and the button
   18px after a <select> (whose line box happens to fit) and 21px after a
   <textarea> (3px of slack), plus 12px more on Reserve from a margin-top
   that page-reserve.php set on this control alone.
   Block-level flex in both implementations removes the line box. Nothing
   else about the control changes: both are width:100%, so flex and
   inline-flex lay the box out identically across, and an <input> has no
   children for align-items/justify-content to move. The two implementations
   carried their own PAINT tokens. That is no longer true, and the paragraph
   that used to stand here — "merging those is the separate item" — is that
   item, done: THIS is now the only rule that paints the submit, and it reads
   the one merged --dp-submit-* set. See the note beside --dp-submit-fs.

   ── WHY THIS RULE AND NOT THE OTHER ──
   `.wpcf7-form input[type="submit"]` is (0,2,1); `.dp-form-wrap
   .wpcf7-submit` is (0,2,0), and its :hover is (0,3,0) against this one's
   (0,3,1). This rule wins every property the two declared in common, on
   every page, in every skin — not by source order, which favours the other
   one by 1361 lines. Modern is the proof: --dp-submit-fs was 15px there and
   --dp-cf7-submit-fs 16px, and the button measured 16px.
   The merged names below therefore carry the values that were ALREADY
   rendering. Four tokens reached this button never — the old --dp-submit-fs,
   --dp-submit-fw, --dp-submit-shadow-hover and --dp-cf7-submit-fg — and are
   gone rather than kept as a second opinion. */
.wpcf7-form input[type="submit"] {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 56px;
  border: none;
  border-radius: var(--dp-submit-radius);
  background: linear-gradient(135deg, var(--dp-accent), var(--dp-accent-dark));
  color: var(--dp-submit-fg);
  font-size: var(--dp-submit-fs);
  font-weight: var(--dp-submit-fw);
  font-family: var(--dp-font-ui);
  cursor: pointer;
  box-shadow: var(--dp-submit-shadow);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
  text-transform: var(--dp-submit-transform);
  letter-spacing: var(--dp-submit-ls);
}

.wpcf7-form input[type="submit"]:hover {
  transform: translateY(-2px);
  box-shadow: var(--dp-submit-shadow-hover);
}

.wpcf7-not-valid-tip {
  color: var(--dp-invalid-color);
  font-size: var(--dp-invalid-fs);
  margin-top: 4px;
  display: block;
}

.wpcf7-response-output {
  margin: 16px 0 0 !important;
  padding: 14px 18px !important;
  border-radius: var(--dp-radius-xs) !important;
  font-size: var(--dp-cf7-response-fs) !important;
  font-weight: var(--dp-cf7-response-fw) !important;
  border: none !important;
}

.wpcf7-mail-sent-ok {
  background: var(--dp-cf7-ok-bg) !important;
  color: var(--dp-cf7-ok-color);
  border: var(--dp-cf7-ok-border) !important;
}

.wpcf7-mail-sent-ng,
.wpcf7-validation-errors {
  background: var(--dp-error-bg) !important;
  color: var(--dp-error-color) !important;
  border: var(--dp-error-border) !important;
}

/* Contact Form 7 6.x stopped putting the outcome on the notice itself.
   .wpcf7-mail-sent-ok, .wpcf7-mail-sent-ng and .wpcf7-validation-errors are
   never emitted any more — the plugin marks the FORM (form.sent, form.failed,
   form.invalid, form.spam, form.aborted, form.unaccepted) and signals the
   result with a border colour alone, which the `border: none !important`
   above removes. The rules just above therefore stopped matching anything and
   the notice rendered as unstyled body text: a customer whose details failed
   validation saw the same flat grey sentence as one whose message had just
   been sent. These restate the same two looks against the selectors 6.x does
   emit; the legacy rules stay for anyone still on Contact Form 7 5.x. */
.wpcf7 form.sent .wpcf7-response-output {
  background: var(--dp-cf7-ok-bg) !important;
  color: var(--dp-cf7-ok-color) !important;
  border: var(--dp-cf7-ok-border) !important;
}

.wpcf7 form.failed .wpcf7-response-output,
.wpcf7 form.aborted .wpcf7-response-output,
.wpcf7 form.spam .wpcf7-response-output,
.wpcf7 form.invalid .wpcf7-response-output,
.wpcf7 form.unaccepted .wpcf7-response-output,
.wpcf7 form.payment-required .wpcf7-response-output {
  background: var(--dp-error-bg) !important;
  color: var(--dp-error-color) !important;
  border: var(--dp-error-border) !important;
}

/* Form row (2 columns) — one field block, same rhythm as a single field.
   Its cells' paragraph margins are zeroed above, so the row owns the spacing:
   margin-bottom below it, and the grid gap between the two cells, which is
   also the gap the two stack with once the row collapses to one column at
   768px. All three numbers are the one field-rhythm value. */
.dp-form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--dp-form-gap);
  margin-bottom: var(--dp-form-gap);
}

/* ══════════════════════════════════════════════
   SCROLL REVEAL
   ══════════════════════════════════════════════ */
/* FIX v1.3.11: Cards visible by default. JS only adds .is-visible to trigger transition.
   If JS fails entirely, cards remain visible — never invisible. */
.dp-scroll-reveal {
  opacity: 1;
  transform: translateY(0);
  transition: var(--dp-scroll-reveal-transition);
}

/* JS adds .dp-scroll-reveal-init to mark "ready to animate" — only then hide initial state */
.dp-scroll-reveal-init {
  opacity: 0;
  transform: translateY(32px);
}

.dp-scroll-reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .dp-scroll-reveal,
  .dp-scroll-reveal-init {
    opacity: 1;
    transform: none;
    animation: none;
    transition: none;
  }
}

/* Hero entrance animations */
/* FIX v1.3.11: CRITICAL — text must be VISIBLE BY DEFAULT.
   Previous approach (opacity:0 + animation) caused text to stay invisible if animation failed.
   New approach: text is fully visible by default. Animation OVERLAYS a reveal effect on top.
   Even if JS/CSS/cache fails completely, text NEVER disappears. */
.dp-reveal {
  opacity: 1;
  animation: var(--dp-reveal-anim);
}

.dp-reveal--1 { animation-delay: 0.15s; }
.dp-reveal--2 { animation-delay: 0.35s; }
.dp-reveal--3 { animation-delay: 0.58s; }
.dp-reveal--4 { animation-delay: 0.80s; }

@media (prefers-reduced-motion: reduce) {
  .dp-reveal {
    animation: none;
  }
}

@keyframes dpRevealUp {
  from {
    opacity: 0;
    transform: translateY(28px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ══════════════════════════════════════════════
   GRIDS
   ══════════════════════════════════════════════ */
.dp-grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; }
.dp-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.dp-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 24px; }

/* ══════════════════════════════════════════════
   TESTIMONIAL CARDS
   ══════════════════════════════════════════════ */
.dp-testimonial {
  position: relative;
  padding: 28px 24px;
  min-height: 100%;
  display: flex;
  flex-direction: column;
  gap: 16px;
  border: var(--dp-testimonial-border);
  background: var(--dp-bg-card);
  border-radius: var(--dp-testimonial-radius);
  transition: border-color 0.3s ease, transform 0.3s ease;
}

.dp-testimonial:hover {
  transform: translateY(-4px);
  border-color: var(--dp-testimonial-border-hover);
}

.dp-testimonial__stars { color: var(--dp-accent); font-size: var(--dp-testimonial-stars-fs); letter-spacing: var(--dp-testimonial-stars-ls); }

.dp-testimonial__text { color: var(--dp-testimonial-text-color); font-size: var(--dp-testimonial-text-fs); line-height: var(--dp-testimonial-text-lh); margin: 0; flex: 1; }

.dp-testimonial__footer { display: flex; align-items: center; gap: 12px; padding-top: 14px; border-top: var(--dp-testimonial-foot-border); margin-top: auto; }

.dp-testimonial__avatar { width: 40px; height: 40px; border-radius: var(--dp-testimonial-av-radius); background: var(--dp-accent); color: var(--dp-testimonial-av-fg); font-size: var(--dp-testimonial-av-fs); font-weight: var(--dp-testimonial-av-fw); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }

.dp-testimonial__name { color: var(--dp-testimonial-name-color); font-size: var(--dp-testimonial-name-fs); font-weight: var(--dp-testimonial-name-fw); margin: 0; }

.dp-testimonial__role { color: var(--dp-testimonial-role-color); font-size: var(--dp-testimonial-role-fs); margin: 0; }

/* ══════════════════════════════════════════════
   FAQ ACCORDION
   ══════════════════════════════════════════════ */
.dp-faq-item {
  background: var(--dp-accordion-item-bg);
  border: 1px solid var(--dp-border);
  border-radius: var(--dp-radius-xs);
  overflow: hidden;
  transition: border-color 0.3s;
}

.dp-faq-item:hover {
  border-color: var(--dp-faq-item-border-hover);
}

.dp-faq-q {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 22px;
  background: none;
  border: none;
  color: var(--dp-accordion-q-color);
  font-size: var(--dp-accordion-q-fs);
  font-weight: var(--dp-accordion-q-fw);
  font-family: var(--dp-font-ui);
  cursor: pointer;
  text-align: left;
  gap: 16px;
}

.dp-faq-icon {
  color: var(--dp-accent);
  font-size: var(--dp-accordion-icon-fs);
  font-weight: var(--dp-accordion-icon-fw);
  flex-shrink: 0;
  transition: transform 0.3s;
}

.dp-faq-a {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.4s ease, padding 0.4s ease;
  padding: 0 22px;
}

.dp-faq-a p {
  margin: 0;
  color: var(--dp-text-soft);
  font-size: var(--dp-accordion-a-fs);
  line-height: var(--dp-accordion-a-lh);
  padding-bottom: 20px;
}

/* ══════════════════════════════════════════════
   FULL-WIDTH PAGE FIX
   ══════════════════════════════════════════════ */
body #page {
  max-width: 100% !important;
  width: 100% !important;
  margin: 0 !important;
  padding: 0 !important;
}

body .widget-area {
  display: none !important;
}

/* ══════════════════════════════════════════════
   RESPONSIVE
   ══════════════════════════════════════════════ */
@media (max-width: 1024px) {
  .dp-title { font-size: var(--dp-title-fs-md); letter-spacing: var(--dp-title-ls-md); }
  .dp-subtitle, .dp-body { font-size: var(--dp-subtitle-fs-md); }
  .dp-grid-4 { grid-template-columns: repeat(2, 1fr); }
  /* .dp-grid-3 had NO step here, so it stayed three-across from 1024px all the
     way down to 767 — the whole tablet band. It is used in exactly three
     places and they are all the testimonial row (front-page.php:334,
     page-about.php:171, page-shipping.php:192), so at 768 three quotes shared
     the panel and each ran at 17-21 characters a line: three vertical ribbons
     of text.

     It stacks to ONE column and not two, because three cards in two columns
     leave an orphan — the ragged shape this theme has rejected before. One
     column at this width would run ~900 characters wide, so the column itself
     is capped and centred: symmetric at any count, and a readable measure. */
  .dp-grid-3 { grid-template-columns: 1fr; gap: 16px; max-width: min(620px, 50ch); margin-inline: auto; }
}

/* ── The sticky CTA bar belongs to the mobile header, so it ends where the
      mobile header ends ─────────────────────────────────────────────────────
   FIX (audit medium): .dp-sticky-bar used to display up to 1024px while the
   header switches back to its desktop layout at 961px. Between 961 and 1024
   the visitor therefore saw BOTH the desktop phone CTA in the header and the
   fixed mobile Call / Request Info bar pinned over the footer — the same two
   actions twice, with the bar still covering the footer's legal links. The
   bar now turns off at exactly the width where the header's own call button
   and nav come back (961px), and the <body> padding that reserves its height
   is kept in step with it above. */
@media (max-width: 960px) {
  .dp-sticky-bar { display: grid; }
}

@media (max-width: 767px) {
  /* FIX (uniformity audit): .dp-shell used to narrow to a 20px gutter here
     while the header, the footer and all nine page containers keep the 16px
     gutter of the base rule, so the header, the hero and every body section
     started on three different left edges (10 / 16 / 18) on one phone screen.
     The override is gone; .dp-shell now inherits min(100% - 32px, …). */
  .dp-section { padding: 64px 0; }
  .dp-title { font-size: var(--dp-title-fs-sm); line-height: var(--dp-title-lh-sm); letter-spacing: var(--dp-title-ls-sm); }
  .dp-section-head { margin-bottom: 28px; }
  .dp-subtitle, .dp-body { font-size: var(--dp-subtitle-fs-sm); line-height: var(--dp-subtitle-lh-sm); }
  /* FIX (this pass): `.dp-line { margin: 18px auto }` used to sit here. The
     previous pass moved about/contact/shipping/reserve's four private divider
     classes onto .dp-line's 22px/24px, but those templates declare no phone
     override, so below 768 home and the listing dropped to 18/18 while the
     other four stayed at 22/24 — the unification held at 1440 and 768 and came
     apart on a phone. Removing this override leaves one divider with one set
     of margins at every width, which is what the change claimed. */
  .dp-btn { width: 100%; min-height: 56px; font-size: var(--dp-btn-fs-sm); }
  .dp-grid-4, .dp-grid-3 { grid-template-columns: 1fr; gap: 16px; }
  .dp-grid-2 { grid-template-columns: 1fr; }
  .dp-section-wrapper { padding: 36px 18px; border-radius: var(--dp-radius); }
  .dp-form-row { grid-template-columns: 1fr; }
  .dp-sticky-bar { display: grid; }
  .dp-sticky-btn { font-size: var(--dp-sticky-fs-sm); }
  .dp-testimonial { padding: 24px 18px 20px; }
  .dp-testimonial__text { font-size: var(--dp-testimonial-text-fs-sm); }
}

@media (prefers-reduced-motion: reduce) {
  .dp-reveal,
  .dp-scroll-reveal {
    animation: none !important;
    transition: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ══════════════════════════════════════════════
   HONEYPOT — hidden from real users, visible to bots
   ══════════════════════════════════════════════ */
/* FIX: the two paragraph selectors here never matched anything. CF7 wraps the
   honeypot as <span class="wpcf7-form-control-wrap"><input class="dp-hp-field">
   </span>, so the input is neither a direct child of the <p> nor is the class
   on the span. It did not show while the whole form was a single <p> — and it
   is as well it did not, because that selector would have hidden the entire
   form. Now that each field has its own <p> the honeypot has one too, and an
   empty 1px paragraph would leave a phantom gap in the rhythm. Matched on the
   input wherever it sits, and never on a paragraph that has a label, so a real
   field can never be hidden by this rule. */
.dp-hp-field,
.wpcf7-form .dp-hp-field,
input.dp-hp-field,
.wpcf7-form p:has(input.dp-hp-field):not(:has(label)) {
  position: absolute !important;
  left: -9999px !important;
  top: -9999px !important;
  width: 1px !important;
  height: 1px !important;
  overflow: hidden !important;
  opacity: 0 !important;
  pointer-events: none !important;
  tabindex: -1 !important;
  visibility: hidden !important;
}

/* ══════════════════════════════════════════════
   SKIP TO CONTENT — accessibility
   ══════════════════════════════════════════════ */
.dp-skip-link {
  position: absolute;
  top: -100px;
  left: 16px;
  z-index: 999999;
  background: var(--dp-skip-bg);
  color: var(--dp-skip-fg);
  padding: 10px 20px;
  border-radius: var(--dp-skip-radius);
  font-size: var(--dp-skip-fs);
  font-weight: var(--dp-skip-fw);
  line-height: var(--dp-skip-lh);
  text-decoration: none;
  transition: top 0.2s;
}
.dp-skip-link:focus {
  top: 0;
  outline: none;
  box-shadow: var(--dp-focus-ring);
}

/* ── Focus visible — keyboard navigation ──
   The indicator is an INSET box-shadow, not an outline. `outline` paints
   OUTSIDE the border box, and skin-heavy.css puts a chamfer clip-path on
   .dp-btn--primary / .wpcf7-submit / .dp-header__call / .dp-mobile-nav__call /
   .dp-sl-reserve / .dp-btt — clip-path discards everything
   painted outside the border box, so on that skin those controls had NO
   visible keyboard focus indicator at all. Painted inside, the ring also
   survives overflow:hidden (.dp-btn sets it) and follows each control's own
   border-radius instead of being squared off by --dp-focus-radius.

   The ring is two concentric inset bands, one light and one dark. For any
   fill colour, contrast-with-white x contrast-with-black is always 21, so at
   least one band clears 4.5:1 against whatever a skin sets, and the two bands
   clear 21:1 against each other.

   While a control is focused the ring REPLACES that control's own drop
   shadow; the component's shadow token is deliberately not composed back in,
   because a skin may set it to `none` and `box-shadow: <ring>, none` is an
   invalid list, which would drop the indicator altogether.

   The :focus-visible:hover twins exist only so the components' own :hover
   box-shadow rules — which sit at equal specificity, some of them in blocks
   printed after this file (header.php, footer.php, functions.php) — cannot
   take the ring away while a focused control is also hovered. */
:focus-visible {
  outline: none;
  box-shadow: var(--dp-focus-ring);
}
.dp-btn:focus-visible,
.dp-btn:focus-visible:hover { box-shadow: var(--dp-focus-ring-btn); }
.dp-btn--cta:focus-visible,
.dp-btn--call:focus-visible,
.dp-btn--cta:focus-visible:hover,
.dp-btn--call:focus-visible:hover { box-shadow: var(--dp-focus-ring-cta); }
.dp-header__call:focus-visible,
.dp-header__call:focus-visible:hover { box-shadow: var(--dp-focus-ring-cta); }
.dp-mobile-nav__call:focus-visible,
.dp-mobile-nav__call:focus-visible:hover { box-shadow: var(--dp-focus-ring-cta); }
.dp-btt:focus-visible,
.dp-btt:focus-visible:hover { box-shadow: var(--dp-focus-ring); }
/* 3.2.0 — the two controls that gained --dp-hover-veil-shadow. Their :hover
   rule is (0,2,0) and would otherwise outrank the bare :focus-visible above
   and take the ring away while a focused control is also hovered, which is
   the exact hazard the paragraph above describes. */
.dp-sticky-btn:focus-visible,
.dp-sticky-btn:focus-visible:hover,
.dp-header__hamburger:focus-visible,
.dp-header__hamburger:focus-visible:hover { box-shadow: var(--dp-focus-ring); }
:focus:not(:focus-visible) { outline: none; }

/* ── The one shape the inset ring cannot reach ──
   a.dp-inv-card__img-link and a.dp-home-fcard__img-link are keyboard stops
   whose whole box is filled by the <img>, which paints over the link's own
   inset ring: forcing :focus-visible changed 2 pixels of a 395x247 box. An
   outset ring is no good either — .dp-inv-card__media / .dp-home-fcard__media
   are overflow:hidden and would clip it.

   No new element is needed. Both cards already carry a base-declared box that
   spans the photo and paints above it: .dp-inv-card__img-wrap::after
   (archive-listing.php — position:absolute, inset:0, z-index:10,
   pointer-events:none) and the real .dp-home-fcard__overlay div
   (front-page.php). Paint the ring there, exactly the way
   single-listing.php already does for .dp-sl-thumb. (0,3,1) and (0,3,0) beat
   both declaring rules regardless of print order, and the ring stays
   retintable through --dp-focus-ring like every other ring in the theme. */
.dp-inv-card__img-link:focus-visible .dp-inv-card__img-wrap::after,
.dp-home-fcard__img-link:focus-visible .dp-home-fcard__overlay {
  box-shadow: var(--dp-focus-ring);
}

/* ── CF7 submit loading state ── */
.wpcf7-submit {
  position: relative;
  transition: opacity .2s, transform .2s;
}
.wpcf7-submit.wpcf7-submit--loading {
  opacity: 0.7;
  pointer-events: none;
  cursor: wait;
}

/* ── Disabled controls ──
   The loading CLASS above was styled; the disabled ATTRIBUTE was not. Contact
   Form 7 sets both for the length of a submission, so a submit that is inert
   still looked fully live — setting disabled=true changed 0.0000 pixels; the
   only difference was cursor:not-allowed, which does not exist on touch.
   Opacity plus desaturation reads on every fill the theme uses and needs no
   per-component colour.

   The two exclusions are load-bearing, not belt-and-braces. Inside a skin's
   body scope a bare :disabled is (0,2,2) and outranks .dp-inv-page-btn:disabled
   at (0,2,0) whatever the sheet order, which relights the pager's deliberately
   faint 0.35 arrow to 0.55. Keeping the exclusions here means the base and the
   skins behave identically. */
:is(button, input, select, textarea):disabled:not(.dp-inv-page-btn, .dp-inv-select),
[aria-disabled="true"]:not(.dp-inv-page-btn, .dp-inv-select) {
  opacity: var(--dp-disabled-opacity);
  filter: grayscale(var(--dp-disabled-grayscale));
  cursor: not-allowed;
}
/* ── The spinner is why the submit's paragraph was 76.95px tall ──
   Contact Form 7 prints <span class="wpcf7-spinner"> as a SIBLING of the
   submit, inside the submit's own <p>. It is visibility:hidden while the
   form is idle, so it shows nothing — but it was display:inline-block, and
   an inline-level box makes the paragraph generate a line box. With the
   submit now block-level, that line box was all that was left: 20.95px of
   empty space under every submit button on the site, on all seven rendered
   forms, at every width and in all three skins.
   Contact Form 7 puts `.submitting` on the form for exactly as long as the
   spinner should be seen — its own stylesheet flips visibility on that same
   selector — so the spinner is taken out of the document while idle and put
   back on `.submitting`. `visibility` alone cannot do this: a hidden box
   still occupies its space, which is the whole defect.
   NOT `position:absolute`: the paragraph is static and the nearest
   positioned ancestor is outside the form, and `.wpcf7-form p` cannot be
   made relative because Contact Form 7's honeypot paragraph IS absolutely
   positioned — that is how the honeypot is hidden, and relative would put
   it back on the page. */
.wpcf7 .wpcf7-spinner {
  display: none !important;
  width: 18px !important;
  height: 18px !important;
  margin-left: 8px !important;
  vertical-align: middle !important;
  background: none !important;
}
.wpcf7 form.submitting .wpcf7-spinner {
  display: inline-block !important;
}
.wpcf7 .wpcf7-spinner::before {
  border-color: var(--dp-spinner-border-color) !important;
  border-width: 2px !important;
  width: 16px !important;
  height: 16px !important;
  margin: 0 !important;
}

/* ── Section title responsive size ── */
.dp-title--section {
  font-family: var(--dp-font-heading);
  font-size: var(--dp-title-fs-section) !important;
}

/* ══════════════════════════════════════════════
   QUICK VIEW — global (used on homepage + inventory)
   ══════════════════════════════════════════════ */
/* ══════════════════════════════════════════════
   QUICK VIEW TRIGGER
   ══════════════════════════════════════════════ */
.dp-inv-card { position: relative; }

/* ── Badge plates the variant rules do not name ──
   The six named modifiers are painted in the template-level <style> blocks --
   search each template for `__badge--hot-deal`: archive-listing.php has the
   `.dp-inv-card__badge--*` set, front-page.php the `.dp-home-fcard__badge--*`
   set, single-listing.php the `.dp-sl-rel-card__img .dp-inv-card__badge--*`
   set -- and four of the six are re-stamped with !important in header.php,
   under its `BADGES - lock colors` comment. (Selector names, not line
   numbers: these files are edited every round and line numbers rot.)
   The slug, though, is free text from post meta, so a seventh status
   -- "Reserved" is the one the fixtures ship -- had no rule anywhere and
   rendered as bare ink on the photograph.

   The default below is (0,1,0) and sits in this file, so it loses to every
   one of those template modifiers, which are (0,1,0) or (0,2,0) and print
   later inside <body>: it only fills the gap they leave. Reserved gets a
   named pair of its own so it is not lumped in with the grey fallback. */
.dp-inv-card__badge,
.dp-home-fcard__badge {
  background: var(--dp-badge-default-bg, var(--dp-badge-sold-bg));
  color: var(--dp-badge-default-fg, var(--dp-badge-sold-fg));
}
.dp-inv-card__badge--reserved,
.dp-home-fcard__badge--reserved,
.dp-sl-rel-card__img .dp-inv-card__badge--reserved {
  background: var(--dp-badge-reserved-bg);
  color: var(--dp-badge-reserved-fg);
}
.dp-qv-trigger {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: var(--dp-qvt-bg);
  color: var(--dp-qvt-fg);
  border: none;
  border-radius: var(--dp-qvt-radius);
  padding: 11px 22px;
  font-size: var(--dp-qvt-fs);
  font-weight: var(--dp-qvt-fw);
  font-family: var(--dp-font-ui);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
  opacity: 0 !important;
  pointer-events: none !important;
  /* NO visibility:hidden — a hidden element cannot receive focus, which made the
     :focus-visible reveal below unreachable by keyboard. opacity+pointer-events
     keep it invisible and un-clickable while leaving it in the tab order. */
  transition: opacity .25s ease;
  z-index: 25;
  letter-spacing: var(--dp-qvt-ls);
  box-shadow: var(--dp-qvt-shadow);
}
.dp-inv-card__media:hover .dp-qv-trigger,
.dp-home-fcard__media:hover .dp-qv-trigger,
.dp-qv-trigger:focus-visible {
  opacity: 1 !important;
  pointer-events: auto !important;
  transition: opacity .25s ease !important;
}
/* ── The pressed state, restated where the reveal can hear it ──
   .dp-qv-trigger is listed in the site-wide pressed rule at the top of the
   BUTTONS section like every other control, and on this one control that
   listing cannot win: its opacity is spoken for by TWO !important
   declarations, `opacity: 0 !important` at rest and `opacity: 1 !important`
   the moment the card is hovered, and no amount of specificity beats an
   !important without one of its own. Measured before this rule: forcing
   :active on the trigger changed nothing, 6 of 6 contexts, even though it
   was in the list.

   This is NOT a second definition of "pressed" — it is the same token,
   --dp-pressed-opacity, restated at the only place the cascade will accept
   it. The selectors are the reveal's own, plus :active, so the press exists
   exactly where the button is visible and nowhere else. (0,4,0) and (0,3,0)
   against the reveal's (0,3,0) and (0,2,0). */
.dp-inv-card__media:hover .dp-qv-trigger:active,
.dp-home-fcard__media:hover .dp-qv-trigger:active,
.dp-qv-trigger:focus-visible:active {
  opacity: var(--dp-pressed-opacity) !important;
}

.dp-qv-trigger:hover {
  background: var(--dp-qvt-bg-hover);
  box-shadow: var(--dp-qvt-shadow-hover);
  transform: translate(-50%, -50%) scale(1.05);
}
.dp-qv-trigger * { pointer-events: none; }

/* ══ QUICK VIEW IS A DESKTOP FEATURE, AND THIS IS WHERE THAT IS SAID ══
   MEASURED, on an emulated phone (390x844, mobile, dsf 3, five touch points):
   matchMedia('(hover: hover)') is FALSE and '(pointer: coarse)' is true, so
   .dp-inv-card__media:hover — the only thing that reveals this button apart
   from :focus-visible — CAN NEVER FIRE. The rule above deliberately avoids
   visibility:hidden so the keyboard reveal stays reachable, which was right
   and stays right; the cost on a touch device was twelve controls per
   inventory page that were invisible, un-tappable, IN THE TAB ORDER AND IN
   THE ACCESSIBILITY TREE, each announced "Quick View", that a screen-reader
   user swiped through one by one and that did nothing when activated.

   The feature itself does not belong there. Quick View exists so you do not
   lose your place in a multi-column grid; a one-column phone list has no
   place to lose, the back button restores the scroll, and a full-screen sheet
   with no URL is a worse copy of the listing page that is one tap away.
   So it is CLOSED on touch, not re-affordanced: display:none takes it out of
   the accessibility tree and out of the tab order together. Nothing else does
   both — opacity/visibility/pointer-events each leave one of them behind.

   WHY (hover: none) AND NOT any-hover / pointer / a width:
     * (hover: none) asks exactly the question that matters: can the PRIMARY
       pointer hover? If it cannot, the reveal is unreachable and the control
       is dead weight. That is the whole defect, stated directly.
     * (pointer: coarse) is the wrong test — it describes precision, not
       hovering. A stylus device is fine and pointer-fine yet cannot hover,
       and `hover:none and pointer:coarse` would leave that device broken.
     * (any-hover: hover) asks whether ANY attached pointer can hover, so a
       phone stays gated but a phone with a mouse plugged in does not. That is
       defensible, but it makes the control appear on a device whose primary
       input still cannot reach it, so the simpler question wins.
     * A width query is what the theme reached for before and it is not the
       same question: a 390px BROWSER WINDOW on a desktop has a mouse and a
       keyboard and Quick View works there, which is why this is not keyed to
       width. (See the dead max-width:680px block noted further down.)

   A TOUCHSCREEN LAPTOP IS THE CASE THAT DECIDES IT, and it is the reason this
   is keyed to `hover` and not to touch support or to `any-pointer`. Its
   primary pointer is the trackpad, so (hover: hover) is TRUE, this block does
   not match, and it keeps Quick View in full. MEASURED on /inventory/ at 1440
   with the media features forced (hover:hover, pointer:fine, any-hover:hover,
   any-pointer:coarse — a trackpad AND a digitiser):
       computed display  flex     in the accessibility tree 12     in tab order 12
   which is identical to a plain laptop with no touchscreen at all. Keyed to
   `any-pointer: coarse` or to navigator.maxTouchPoints, that same laptop would
   have LOST a feature that works perfectly on it.

   A convertible flipped into tablet mode reports (hover: none) and is gated —
   and that is right, not a casualty: in tablet mode the user IS on touch. Flip
   it back and the media query re-evaluates and the control returns. That is
   only true because this is keyed to the CURRENT primary pointer; `any-hover`
   would have left the dead control in place in tablet mode.

   A WARNING FOR WHOEVER MEASURES THIS NEXT. Chrome's CDP touch emulation
   (Emulation.setTouchEmulationEnabled) FORCES hover:none / pointer:coarse, so
   under it a touchscreen laptop is indistinguishable from a phone and this
   block appears to gate it. It does not; that is the emulator, not the query.
   Emulation.setEmulatedMedia is the right instrument for that case — and note
   that it honours `hover: hover` but IGNORES `hover: none`, so the gated side
   has to be measured with the touch emulation instead. Both halves were
   measured that way for 3.3.1.

   An engine too old to know the `hover` media feature (pre-2018) simply does
   not match this block and keeps today's behaviour, which is the safe way
   round: the failure mode is "desktop as it is now", never "no Quick View".
   Stating it as `@media (hover: hover) { display: inline-flex }` would have
   inverted that and cost those engines the feature entirely. */
@media (hover: none) {
  .dp-qv-trigger {
    display: none;
  }
}

/* ══════════════════════════════════════════════
   QUICK VIEW MODAL
   ══════════════════════════════════════════════ */
.dp-qv-modal {
  position: fixed;
  inset: 0;
  z-index: 999999;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
/* Was `.22s ease` in and `.18s ease` out — two hard numbers and a generic
   curve, on a surface that covers the whole window. Both now take the skin's
   own eased motion through one token, and assets/js/quick-view.js reads the
   same token for the hide it schedules after the close, so the two cannot
   drift. .18s was also FASTER than the .22s open, which is backwards: a
   dismissal that outruns the reveal reads as a glitch rather than a close. */
.dp-qv-modal.dp-qv-open { animation: dpQvFadeIn var(--dp-qv-motion) forwards; }
.dp-qv-modal.dp-qv-close { animation: dpQvFadeOut var(--dp-qv-motion) forwards; }
@keyframes dpQvFadeIn { from{opacity:0;} to{opacity:1;} }
@keyframes dpQvFadeOut { from{opacity:1;} to{opacity:0; pointer-events:none;} }

.dp-qv-backdrop {
  position: fixed;
  inset: 0;
  background: var(--dp-qv-backdrop);
  backdrop-filter: var(--dp-qv-backdrop-blur);
  -webkit-backdrop-filter: var(--dp-qv-backdrop-blur);
}
.dp-qv-dialog {
  position: relative;
  z-index: 2;
  background: var(--dp-qv-dialog-bg);
  border: var(--dp-qv-dialog-border);
  border-radius: var(--dp-qv-dialog-radius);
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  width: 100%;
  max-width: 880px;
  max-height: 88vh;
  overflow: hidden;
  /* ELEVATION. The dialog had no box-shadow of any kind: it sat on the blurred
     backdrop with nothing beneath it, which is what made it read as a flat
     cut-out instead of a raised panel. Each skin sets its own — heavy's is a
     hard offset with no blur, classic's is a soft warm one, modern's is deep
     and diffuse — through --dp-qv-dialog-shadow. */
  box-shadow: var(--dp-qv-dialog-shadow);
  /* GLASS, where the skin wants it. `none` on the skins that do not. */
  backdrop-filter: var(--dp-qv-dialog-blur);
  -webkit-backdrop-filter: var(--dp-qv-dialog-blur);
  animation: dpQvSlideIn var(--dp-qv-motion) forwards;
}
/* THE 1px TOP-EDGE LIGHT LINE that 3.2.0 put on every other raised surface.
   It is a positioned pseudo-element, so it is out of flow and cannot touch the
   grid the dialog lays out; and it sits above .dp-qv-gallery, which paints its
   own background right up to the dialog's top edge and would otherwise cover
   the line on the gallery half. Each skin supplies the gradient. */
.dp-qv-dialog::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--dp-qv-dialog-edge);
  z-index: 11;
  pointer-events: none;
}
@keyframes dpQvSlideIn { from{transform:scale(0.94) translateY(12px);} to{transform:scale(1) translateY(0);} }

.dp-qv-close {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 10;
  width: 34px;
  height: 34px;
  border-radius: var(--dp-qv-close-radius);
  background: var(--dp-qv-close-bg);
  border: var(--dp-qv-close-border);
  color: var(--dp-qv-close-fg);
  font-size: var(--dp-qv-close-modal-fs);
  line-height: var(--dp-qv-close-lh);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background var(--dp-qv-motion), border-color var(--dp-qv-motion),
              color var(--dp-qv-motion);
  font-family: var(--dp-font-ui);
}
.dp-qv-close:hover { background: var(--dp-qv-close-bg-hover); }

.dp-qv-gallery { display:flex; flex-direction:column; background:var(--dp-qv-gallery-bg); }
.dp-qv-main-img-wrap { position:relative; flex:1; min-height:280px; overflow:hidden; }
.dp-qv-main-img { width:100%; height:100%; object-fit:cover; transition:opacity .25s ease; position:relative; z-index:1; }
.dp-qv-main-img-wrap::before { content:''; position:absolute; inset:0; background:var(--dp-qv-skeleton-bg); background-size:200% 100%; animation:dpQvSkeleton 1.4s infinite; z-index:0; }
.dp-qv-main-img-wrap.dp-qv-loaded::before { display:none; }
@keyframes dpQvSkeleton { 0%{background-position:200% 0;} 100%{background-position:-200% 0;} }
.dp-qv-badge { position:absolute; top:12px; left:12px; padding:5px 12px; border-radius:var(--dp-qv-badge-radius); background:var(--dp-accent); color:var(--dp-qv-badge-fg); font-size:var(--dp-qv-badge-fs); font-weight:var(--dp-qv-badge-fw); text-transform:var(--dp-qv-badge-transform); letter-spacing:var(--dp-qv-badge-ls); z-index:3; }
.dp-qv-counter { position:absolute; bottom:12px; right:12px; background:var(--dp-qv-counter-bg); color:var(--dp-qv-counter-fg); font-size:var(--dp-qv-counter-fs); font-weight:var(--dp-qv-counter-fw); padding:4px 10px; border-radius:var(--dp-qv-counter-radius); z-index:3; letter-spacing:var(--dp-qv-counter-ls); backdrop-filter:blur(4px); font-family:var(--dp-font-numeric); }

.dp-qv-nav {
  position:absolute; top:50%; transform:translateY(-50%);
  width:36px; height:36px; background:var(--dp-qv-nav-bg);
  border:var(--dp-qv-nav-border); border-radius:var(--dp-qv-nav-radius);
  color:var(--dp-qv-nav-fg); font-size:var(--dp-qv-nav-fs); cursor:pointer;
  display:flex; align-items:center; justify-content:center;
  transition:background .2s; z-index:3; font-family:var(--dp-font-ui);
}
.dp-qv-nav {
  transition: background var(--dp-qv-motion), border-color var(--dp-qv-motion);
  backdrop-filter: var(--dp-qv-nav-blur);
  -webkit-backdrop-filter: var(--dp-qv-nav-blur);
}
.dp-qv-nav:hover { background:var(--dp-qv-nav-bg-hover); }
.dp-qv-nav--prev { left:10px; }
.dp-qv-nav--next { right:10px; }

.dp-qv-thumbs { display:flex; gap:6px; padding:8px 10px; background:var(--dp-qv-thumbs-bg); overflow-x:auto; flex-shrink:0; scrollbar-width:none; }
.dp-qv-thumbs::-webkit-scrollbar { display:none; }
/* .dp-qv-thumb moved from the <img> to a <button> wrapping it in 3.2.0 (see
   renderThumbs() in assets/js/quick-view.js). Everything that made the box is
   unchanged; the four declarations added are the UA defaults a <button> brings
   and an <img> does not — padding 1px 6px, a grey background, a font, and no
   clipping — and they are set back to what the <img> had, so the measured box
   stays 58x44 with a 2px border and the photo still fills it. object-fit moved
   to the child, which is the element it applies to now. */
.dp-qv-thumb { width:58px; height:44px; padding:0; background:none; font:inherit; color:inherit; overflow:hidden; display:block; border-radius:var(--dp-qv-thumb-radius); cursor:pointer; border:var(--dp-qv-thumb-border); transition:border-color var(--dp-qv-motion), opacity var(--dp-qv-motion); opacity:0.6; flex-shrink:0; }
.dp-qv-thumb img { width:100%; height:100%; object-fit:cover; display:block; }
.dp-qv-thumb:hover { opacity:0.88; }
.dp-qv-thumb.dp-qv-thumb--active { border-color:var(--dp-accent); opacity:1; }

/* 3.2.0 gave the thumbnails real <button> wrappers, which added five keyboard
   stops per modal. The theme's focus indicator is a two-layer INSET box-shadow
   (the :focus-visible catch-all above), and .dp-qv-thumb is overflow:hidden with
   an <img> filling it edge to edge — so the ring paints UNDERNEATH the photo and
   a keyboard user sees nothing at all on heavy and classic.
   An OUTLINE is painted on top of an element's descendants, so it survives the
   photo. outline-offset is negative so it draws inside the 58x44 box: an outline
   never affects layout, and a negative offset also keeps it clear of the
   horizontally scrolling thumb strip that would otherwise clip it.
   border-color is deliberately NOT reused here — it already carries a different
   meaning on this control, "this is the photo you are looking at". */
.dp-qv-thumb:focus-visible {
  outline: var(--dp-focus-ring-w, 2px) solid var(--dp-focus-ring-color, #ffffff);
  outline-offset: -4px;
  opacity: 1;
}

.dp-qv-info { padding:26px 26px 22px; display:flex; flex-direction:column; overflow-y:auto; scrollbar-width:thin; scrollbar-color:var(--dp-qv-scrollbar-color); }
.dp-qv-title { font-size:var(--dp-qv-title-modal-fs); font-weight:var(--dp-qv-title-fw); color:var(--dp-qv-title-color); line-height:var(--dp-qv-title-lh); margin-bottom:12px; padding-right:22px; font-family:var(--dp-font-heading); }
.dp-qv-price-row { display:flex; align-items:baseline; gap:12px; margin-bottom:14px; flex-wrap:wrap; }
.dp-qv-price { font-size:var(--dp-qv-price-fs); font-weight:var(--dp-qv-price-fw); color:var(--dp-qv-price-color); letter-spacing:var(--dp-qv-price-ls); font-family:var(--dp-font-numeric); }
.dp-qv-specs { display:flex; flex-wrap:wrap; gap:7px; margin-bottom:14px; }
/* THE SPEC ROWS. Until 3.3.1 each pill was ONE text node — `icon + ' ' + val`
   with a colour emoji for the icon — so `gap` had nothing to act on and the
   mark was painted by the operating system in whatever palette it chose. The
   pill now holds two children: the theme's own SVG and the value. gap is a
   token because the five marks are optically lighter than the emoji they
   replace and needed a hair more room than the 5px that was never used. */
.dp-qv-spec { display:inline-flex; align-items:center; gap:var(--dp-qv-spec-gap); padding:5px 11px; background:var(--dp-qv-spec-bg); border:var(--dp-qv-spec-border); border-radius:var(--dp-qv-spec-radius); font-size:var(--dp-qv-spec-fs); font-weight:var(--dp-qv-spec-fw); color:var(--dp-qv-spec-color); }
.dp-qv-spec__ic { display:inline-flex; align-items:center; justify-content:center; flex:0 0 auto; color:var(--dp-qv-spec-ic-color); }
.dp-qv-spec__ic svg { display:block; }
.dp-qv-desc { font-size:var(--dp-qv-desc-modal-fs); line-height:var(--dp-qv-desc-modal-lh); color:var(--dp-qv-desc-color); margin:0 0 20px; }
.dp-qv-actions { display:flex; flex-direction:column; gap:9px; margin-top:auto; }
.dp-qv-actions .dp-btn { width:100%; justify-content:center; }
.dp-qv-note { text-align:center; color:var(--dp-qv-note-color); font-size:var(--dp-qv-note-modal-fs); margin:8px 0 0; }

@media(max-width:680px) {
  .dp-qv-modal { padding:0; align-items:flex-end; }
  .dp-qv-dialog { grid-template-columns:1fr; border-radius:var(--dp-qv-sheet-radius); max-height:93vh; animation:dpQvSlideUp var(--dp-qv-motion) forwards; }
  @keyframes dpQvSlideUp { from{transform:translateY(32px);} to{transform:translateY(0);} }
  .dp-qv-main-img-wrap { min-height:210px; max-height:210px; }
  .dp-qv-thumbs { display:none; }
  .dp-qv-info { padding:18px 18px 26px; }
  /* THE .dp-qv-trigger RULE THAT WAS HERE HAS BEEN REMOVED, AND IT NEVER DID
     ANYTHING. It read `opacity:1; pointer-events:auto; transform:...scale(1)`
     and was an earlier round's attempt to make the trigger permanently visible
     on small screens. It could not work: the base rule declares
     `opacity: 0 !important` and `pointer-events: none !important`, and no
     amount of specificity beats an !important without one of its own, so both
     declarations lost from the day they were written.

     RE-MEASURED PROPERLY, and the first attempt at this table was wrong in a
     way worth recording. It read the FIRST .dp-qv-trigger in the DOM, and on
     /inventory/ that one is inside a card the pager has hidden with an inline
     display:none - 10 of the 22 are, 12 to a page. getComputedStyle on an
     element with no box cannot resolve a percentage translate, so it answered
     `transform: none`, and the table printed that as if it were the control's
     resting transform. It is not; the pill is centred, as it always was.

     The test that actually settles it is not a table of values at all: put the
     deleted rule BACK, as the last stylesheet in the document - later origin,
     same specificity, the most favourable position it could ever occupy - and
     compare the computed style with and without it, on the first RENDERED
     trigger. Done at six widths, three either side of the breakpoint:
         390 600 680 | 681 900 1440
         without:  opacity 0  pointer-events none
                   transform matrix(1, 0, 0, 1, -75.8047, -19)   box 151.61x38
         with:     byte-identical at all six widths
     The pill sits dead centre on its card media (offset 0, 0) in both cases.
     Nothing changes by deleting it.

     It is deleted rather than fixed because it states the opposite of what
     3.3.1 decided: Quick View is a desktop feature, gated on (hover: none) and
     not on width. A 390px BROWSER WINDOW still gets it, because that window
     has a mouse and a keyboard; a phone does not, because it has neither. */
}
/* ══════════════════════════════════════════════
   TRUST STRIP
   ══════════════════════════════════════════════ */
.dp-inv-trust {
  background: var(--dp-trust-bg);
  border-top: var(--dp-trust-border);
  border-bottom: var(--dp-trust-border);
  padding: 14px 0;
}
.dp-inv-trust__pills {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px 28px;
}
.dp-inv-trust__pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: var(--dp-trust-pill-fs);
  font-weight: var(--dp-trust-pill-fw);
  color: var(--dp-trust-pill-color);
  white-space: nowrap;
  letter-spacing: var(--dp-trust-pill-ls);
}
.dp-inv-trust__pill svg {
  color: var(--dp-accent);
  flex-shrink: 0;
}
@media(max-width:767px) {
  .dp-inv-trust__pills { gap: 10px 20px; justify-content: flex-start; }
  .dp-inv-trust__pill { font-size: var(--dp-trust-pill-fs-sm); }
}

/* ══════════════════════════════════════════════
   REUSABLE COMPONENTS
   ══════════════════════════════════════════════ */

.dp-section-heading {
  margin-bottom: 40px;
}
.dp-section-heading--center { text-align: center; }
.dp-section-heading--left { text-align: left; }
.dp-section-heading__title {
  font-family: var(--dp-font-heading);
  font-size: var(--dp-heading-title-fs);
  font-weight: var(--dp-heading-title-fw);
  color: var(--dp-heading-title-color);
  line-height: var(--dp-heading-title-lh);
  letter-spacing: var(--dp-heading-title-ls);
  margin: 0 0 16px;
}
.dp-section-heading__title span {
  color: var(--dp-accent);
}
.dp-section-heading__divider {
  width: 80px;
  height: 3px;
  border-radius: var(--dp-heading-divider-radius);
  background: linear-gradient(90deg, var(--dp-accent), var(--dp-accent-dark));
  margin: 0 auto 20px;
}
.dp-section-heading--left .dp-section-heading__divider { margin-left: 0; }
.dp-section-heading__subtitle {
  font-size: var(--dp-heading-sub-fs);
  color: var(--dp-heading-sub-color);
  line-height: var(--dp-heading-sub-lh);
  max-width: 720px;
  margin: 0 auto;
}
.dp-section-heading--left .dp-section-heading__subtitle { margin-left: 0; }

/* ══════════════════════════════════════════════════════════════
   GLOBAL COMPONENTS — use these classes on ALL pages for consistency
   ══════════════════════════════════════════════════════════════ */

/* ─── INFO CARDS (icon + title + description) ─── */
/* FIX v1.3.27: Homepage "Built for Serious Buyers", Reserve "What to Expect", Thank You "What Happens Next" now use .dp-feature-card for consistency with Shipping page. The .dp-home-info class was removed — it caused rendering inconsistencies between pages. */

/* ─── REVIEW / TESTIMONIAL ─── */
/* FIX v1.3.9: Premium gradient background + radial glow on hover (consistent with .dp-card) */
.dp-review {
  position: relative;
  overflow: hidden;
  background: var(--dp-review-bg);
  border: var(--dp-review-border);
  border-radius: var(--dp-review-radius);
  padding: 30px 26px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  transition: var(--dp-review-transition);
  box-shadow: var(--dp-review-shadow);
}
.dp-review::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--dp-review-glow);
  opacity: 0;
  transition: opacity .35s ease;
  pointer-events: none;
}
.dp-review:hover {
  transform: translateY(-4px);
  border-color: var(--dp-review-border-hover);
  box-shadow: var(--dp-review-shadow-hover);
}
.dp-review:hover::before { opacity: 1; }
.dp-review > * { position: relative; z-index: 1; }
.dp-review__stars {
  display: flex;
  gap: 3px;
  color: var(--dp-review-star-color);
}
.dp-review__stars svg {
  filter: drop-shadow(0 2px 4px color-mix(in srgb, var(--dp-accent) 40%, transparent));
}
.dp-review__text {
  color: var(--dp-review-text-color);
  font-family: var(--dp-font-quote);
  font-size: var(--dp-review-text-fs);
  line-height: var(--dp-review-text-lh);
  margin: 0;
  flex: 1;
  font-style: var(--dp-review-text-style);
}
.dp-review__foot {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-top: 14px;
  border-top: var(--dp-review-foot-border);
  margin-top: auto;
}
.dp-review__av {
  width: 40px;
  height: 40px;
  border-radius: var(--dp-review-av-radius);
  background: var(--dp-review-av-bg);
  color: var(--dp-review-av-fg);
  font-size: var(--dp-review-av-fs);
  font-weight: var(--dp-review-av-fw);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.dp-review__name {
  color: var(--dp-review-name-color);
  font-size: var(--dp-review-name-fs);
  font-weight: var(--dp-review-name-fw);
  display: block;
}
.dp-review__role {
  color: var(--dp-review-role-color);
  font-size: var(--dp-review-role-fs);
  display: block;
  margin-top: 2px;
}

/* ─── CTA BANNER (big call-to-action) ─── */
.dp-cta-banner {
  background: linear-gradient(135deg, var(--dp-cta) 0%, var(--dp-cta-dark) 100%);
  border-radius: var(--dp-cta-banner-radius);
  padding: 48px 40px;
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 24px;
  align-items: center;
  box-shadow: var(--dp-cta-banner-shadow);
  margin: 40px 0;
}
.dp-cta-banner__content { color: var(--dp-cta-banner-content-color); }
.dp-cta-banner__title {
  font-family: var(--dp-font-heading);
  font-size: var(--dp-cta-banner-title-fs);
  font-weight: var(--dp-cta-banner-title-fw);
  color: var(--dp-cta-banner-title-color);
  line-height: var(--dp-cta-banner-title-lh);
  margin: 0 0 10px;
}
.dp-cta-banner__subtitle {
  font-size: var(--dp-cta-banner-sub-fs);
  color: var(--dp-cta-banner-sub-color);
  opacity: 0.88;
  line-height: var(--dp-cta-banner-sub-lh);
  margin: 0;
  max-width: 600px;
}
.dp-cta-banner__btn {
  padding: 16px 32px;
  /* FIX (uniformity audit): the ghost variant adds border:2px and both buttons
     are auto-height, so the pair rendered 52px vs 56px side by side in the same
     row. A transparent border of the same width makes the boxes equal; the
     ghost's own border rule still overrides the colour. */
  border: 2px solid transparent;
  background: var(--dp-cta-banner-btn-bg);
  color: var(--dp-cta);
  border-radius: var(--dp-cta-banner-btn-radius);
  font-size: var(--dp-cta-banner-btn-fs);
  font-weight: var(--dp-cta-banner-btn-fw);
  text-decoration: none;
  transition: transform .25s, box-shadow .25s;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  box-shadow: var(--dp-cta-banner-btn-shadow);
}
.dp-cta-banner__btn:hover {
  transform: translateY(-2px);
  box-shadow: var(--dp-cta-banner-btn-shadow-hover);
}
/* FIX v1.3.19: Ghost button — clearer outline + lower opacity for better hierarchy */
.dp-cta-banner__btn--ghost {
  background: var(--dp-cta-banner-ghost-bg);
  color: var(--dp-cta-banner-ghost-color);
  border: var(--dp-cta-banner-ghost-border);
  box-shadow: var(--dp-cta-banner-btn-ghost-shadow);
  opacity: 0.92;
}
.dp-cta-banner__btn--ghost:hover {
  background: var(--dp-cta-banner-btn-ghost-bg-hover);
  border-color: var(--dp-cta-banner-ghost-border-color-hover);
  opacity: 1;
}
@media (max-width: 860px) {
  .dp-cta-banner { grid-template-columns: 1fr; padding: 36px 28px; text-align: center; }
  .dp-cta-banner__subtitle { margin: 0 auto; }
}

/* ─── FEATURE CARD (why choose us) ─── */
.dp-feature-card {
  background: var(--dp-feature-bg);
  border: var(--dp-feature-border);
  border-radius: var(--dp-feature-radius);
  padding: 32px 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  text-align: center;
  align-items: center;
  transition: var(--dp-feature-transition);
  position: relative;
  overflow: hidden;
}
.dp-feature-card:hover {
  transform: translateY(-6px);
  border-color: var(--dp-feature-border-hover);
}
.dp-feature-card::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--dp-feature-glow);
  opacity: 0;
  transition: opacity .3s;
  pointer-events: none;
}
.dp-feature-card:hover::after { opacity: 1; }
/* ══════════════════════════════════════════════════════════════════════════
   ICON SIZING (3.2.0, two rules added in 3.3.0)

   Ten containers used to hold a single emoji character, sized by the
   font-size token below. They now hold an <svg> from dp_icon() instead, and
   these rules hand that svg the SAME token, so every per-skin size that was
   tuned for the emoji still applies -- heavy's feature icon is still bigger
   than modern's, because heavy still says 34px and modern still says 26px.

   The -sw token beside each -fs token is 36 / fs. That is what keeps the
   painted keyline at a constant 1.5px as the size changes between skins;
   without it a 34px icon would be drawn with a heavier line than a 26px one.

   EIGHT of the ten containers declare width:Npx; height:Npx; display:flex, so
   nothing there can change a box or move a neighbour. The TWO added in 3.3.0,
   .dp-home-shipping__step-icon and .dp-inv-empty__icon, are full-width blocks
   with no width of their own; what holds those two still is an explicit
   HEIGHT equal to the height the block already rendered at, carried by
   --dp-ship-step-icon-h and --dp-inv-empty-icon-h -- measured per skin, and
   given a measured base value in this file for a site that loads no skin at
   all. Do not read this paragraph as covering every icon container in the
   theme: it covers the ten rules directly below it.

   To resize an icon, change the font-size token as you always did -- and then
   change its -sw token to 36 divided by the new number. For those two, change
   the matching -h token as well, or the box will no longer match its mark.
   ══════════════════════════════════════════════════════════════════════════ */
.dp-home-story__feat-icon > .dp-ic {
  width: var(--dp-story-feat-icon-fs); height: var(--dp-story-feat-icon-fs);
  stroke-width: var(--dp-story-feat-icon-sw);
}
.dp-home-shipping__step-icon > .dp-ic {
  width: var(--dp-ship-step-icon-fs); height: var(--dp-ship-step-icon-fs);
  stroke-width: var(--dp-ship-step-icon-sw);
}
.dp-inv-empty__icon > .dp-ic {
  width: var(--dp-inv-empty-icon-fs); height: var(--dp-inv-empty-icon-fs);
  stroke-width: var(--dp-inv-empty-icon-sw);
}
.dp-feature-card__icon > .dp-ic {
  width: var(--dp-feature-icon-fs); height: var(--dp-feature-icon-fs);
  stroke-width: var(--dp-feature-icon-sw);
}
.dp-home-contact__icon > .dp-ic {
  width: var(--dp-contact-icon-fs); height: var(--dp-contact-icon-fs);
  stroke-width: var(--dp-contact-icon-sw);
}
.dp-con-trust-card__icon > .dp-ic {
  width: var(--dp-page-card-icon-fs); height: var(--dp-page-card-icon-fs);
  stroke-width: var(--dp-page-card-icon-sw);
}
.dp-abt-check__icon > .dp-ic {
  width: var(--dp-abt-check-icon-fs); height: var(--dp-abt-check-icon-fs);
  stroke-width: var(--dp-abt-check-icon-sw);
}
.dp-abt-val__icon > .dp-ic {
  width: var(--dp-abt-val-icon-fs); height: var(--dp-abt-val-icon-fs);
  stroke-width: var(--dp-abt-val-icon-sw);
}
.dp-abt-ci__icon > .dp-ic,
.dp-con-ci__icon > .dp-ic {
  width: var(--dp-page-ci-icon-fs); height: var(--dp-page-ci-icon-fs);
  stroke-width: var(--dp-page-ci-icon-sw);
}

.dp-feature-card__icon {
  width: 68px;
  height: 68px;
  border-radius: var(--dp-feature-icon-radius);
  background: var(--dp-feature-icon-bg);
  border: var(--dp-feature-icon-border);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--dp-feature-icon-color);
  font-size: var(--dp-feature-icon-fs);
  line-height: var(--dp-feature-icon-lh);
  position: relative;
  z-index: 1;
  /* FIX (uniformity audit): was 4px. The card is a 12px-gap flex column, so a
     4px icon margin put the h3 16px below the decorative icon and 22px above
     the paragraph it introduces — the heading grouped with the ornament
     instead of with its own copy. 16px is the value page-about, page-shipping
     and page-thank-you were already overriding this rule with. */
  margin: 0 auto 16px;
}
.dp-feature-card__title {
  font-family: var(--dp-font-heading);
  color: var(--dp-feature-title-color);
  font-size: var(--dp-feature-title-fs);
  font-weight: var(--dp-feature-title-fw);
  margin: 0;
  position: relative;
  z-index: 1;
}
.dp-feature-card__text,
.dp-feature-card p {
  color: var(--dp-feature-text-color);
  font-size: var(--dp-feature-text-fs);
  line-height: var(--dp-feature-text-lh);
  margin: 0;
  position: relative;
  z-index: 1;
}
.dp-feature-card h3 {
  font-family: var(--dp-font-heading);
  color: var(--dp-feature-title-color);
  font-size: var(--dp-feature-title-fs);
  font-weight: var(--dp-feature-title-fw);
  margin: 0 0 10px;
  position: relative;
  z-index: 1;
}

/* ─── STEP CARD (how it works) ─── */
.dp-step-card {
  background: var(--dp-bg-card);
  border: var(--dp-step-border);
  border-radius: var(--dp-step-radius);
  padding: 32px 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  text-align: center;
  align-items: center;
  position: relative;
  transition: border-color .3s ease, transform .3s ease;
}
.dp-step-card h3 {
  font-family: var(--dp-font-heading);
  color: var(--dp-step-title-color);
  font-size: var(--dp-step-title-fs);
  font-weight: var(--dp-step-title-fw);
  margin: 0 0 6px;
}
.dp-step-card p {
  color: var(--dp-step-text-color);
  font-size: var(--dp-step-text-fs);
  line-height: var(--dp-step-text-lh);
  margin: 0;
}
.dp-step-card__list {
  list-style: none;
  padding: 0;
  margin: 10px 0 0;
  text-align: left;
  width: 100%;
}
.dp-step-card__list li {
  color: var(--dp-step-list-color);
  font-size: var(--dp-step-list-fs);
  line-height: var(--dp-step-list-lh);
  padding-left: 18px;
  position: relative;
  margin-bottom: 6px;
}
/* THIS RULE DRAWS ON NO PAGE. .dp-step-card__list is in no template: the class
   was searched for across every .php and .js file in the theme and appears
   nowhere, and the DOM was counted on all eight page types (home, inventory,
   about, contact, shipping, reserve, thank-you, 404) on the live install -
   .dp-step-card is present four times on /shipping/ and .dp-step-card__list is
   zero everywhere. So the arrow below is never painted, and converting it to a
   mask would be converting something nobody can see. It also CANNOT be
   converted under the rule that an explicit box must equal the box the block
   renders at today: there is no rendered box to measure.
   Left exactly as it is, and the rule left in place, because the step cards it
   styles are real and a bullet list may yet be added to them. */
.dp-step-card__list li::before {
  content: "→";
  position: absolute;
  left: 0;
  color: var(--dp-accent);
  font-weight: var(--dp-step-list-tick-fw);
}
.dp-step-card__list a {
  color: var(--dp-accent);
  text-decoration: none;
}
.dp-step-card:hover {
  transform: translateY(-4px);
  border-color: var(--dp-step-card-border-hover);
}
.dp-step-card__num {
  font-family: var(--dp-font-numeric);
  width: 52px;
  height: 52px;
  border-radius: var(--dp-step-num-radius);
  background: var(--dp-accent-soft);
  border: 2px solid var(--dp-accent-border);
  color: var(--dp-accent);
  font-size: var(--dp-step-num-fs);
  font-weight: var(--dp-step-num-fw);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-bottom: 8px;
}
.dp-step-card__title {
  font-family: var(--dp-font-heading);
  color: var(--dp-step-title-color);
  font-size: var(--dp-step-title-fs);
  font-weight: var(--dp-step-title-fw);
  margin: 0;
}
.dp-step-card__text {
  color: var(--dp-step-text-color);
  font-size: var(--dp-step-text-fs);
  line-height: var(--dp-step-text-lh);
  margin: 0;
}

/* ─── FAQ ─── */
.dp-faq {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 860px;
  margin: 0 auto;
  text-align: left;
}
.dp-faq-item {
  background: var(--dp-bg-card);
  border: var(--dp-faq-item-border);
  border-radius: var(--dp-faq-item-radius);
  overflow: hidden;
  transition: border-color .3s;
}
.dp-faq-item--open {
  border-color: var(--dp-faq-item-border-open);
}
.dp-faq-item__q {
  width: 100%;
  background: none;
  border: none;
  color: var(--dp-faq-q-color);
  font-size: var(--dp-faq-q-fs);
  font-weight: var(--dp-faq-q-fw);
  padding: 20px 22px;
  text-align: left;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-family: var(--dp-font-ui);
  transition: color .2s;
}
.dp-faq-item__q:hover { color: var(--dp-accent); }
/* ── The open question ──
   Measured before this rule existed: fg, bg, border-color, box-shadow and
   every other paint property of the TRIGGER were byte-identical open and
   closed, on all three skins, after a real click that flipped aria-expanded
   to true. Only the "+" rotated. So the one rule here, and deliberately in
   style.css and not in the four templates that each carry their own copy of
   the FAQ block: (0,2,0) beats every `.dp-faq-item__q` those templates
   declare later, so an open row looks the same on /about/, /contact/,
   /reserve/ and /shipping/ from ONE definition.
   background only. font-weight or padding would re-flow the question text
   and move a box, which this round may not do. */
.dp-faq-item--open .dp-faq-item__q { background: var(--dp-faq-q-bg-open); }
.dp-faq-item__q > span:first-child { flex: 1; }
.dp-faq-item__icon {
  font-size: var(--dp-faq-icon-fs);
  font-weight: var(--dp-faq-icon-fw);
  color: var(--dp-cta);
  flex-shrink: 0;
  margin-left: 16px;
  transition: transform .3s;
}
.dp-faq-item--open .dp-faq-item__icon { transform: rotate(45deg); }
.dp-faq-item__a { display: none; padding: 0 22px 20px; }
.dp-faq-item--open .dp-faq-item__a { display: block; }
.dp-faq-item__a p {
  color: var(--dp-faq-a-color);
  font-size: var(--dp-faq-a-fs);
  line-height: var(--dp-faq-a-lh);
  margin: 0;
}

/* ─── SECTION HEAD (kicker + title + subtitle) — bulletproof ─── */
.dp-section-head {
  text-align: center;
  max-width: 800px;
  margin: 0 auto 40px;
}
/* FIX (uniformity audit): every page template invented its own section-head
   class and none re-declared the kicker margin, so the intended 20px applied
   on home only and the other five rendered 0px — the kicker pill sat flush
   against a 52px headline on about, contact and shipping. One value, one rule.

   FIX (this pass), two holes in that rule, both measured:

   1. `.dp-rv-sec-head .dp-kicker` matched NOTHING. Reserve's three section
      heads emit `.dp-rv-kicker`, not `.dp-kicker` (all three section heads
      in page-reserve.php), so the selector was dead code and reserve kept the 10px its own
      template declared — 20px everywhere else, 10px on the one page the
      RESERVE button leads to. The selector now names the class reserve
      actually emits, and page-reserve.php no longer declares a margin of its
      own. (Reserve's kicker is still bare accent text rather than the pill —
      a separate, deliberate, per-skin treatment; see the note there.)

   2. The rule only ever listed SECTION heads. The same kicker-then-heading
      pair also opens four cards — the home story panel, the home shipping
      panel, the about story column and the thank-you card — and in those the
      pill sat flush against the headline, exactly the defect this rule was
      written to remove. 36 instances, all three skins, all three widths.
      Listed here rather than applied to `.dp-kicker` itself, because the hero
      kicker's rhythm comes from its own block and is not this rule's to set. */
.dp-section-head .dp-kicker,
.dp-abt-sec-head .dp-kicker,
.dp-con-sec-head .dp-kicker,
.dp-shp-sec-head .dp-kicker,
.dp-ty-sec-head .dp-kicker,
.dp-sl-related__head .dp-kicker,
.dp-home-story__content .dp-kicker,
.dp-home-shipping .dp-kicker,
.dp-abt-story__left .dp-kicker,
.dp-ty-card .dp-kicker,
.dp-rv-sec-head .dp-rv-kicker {
  margin-bottom: 20px;
}
.dp-section-head__title {
  font-family: var(--dp-font-heading);
  font-size: var(--dp-heading-title-fs);
  font-weight: var(--dp-heading-title-fw);
  color: var(--dp-heading-title-color);
  line-height: var(--dp-heading-title-lh);
  letter-spacing: var(--dp-heading-title-ls);
  margin: 0 0 16px;
}
.dp-section-head__divider {
  width: 80px;
  height: 3px;
  border-radius: var(--dp-heading-divider-radius);
  background: linear-gradient(90deg, var(--dp-accent), var(--dp-accent-dark));
  margin: 0 auto 20px;
}
.dp-section-head__sub {
  font-size: var(--dp-heading-sub-fs);
  color: var(--dp-heading-sub-color);
  line-height: var(--dp-heading-sub-lh);
  margin: 0;
}

/* ─── KICKER BULLETPROOF (force white on any accent color) ─── */
.dp-kicker {
  color: var(--dp-kicker-color) !important;  /* Bulletproof — always visible on accent-soft bg */
}

.dp-qv-trigger:focus-visible,
.dp-qv-trigger:focus-visible:hover {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
  outline: none;
  box-shadow: var(--dp-focus-ring);
}

/* ══════════════════════════════════════════════════════════════
   GLOBAL HERO COMPONENT — use .dp-hero on all pages for consistency
   ══════════════════════════════════════════════════════════════ */

/* ─── Hero reveal stagger animations ─── */
/* FIX v1.3.11: Text visible by default, animation only enhances (backwards fill) */
.dp-hero .dp-reveal {
  opacity: 1;
  animation: var(--dp-hero-reveal);
}
.dp-hero .dp-reveal--1 { animation-delay: .15s; }
.dp-hero .dp-reveal--2 { animation-delay: .35s; }
.dp-hero .dp-reveal--3 { animation-delay: .55s; }
.dp-hero .dp-reveal--4 { animation-delay: .75s; }
.dp-hero .dp-reveal--5 { animation-delay: .95s; }

@media (prefers-reduced-motion: reduce) {
  .dp-hero .dp-reveal {
    animation: none;
  }
}

@keyframes dpHeroReveal {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Responsive */

  
  
  

/* ══════════════════════════════════════════════════════════════
   GLOBAL FORM WRAPPER — use on all CF7 form containers
   ══════════════════════════════════════════════════════════════ */
.dp-form-wrap {
  background: var(--dp-form-bg);
  border: var(--dp-form-border);
  border-radius: var(--dp-form-radius);
  padding: 36px;
  text-align: left;
}
.dp-form-head {
  margin-bottom: 24px;
}
.dp-form-head h3 {
  font-family: var(--dp-font-heading);
  color: var(--dp-form-title-color);
  font-size: var(--dp-form-title-fs);
  font-weight: var(--dp-form-title-fw);
  margin: 0 0 6px;
}
.dp-form-head p {
  color: var(--dp-form-sub-color);
  font-size: var(--dp-form-sub-fs);
  margin: 0;
}
.dp-form-note {
  text-align: center;
  color: var(--dp-form-note-color);
  font-size: var(--dp-form-note-fs);
  margin-top: 16px;
}
.dp-form-actions {
  margin-top: 24px;
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}
@media(max-width:768px) {
  .dp-form-wrap { padding: 24px 18px; }
}

/* ── CF7 field styling (applies globally) ── */
.dp-form-wrap .wpcf7-form-control-wrap { display: block; }
.dp-form-wrap input[type="text"],
.dp-form-wrap input[type="email"],
.dp-form-wrap input[type="tel"],
.dp-form-wrap input[type="number"],
.dp-form-wrap input[type="url"],
.dp-form-wrap select,
.dp-form-wrap textarea {
  /* See the note on .wpcf7-form textarea: block-level, no baseline slack. */
  display: block;
  width: 100%;
  padding: 14px 16px;
  background: var(--dp-field-bg);
  border: var(--dp-field-border);
  border-radius: var(--dp-field-radius);
  color: var(--dp-field-color);
  font-size: var(--dp-field-fs);
  font-family: var(--dp-font-ui);
  transition: var(--dp-field-transition);
  box-sizing: border-box;
}
/* The field focus rule, with `input` restored to it. A previous round inserted
   the select-arrow rule directly after this selector's comma, which silently
   moved `input:focus` OUT of this rule and INTO the arrow rule — so every text
   input grew a dropdown chevron and a 44px right gutter the moment it was
   focused, and lost its focus border and background. Three defects from one
   misplacement, on all three skins. */
.dp-form-wrap input:not([type="submit"]):not([type="button"]):focus,
.dp-form-wrap select:focus,
.dp-form-wrap textarea:focus {
  outline: none;
  border-color: var(--dp-field-border-focus);
  background: var(--dp-field-bg-focus);
}

/* ── THE DROPDOWN ARROW, PUT BACK ──
   .wpcf7-form select asks for appearance:none, a custom arrow image and a 44px
   right gutter to clear it. `.dp-form-wrap select` earlier in this file ties it
   on specificity (0,1,1) and wins on source order — and it does so by accident:
   its `background:` SHORTHAND resets background-image to none and its `padding:`
   shorthand resets padding-right to 16px. Only appearance:none survived, so the
   native arrow was stripped and its replacement thrown away, and "Trailer Type"
   on the shipping form rendered as something indistinguishable from a text input.
   Pre-existing; identical on 3.1.0.

   Fixed here rather than by editing that rule, because it is shared with textarea
   and splitting its shorthands would take the padding off the textarea too.

   `select:focus` is listed explicitly: the focus rule above sets the `background`
   SHORTHAND, which resets background-image to none, and it would otherwise win on
   a focused select at (0,2,1). Matching that specificity and coming later keeps
   the arrow in both states, while background-COLOR still comes from the focus rule.

   THIS CANNOT MOVE ANYTHING: the select is width:100% with box-sizing:border-box,
   so its border box is fixed by the container. Raising padding-right from 16px to
   44px re-divides space INSIDE a box whose outside is already decided, and the
   text is left-aligned, so the text does not move either. */
.dp-form-wrap select,
.dp-form-wrap select:focus {
  background-image: var(--dp-input-arrow);
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 44px;
}
/* The :focus rule above only recolours the field's own border, which a skin
   may set to a low-contrast hairline. The keyboard ring is separate. */
.dp-form-wrap input:not([type="submit"]):not([type="button"]):focus-visible,
.dp-form-wrap select:focus-visible,
.dp-form-wrap textarea:focus-visible {
  box-shadow: var(--dp-focus-ring);
}
.dp-form-wrap textarea { min-height: 120px; resize: vertical; }
.dp-form-wrap label {
  display: block;
  color: var(--dp-label-color);
  font-size: var(--dp-label-fs);
  font-weight: var(--dp-label-fw);
  margin-bottom: var(--dp-form-label-gap);
  letter-spacing: var(--dp-label-ls);
  /* See the note on .wpcf7-form label. --dp-field-border-w must stay in step
     with --dp-field-border's width in every skin. */
  padding-left: calc(16px + var(--dp-field-border-w, 1px));
}
/* FIX (uniformity audit): this said 16px while .wpcf7-form p said 18px, so
   the same form was spaced one way on About/Contact/Shipping and another on
   Home/Listing/Reserve. One value now, and it lives in :root. */
.dp-form-wrap p { margin: 0 0 var(--dp-form-gap); }
/* ── What is left of the second submit rule ──
   3.2.0: every other declaration this rule carried — display, align-items,
   justify-content, min-height, background, color, border, border-radius,
   font-size, font-weight, font-family, cursor, transition, box-shadow and
   width — is also declared by `.wpcf7-form input[type="submit"]` at (0,2,1)
   against this selector's (0,2,0), so not one of them ever reached the
   button. Its :hover was the same story at (0,3,1) against (0,3,0). They are
   deleted, not commented out: a declaration that cannot win is not a
   fallback, it is a second opinion that misleads the next reader.

   These two DO win, because the other rule does not declare them, and they
   are the whole reason the submit has a different box model inside a
   .dp-form-wrap (contact, about, shipping) than outside one (home, listing,
   reserve, where the UA's 1px 6px stands). Unifying THAT is a box change and
   therefore not this round's to make. */
.dp-form-wrap .wpcf7-submit {
  gap: 10px;
  padding: 0 32px;
}
/* (0,3,0) / (0,4,0). The rules these have to outrank moved in 3.2.0: the
   submit's only shadow rules are now `.wpcf7-form input[type="submit"]` at
   (0,2,1) and its :hover at (0,3,1), and both are beaten here on class count.
   skin-heavy chamfers this control, so the ring still has to be inset. */
.dp-form-wrap .wpcf7-submit:focus-visible,
.dp-form-wrap .wpcf7-submit:focus-visible:hover { box-shadow: var(--dp-focus-ring-btn); }
.dp-form-wrap .wpcf7-response-output {
  margin: 20px 0 0;
  padding: 14px 18px;
  border-radius: var(--dp-form-response-radius);
  font-size: var(--dp-form-response-fs);
}
.dp-form-wrap .wpcf7-not-valid-tip {
  color: var(--dp-form-invalid-color);
  font-size: var(--dp-form-invalid-fs);
  margin-top: 4px;
  font-weight: var(--dp-form-invalid-fw);
}

/* ══════════════════════════════════════════════════════════════
   HERO — UNIFIED GLOBAL (single source of truth, all pages)
   ══════════════════════════════════════════════════════════════ */
body .dp-hero,
section.dp-hero,
.dp-hero {
  position: relative !important;
  min-height: 600px !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  overflow: hidden !important;
  text-align: center !important;
  width: 100% !important;
}
.dp-hero__bg {
  position: absolute;
  inset: 0;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  transform: scale(1.04);
  animation: var(--dp-hero-zoom);
  z-index: 0;
}
.dp-hero__overlay {
  position: absolute;
  inset: 0;
  background: var(--dp-hero-overlay);
  z-index: 1;
}
.dp-hero .dp-hero__inner,
.dp-hero__inner {
  position: relative !important;
  z-index: 2 !important;
  max-width: 940px !important;
  /* FIX (uniformity audit): the inline gutter was 20px while the header, the
     footer and all nine page containers use 16px, so at phone width the
     hero copy started 4px right of the header logo above it. (The 18px in
     front-page.php's 767px block never applied - this !important always
     won - which is why a source read reported 18px and the screen showed 20.) */
  padding: 80px 16px !important;
  margin: 0 auto !important;
  text-align: center !important;
  width: 100% !important;
}
.dp-hero__title {
  font-family: var(--dp-font-heading);
  margin: 12px 0 18px;
  color: var(--dp-hero-title-color);
  font-size: var(--dp-hero-title-fs);
  font-weight: var(--dp-hero-title-fw);
  letter-spacing: var(--dp-hero-title-ls);
  line-height: var(--dp-hero-title-lh);
}
.dp-hero__title span {
  display: block;
  color: var(--dp-accent);
}
.dp-hero__sub {
  color: var(--dp-hero-sub-color);
  font-size: var(--dp-hero-sub-fs);
  line-height: var(--dp-hero-sub-lh);
  max-width: 720px;
  margin: 0 auto 24px;
}
.dp-hero__pills {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin: 24px 0 28px;
}
.dp-hero__pills span {
  background: var(--dp-hero-pill-bg);
  border: var(--dp-hero-pill-border);
  color: var(--dp-hero-pill-color);
  padding: 10px 18px;
  border-radius: var(--dp-hero-pill-radius);
  font-size: var(--dp-hero-pill-fs);
  font-weight: var(--dp-hero-pill-fw);
  letter-spacing: var(--dp-hero-pill-ls);
  transition: border-color .25s ease, background .25s ease;
}
.dp-hero__pills span:hover {
  background: var(--dp-hero-pill-bg-hover);
  border-color: var(--dp-hero-pill-border-hover);
}
.dp-hero__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
  margin-top: 8px;
}
.dp-hero__note {
  margin-top: 22px;
  color: var(--dp-hero-note-color);
  font-size: var(--dp-hero-note-fs);
  letter-spacing: var(--dp-hero-note-ls);
}
@keyframes dpHeroZoom {
  from { transform: scale(1.04); }
  to   { transform: scale(1.0); }
}
@media (max-width: 768px) {
  .dp-hero { min-height: 480px; }
  .dp-hero__title { letter-spacing: var(--dp-hero-title-ls-sm); }
  .dp-hero__actions { flex-direction: column; align-items: stretch; }
  .dp-hero__actions .dp-btn { width: 100%; }
  .dp-hero__pills span { width: 100%; text-align: center; }
}
