/*
 * DEMARCA Affiliate Styles — ContentForge article components
 *
 * One stylesheet, three brands. Everything is expressed through custom
 * properties so a brand is a palette swap, never a fork of the rules.
 *
 * ⚠️ THE RULE THIS FILE EXISTS UNDER
 * The PHP strips inline styles from these components. Anything it
 * strips and this file does not replace renders unstyled — that is how
 * v1.0.0 shipped invisible product links and v1.1.0 collapsed the
 * pillar's jump-links into a vertical stack. Every hook the PHP adds
 * (.cfChoice .cfBtn .cfBadge .cfRow .cfGrid .cfTableGrid .cfProductImg)
 * has rules here, and every component is matched as BOTH class and id,
 * because the generator emits both.
 *
 * DESIGN NOTES
 * The theme owns the typeface; this file owns scale, weight, tracking
 * and colour. Two decisions carry the look:
 *   1. Summary blocks are hairline panels with a left accent rule and a
 *      tracked eyebrow label — editorial, not a banner. The old
 *      saturated gradient card competed with the article's own H2s.
 *   2. Buttons read as objects: 6px radius, 600 weight, a layered
 *      shadow and a 6% sheen. Flat fills read as theme links.
 *
 * Two colours are deliberately NOT brand-tinted:
 *   --cf-thead   table headers are neutral slate everywhere. Brand
 *                colour across a whole header row reads as decoration
 *                and fought the winner column for attention.
 *   --cf-choice  the editor's choice is ALWAYS green, on every brand.
 *                Green means "the good one" to everybody; amber on the
 *                workshop brand read as a warning.
 *
 * And the buy button has its own colour, separate from --cf-accent:
 *   --cf-cta / --cf-cta-hover
 * The accent is the brand talking; the CTA is the reader clicking, and
 * they want different things.
 *
 * 🔴 SIZE AND COLOUR ARE ONE DECISION, NOT TWO.
 * WCAG 1.4.3 asks 4.5:1 of normal text and 3:1 of "large text" (>=18.66px
 * bold). v1.4.0 bought the lower threshold by setting 19px/700, and the
 * button read as oversized. v1.5.0 changed the fill instead — to Amazon's
 * own amber, which passes at any size but is their trade dress, so it was
 * reverted. This is the interim state while a design is chosen; the five
 * candidates are in the button-styles artifact.
 *
 * The reasoning that still holds: a SOLID button with WHITE text at normal
 * size is necessarily dark, because 4.5:1 against white ink caps the
 * background at ~0.175 luminance whatever the hue. Wanting "compact, light
 * and white-on-colour" at once is asking for something the contrast maths
 * does not allow.
 *
 * Every button ink is set explicitly next to its background. A per-brand
 * ink token once shipped near-black labels onto slate buttons at 1.02:1.
 * Buttons on light surfaces are GHOST (border + dark label), never a
 * pale fill — see the table variants.
 */

:root,
body.dmca-brand-neutral {
  --cf-accent: #0f766e;
  --cf-accent-dark: #115e59;
  --cf-accent-soft: #f0fdfa;
  --cf-primary: #1e293b;
  --cf-ink: #334155;
  --cf-muted: #64748b;
  --cf-line: #e2e8f0;
  --cf-surface: #f8fafc;

  /* Shared across every brand — see the note above. */
  --cf-thead: #1f2937;
  --cf-choice: #16a34a;
  --cf-choice-dark: #15803d;
  --cf-choice-darker: #166534;
  --cf-choice-tint: #f0fdf4;

  /* The buy button uses --cf-cta directly.
     ⛔ It was briefly Amazon's own palette (#ffd814 / #0f1111). That is
     trade dress: dressing our link up as Amazon's buy button can imply an
     endorsement the Associates terms do not grant, and Amazon supplies
     official creatives to anyone who wants their look. Reverted
     2026-08-16, pending a chosen design. Whatever replaces it must NOT
     imitate Amazon's buttons.
     ⚠️ And no --cf-buy alias: a custom property whose value is var(...)
     resolves against the element it is DECLARED on, so an alias here on
     :root never saw the per-brand override on <body> and painted all
     three sites teal. */
  --cf-cta: #0f766e;
  --cf-cta-hover: #115e59;

  --cf-warning: #f59e0b;
  --cf-warning-soft: #fffbeb;
  --cf-warning-ink: #78350f;
  --cf-info: #3b82f6;
  --cf-info-soft: #eff6ff;
  --cf-info-ink: #1e40af;
  --cf-danger: #dc2626;

  --cf-radius: 10px;
  --cf-radius-btn: 6px;
}

/* SanderScore — workshop, oiled wood, ochre.
   Softened from #c2410c: at full saturation it read as an error state,
   which is fatal on a block that is meant to say "this is the good one". */
body.dmca-brand-sander {
  --cf-accent: #b45309;
  --cf-accent-dark: #92400e;
  --cf-accent-soft: #fffbeb;
  --cf-primary: #1c1917;
  --cf-ink: #292524;
  --cf-muted: #78716c;
  --cf-line: #e7e5e4;
  --cf-surface: #fafaf9;

  /* Blue against a warm, orange-toned site: the CTA stops competing with
     the brand and starts contrasting with it. 5.17:1 on white text. */
  --cf-cta: #2563eb;
  --cf-cta-hover: #1d4ed8;
}

/* ThePatioPro — garden, foliage, green. */
body.dmca-brand-patio {
  --cf-accent: #15803d;
  --cf-accent-dark: #166534;
  --cf-accent-soft: #f0fdf4;
  --cf-primary: #14532d;
  --cf-ink: #1f2937;
  --cf-muted: #6b7280;
  --cf-line: #e5e7eb;
  --cf-surface: #f8faf9;

  /* ⚠️ green-600 (#16a34a) is only 3.30:1 under white text. It was allowed
     while the label was 19px/700 — "large text", 3:1 — and became
     non-compliant the moment the label went back to 15px. Size and colour
     are one decision; changing one without re-checking the other is how
     this shipped failing. Back to green-700 at 5.02:1 for the interim. */
  --cf-cta: #15803d;
  --cf-cta-hover: #166534;
}

/* Mirrorank — vanity, cosmetics, violet. */
body.dmca-brand-mirror {
  --cf-accent: #7e22ce;
  --cf-accent-dark: #6b21a8;
  --cf-accent-soft: #faf5ff;
  --cf-primary: #3b0764;
  --cf-ink: #3f3f46;
  --cf-muted: #71717a;
  --cf-line: #e4e4e7;
  --cf-surface: #fafafa;

  --cf-cta: #7e22ce;
  --cf-cta-hover: #6b21a8;
}

/* ── Buttons ──────────────────────────────────────────────────────
   .cfBtn is added by the PHP to inline-styled anchors that were drawn
   as buttons. Without it every "Shop Now at Amazon" degrades to a bare
   text link — the single most expensive thing this plugin can break. */

.cfBtn,
a.cfBtn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background-color: var(--cf-cta);
  /* Flat fill, no sheen — this is the approved "solid brand" specimen. The
     depth comes from the layered shadow below, not from a gradient. */
  background-image: none;
  color: #fff !important;
  padding: 10px 18px;
  border: 1.5px solid transparent;
  border-radius: var(--cf-radius-btn);
  font-weight: 600;
  font-size: 15px;
  line-height: 1.25;
  text-decoration: none !important;
  white-space: nowrap;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.10), 0 2px 6px rgba(15, 23, 42, 0.12);
  transition: transform 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
}

/* ThePatioPro's theme paints `p a:hover` with an inset highlighter bar
   and `table a:hover` with `color: … !important`. Both would gut the
   button, so these two properties are defended explicitly. */
.cfBtn:hover,
.cfBtn:focus,
a.cfBtn:hover,
a.cfBtn:focus {
  background-color: var(--cf-cta-hover);
  color: #fff !important;
  text-decoration: none !important;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), 0 6px 16px rgba(15, 23, 42, 0.20);
  transform: translateY(-1px);
}
.cfBtn:active { transform: translateY(0); box-shadow: 0 1px 2px rgba(15, 23, 42, 0.20); }
.cfBtn:focus-visible { outline: 2px solid var(--cf-accent); outline-offset: 3px; }

.cfProductShot + p > .cfBtn,
p > .cfBtn { margin: 4px 0; }

/* ── The buy button ───────────────────────────────────────────────
   .cfBtnBuy is added by the PHP to anchors that actually point at Amazon.
   The jump-links are .cfBtn too, so this class — not .cfBtn — is what
   carries the shop treatment and the cart. */
.cfBtnBuy,
a.cfBtnBuy {
  background-color: var(--cf-cta);
  color: #fff !important;
  border-color: transparent;
  font-weight: 700;
}
.cfBtnBuy:hover,
.cfBtnBuy:focus,
a.cfBtnBuy:hover,
a.cfBtnBuy:focus {
  background-color: var(--cf-cta-hover);
  color: #fff !important;
  border-color: transparent;
}
/* The cart lives here, not in the label: text in the markup is prose, and
   the article did not write it. This also guarantees every buy button has
   exactly one — the source had some with, some without, some with two. */
/* An inline SVG cart, not the 🛒 emoji: the emoji renders as a different
   picture on every platform (and in colour), which is the opposite of the
   consistency this normalisation is for. Stroke is baked white because
   every button carrying this class has a white label. Generic cart — not
   Amazon's glyph. */
.cfBtnBuy::before {
  content: "";
  flex: 0 0 16px;
  width: 16px;
  height: 16px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='9' cy='21' r='1'/%3E%3Ccircle cx='20' cy='21' r='1'/%3E%3Cpath d='M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

@media (prefers-reduced-motion: reduce) {
  .cfBtn { transition: none; }
  .cfBtn:hover, .cfBtn:focus { transform: none; }
}

/* ── Comparison tables ────────────────────────────────────────────
   .cfTableGrid is added by the PHP to every table inside a component,
   which is the only thing four generations of generator output have in
   common: some tables carry id="cfTableInner", some id="cfTableInner2",
   and the pillar's carry no attribute at all. */

div[id^="cfTable"],
div[class~="cfTable"],
div[id^="cfInfoTable"] {
  clear: both;
  width: 100%;
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin: 28px 0;
  border: 1px solid var(--cf-line);
  border-radius: var(--cf-radius);
}

/* Default: a table with no scroll wrapper scrolls inside itself. It must
   never force a min-width onto the article — that is what pushed a
   comparison table out of the content column. */
.cfTableGrid {
  display: block;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  overflow-x: auto;
  border-collapse: collapse;
  margin: 28px 0;
  font-size: 14px;
  background: #fff;
}
/* Inside a wrapper, the wrapper does the scrolling and the table can go
   back to being a table. */
div[id^="cfTable"] > .cfTableGrid,
div[class~="cfTable"] > .cfTableGrid {
  display: table;
  overflow: visible;
  min-width: 640px;
  margin: 0;
}

.cfTableGrid th,
.cfTableGrid td {
  padding: 12px 16px;
  text-align: center;
  border: 0;
  border-top: 1px solid var(--cf-line);
  vertical-align: middle;
  color: var(--cf-ink);
  background: transparent;
}
.cfTableGrid thead th,
.cfTableGrid tr:first-child th {
  background: var(--cf-thead);
  color: #fff;
  font-weight: 600;
  font-size: 13.5px;
  letter-spacing: 0.01em;
  border-top: 0;
  line-height: 1.4;
}
/* First column is the spec label, not a product. */
.cfTableGrid td:first-child,
.cfTableGrid th:first-child {
  text-align: left;
  font-weight: 600;
  color: var(--cf-ink);
  background: var(--cf-surface);
}
.cfTableGrid thead th:first-child,
.cfTableGrid tr:first-child th:first-child {
  color: #fff;
  background: var(--cf-thead);
}
.cfTableThumb,
.cfTableGrid td img {
  max-height: 104px;
  width: auto;
  max-width: 100%;
  object-fit: contain;
}
.cfTableThumbLink { display: inline-block; }
.cfTableImageRow td { padding-top: 16px; padding-bottom: 16px; }

/* The winner. Green on every brand, and outlined on all four sides so
   the column reads as one object rather than a tinted stripe — the top
   cap is a darker green so it stays visible against the green header. */
.cfTableGrid td.cfChoice {
  background: var(--cf-choice-tint);
  border-left: 2px solid var(--cf-choice);
  border-right: 2px solid var(--cf-choice);
}
/* ⚠️ Both selectors are needed. `.cfTableGrid tr:first-child th` scores
   (0,2,2) — a bare `.cfTableGrid th.cfChoice` at (0,2,1) loses to it and
   the winning column's header silently stays slate. */
.cfTableGrid thead th.cfChoice,
.cfTableGrid tr:first-child th.cfChoice {
  background: var(--cf-choice);
  color: #fff;
  border-left: 2px solid var(--cf-choice);
  border-right: 2px solid var(--cf-choice);
  border-top: 3px solid var(--cf-choice-dark);
}
.cfTableGrid tr:last-child td.cfChoice { border-bottom: 2px solid var(--cf-choice); }
/* ⚠️ The winner's button is styled once, further down, next to the ghost
   rules it contrasts with. A second copy lived here and was overridden by
   that later one — dead weight that made the file read as if the winner
   were choice-green when it is actually the brand CTA. */

.cfBadge {
  display: inline-block;
  margin-top: 5px;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.20);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  white-space: nowrap;
}

/* In a comparison table only ONE product is being recommended, so only one
   button is solid. The rest are ghosts: a row of five filled blocks was
   heavier than the data above it, and read as five equal calls to action
   when the whole point of the table is that they are not equal. */
.cfTableGrid .cfBtn {
  margin: 0;
  padding: 7px 12px;
  font-size: 13px;
  font-weight: 600;
  background-color: #fff;
  background-image: none;
  color: var(--cf-thead) !important;
  border: 1.5px solid var(--cf-line);
  box-shadow: none;
}
.cfTableGrid .cfBtn:hover,
.cfTableGrid .cfBtn:focus {
  background-color: var(--cf-surface);
  color: var(--cf-thead) !important;
  border-color: var(--cf-muted);
  box-shadow: 0 2px 8px rgba(15, 23, 42, 0.10);
}
/* Ghosts drop the cart — five carts in a row is clutter, and the column
   header already says what these are. */
.cfTableGrid .cfBtn::before { content: none; }

/* The winner keeps the real buy button. That contrast against four ghosts
   IS the recommendation. Amber on near-black is ~15:1, so it is compliant
   at this size too. */
.cfTableGrid td.cfChoice .cfBtn {
  background-color: var(--cf-cta);
  color: #fff !important;
  border-color: transparent;
  font-weight: 700;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.10);
}
.cfTableGrid td.cfChoice .cfBtn:hover,
.cfTableGrid td.cfChoice .cfBtn:focus {
  background-color: var(--cf-cta-hover);
  color: #fff !important;
  border-color: transparent;
  box-shadow: 0 2px 8px rgba(15, 23, 42, 0.18);
}
.cfTableGrid td.cfChoice .cfBtn::before { content: "🛒"; font-size: 1.05em; line-height: 1; }

/* Spec/info tables: same shell, no product columns, so no winner. */
.cfInfoGrid {
  width: 100%;
  max-width: 100%;
  min-width: 0;
  border-collapse: collapse;
  margin: 0;
  font-size: 14.5px;
  background: #fff;
}
div[id^="cfInfoTable"] > .cfInfoGrid { min-width: 480px; }
.cfInfoGrid th,
.cfInfoGrid td {
  padding: 12px 16px;
  border: 0;
  border-bottom: 1px solid var(--cf-line);
  text-align: left;
  vertical-align: top;
  color: var(--cf-ink);
}
.cfInfoGrid th {
  background: var(--cf-surface);
  font-weight: 700;
  color: var(--cf-primary);
  border-bottom: 2px solid var(--cf-line);
}
.cfInfoGrid tr:last-child td { border-bottom: 0; }

/* ── Summary blocks ───────────────────────────────────────────────
   Key Takeaways and The Verdict. A hairline panel with a left accent
   rule and a tracked eyebrow label: present, scannable, and quieter
   than the article's own headings. The previous full-bleed gradient
   card outshouted every H2 on the page. */

#cfTakeaway, .cfTakeaway,
#cfVerdict,  .cfVerdict {
  margin: 30px 0;
  padding: 22px 26px;
  background: #fff;
  border: 1px solid var(--cf-line);
  border-left: 3px solid var(--cf-accent);
  border-radius: 0 var(--cf-radius) var(--cf-radius) 0;
  color: var(--cf-ink);
  font-size: 15.5px;
  line-height: 1.7;
}
/* The verdict is the conclusion, so it earns a tint — the difference
   between the two blocks is fill, not volume. */
#cfVerdict, .cfVerdict { background: var(--cf-accent-soft); }

#cfTakeaway > p:first-child,
.cfTakeaway > p:first-child,
#cfVerdict > p:first-child,
.cfVerdict > p:first-child {
  margin: 0 0 14px;
  color: var(--cf-accent);
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
#cfTakeaway p, .cfTakeaway p,
#cfVerdict p,  .cfVerdict p { color: var(--cf-ink); margin: 0 0 10px; }
#cfTakeaway p:last-child, .cfTakeaway p:last-child,
#cfVerdict p:last-child,  .cfVerdict p:last-child { margin-bottom: 0; }

#cfTakeaway ul, .cfTakeaway ul,
#cfVerdict ul,  .cfVerdict ul { margin: 0; padding: 0; list-style: none; }
#cfTakeaway li, .cfTakeaway li,
#cfVerdict li,  .cfVerdict li {
  position: relative;
  margin: 0 0 12px;
  padding-left: 22px;
  list-style: none;
}
#cfTakeaway li:last-child, .cfTakeaway li:last-child { margin-bottom: 0; }
/* The marker: a short accent bar. These are parallel verdicts, not a
   sequence, so they are not numbered. */
#cfTakeaway li::before,
.cfTakeaway li::before,
#cfVerdict li::before,
.cfVerdict li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 11px;
  height: 2px;
  background: var(--cf-accent);
  border-radius: 1px;
}
#cfTakeaway strong, .cfTakeaway strong,
#cfVerdict strong,  .cfVerdict strong { color: var(--cf-primary); }
#cfTakeaway a, .cfTakeaway a,
#cfVerdict a,  .cfVerdict a {
  color: var(--cf-accent);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* The end-of-article CTA banner keeps its weight — it is the last thing
   on the page and has nothing left to compete with. */
#cfCta, #cfCta2, .cfCta {
  margin: 34px 0;
  padding: 28px 32px;
  border-radius: var(--cf-radius);
  background: var(--cf-primary);
  color: #fff;
  text-align: center;
}
#cfCta p, #cfCta2 p, .cfCta p { color: #fff; margin: 0 0 14px; }
#cfCta > p:first-child, #cfCta2 > p:first-child { font-size: 19px; font-weight: 700; }
#cfCta .cfBtn, #cfCta2 .cfBtn {
  background-color: #fff;
  background-image: none;
  color: var(--cf-primary) !important;
}
#cfCta .cfBtn:hover, #cfCta2 .cfBtn:hover {
  background-color: #fff;
  color: var(--cf-primary) !important;
}
.cfBtn:focus-visible { outline-color: var(--cf-cta); }

#cfQuickPick, .cfQuickPick {
  margin: 26px 0;
  padding: 20px 24px;
  border: 1px solid var(--cf-line);
  border-left: 3px solid var(--cf-accent);
  border-radius: 0 var(--cf-radius) var(--cf-radius) 0;
  background: var(--cf-accent-soft);
  color: var(--cf-ink);
}
#cfQuickPick > p:first-child, .cfQuickPick > p:first-child {
  margin: 0 0 12px;
  color: var(--cf-accent);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
#cfQuickPick p, .cfQuickPick p { margin: 0 0 10px; }
#cfQuickPick p:last-child, .cfQuickPick p:last-child { margin-bottom: 0; }
#cfQuickPick a, .cfQuickPick a { color: var(--cf-accent); font-weight: 600; }

/* ── Callouts ─────────────────────────────────────────────────────
   Each variant sets background AND text colour together. The source
   markup colours the label and the body inline for the variant's own
   background; strip one without the other and you get, literally,
   green text on a red panel.

   The tip is deliberately NOT brand-coloured: a full amber panel on the
   workshop brand reads as a warning, which is the opposite of a tip. */

.cfCallout {
  margin: 22px 0;
  padding: 15px 20px;
  border-radius: 0 8px 8px 0;
  border-left: 3px solid var(--cf-accent);
  background: var(--cf-surface);
  color: var(--cf-ink);
  font-size: 15px;
  line-height: 1.65;
}
.cfCallout p { margin: 0 0 6px; color: inherit; }
.cfCallout p:last-child { margin-bottom: 0; }
.cfCallout > p:first-child {
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.04em;
}

.cfTip { border-left-color: var(--cf-accent); background: var(--cf-surface); color: var(--cf-ink); }
.cfTip > p:first-child { color: var(--cf-accent); }

.cfWarning { border-left-color: var(--cf-warning); background: var(--cf-warning-soft); color: var(--cf-warning-ink); }
.cfWarning > p:first-child { color: #92400e; }

.cfInfo { border-left-color: var(--cf-info); background: var(--cf-info-soft); color: var(--cf-info-ink); }
.cfInfo > p:first-child { color: #1d4ed8; }

.cfRelated {
  margin: 18px 0;
  padding: 12px 16px;
  background: var(--cf-surface);
  border-left: 3px solid var(--cf-accent);
  border-radius: 0 8px 8px 0;
  font-size: 15px;
  color: var(--cf-ink);
}
.cfRelated a { color: var(--cf-accent); font-weight: 600; }
.cfDiscontinued {
  margin: 14px 0;
  padding: 12px 16px;
  background: var(--cf-warning-soft);
  border-left: 3px solid var(--cf-warning);
  border-radius: 0 8px 8px 0;
  font-size: 14px;
  line-height: 1.55;
  color: var(--cf-warning-ink);
}

/* ── Layout containers the PHP tagged ─────────────────────────────
   A div whose only job was `display:flex` (the pillar's jump-links)
   collapses into a stack once its inline style is gone. */

.cfRow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin: 18px 0;
}
.cfRow br { display: none; }
/* Jump-links are navigation, not commerce: neutral, compact, no sheen.
   Ink pinned white for the same reason as the table buttons — a dark
   surface must never inherit a dark CTA ink. */
.cfRow .cfBtn::before { content: none; }
.cfRow .cfBtn {
  padding: 7px 15px;
  font-size: 13px;
  font-weight: 600;
  background-color: var(--cf-thead);
  background-image: none;
  color: #fff !important;
  box-shadow: none;
}
.cfRow .cfBtn:hover,
.cfRow .cfBtn:focus {
  background-color: var(--cf-accent);
  color: #fff !important;
  box-shadow: 0 2px 8px rgba(15, 23, 42, 0.18);
}

.cfGrid { display: grid; gap: 14px; }

.cfProsCons {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin: 22px 0;
}
.cfProsCons > div {
  padding: 16px 20px;
  border-radius: var(--cf-radius);
  background: var(--cf-surface);
  border: 1px solid var(--cf-line);
}
.cfProsCons ul { margin: 8px 0 0 18px; }
.cfProsCons p:first-child {
  margin: 0 0 8px;
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.04em;
  color: var(--cf-primary);
}

.cfHighlights {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  margin: 22px 0;
}
.cfHighlights > div {
  padding: 16px;
  border-radius: var(--cf-radius);
  background: var(--cf-surface);
  border: 1px solid var(--cf-line);
  text-align: center;
}

@media (max-width: 640px) {
  .cfProsCons { grid-template-columns: 1fr; }
  .cfHighlights { grid-template-columns: 1fr; }
}

/* ── Product cards and review shots ───────────────────────────────
   .cfProductImg replaces the pillar's unresolved
   <!-- PRODUCT_IMAGE:ASIN --> placeholders. */

/* The photo sits left at a medium size and the review text wraps to its
   right — the same shape as a .cfHybridCard, built out of flat siblings.
   .cfProductRow is `flow-root` so it CONTAINS the float; without it the
   photo escapes past the review and shoves the next product's heading
   sideways. */
.cfProductRow { display: flow-root; margin: 0 0 18px; }
.cfProductRow > p:last-child { margin-bottom: 0; }

.cfProductShot {
  float: left;
  width: 280px;
  max-width: 42%;
  margin: 4px 26px 12px 0;
}
/* ⚠️ The size lives on the WRAPPER, not the image. Every one of these
   themes ships `.entry-content img { max-width: 100% }` at (0,1,1), which
   outranks a bare `.cfProductImg` at (0,1,0) — the photos rendered
   802px wide across the whole column. Capping the parent sidesteps the
   cascade fight entirely. */
.cfProductShot .cfProductImg {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--cf-line);
  border-radius: 8px;
  background: #fff;
  padding: 8px;
}

@media (max-width: 640px) {
  .cfProductShot {
    float: none;
    width: 100%;
    max-width: 100%;
    margin: 0 0 14px;
  }
}

.cfHybridCard {
  display: flex;
  gap: 20px;
  align-items: flex-start;
  margin: 22px 0;
  padding: 18px;
  border: 1px solid var(--cf-line);
  border-radius: var(--cf-radius);
  background: #fff;
}
.cfHybridCardImage { flex: 0 0 150px; max-width: 150px; }
.cfHybridCardImage img { width: 100%; height: auto; border-radius: 8px; }
.cfHybridCardBody { flex: 1 1 auto; }
@media (max-width: 640px) {
  .cfHybridCard { flex-direction: column; }
  .cfHybridCardImage { flex-basis: auto; max-width: 100%; }
}

/* ── FAQ accordion ────────────────────────────────────────────────
   9 patio articles ship <details> with no <summary> at all; the PHP
   promotes the question into one before this stylesheet ever sees it. */

#cfFaq, .cfFaq { margin: 34px 0; }
#cfFaq > h2, #cfFaq > h3 { margin-bottom: 16px; }

.cfFaqItem {
  border: 1px solid var(--cf-line);
  border-radius: 8px;
  margin: 8px 0;
  background: #fff;
  overflow: hidden;
}
.cfFaqItem > summary {
  cursor: pointer;
  padding: 14px 18px;
  font-weight: 600;
  font-size: 16px;
  color: var(--cf-primary);
  background: var(--cf-surface);
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  transition: background 0.2s ease;
}
.cfFaqItem > summary:hover { background: var(--cf-accent-soft); }
.cfFaqItem > summary::-webkit-details-marker { display: none; }
.cfFaqItem > summary::marker { content: ""; }
.cfFaqItem > summary:focus-visible { outline: 2px solid var(--cf-accent); outline-offset: -2px; }
/* The question may arrive as a heading the PHP moved into the summary; it
   must not keep heading scale — or heading TYPEFACE — inside a one-line
   control. ⚠️ `font-family: inherit` is the load-bearing one: ThePatioPro
   sets Anton (a condensed display face) on h1-h6, and a question set in
   Anton at control weight is genuinely hard to read. */
.cfFaqQ,
.cfFaqItem > summary h2,
.cfFaqItem > summary h3,
.cfFaqItem > summary h4 {
  margin: 0;
  font-family: inherit;
  font-size: inherit;
  font-weight: inherit;
  line-height: 1.45;
  color: inherit;
  text-transform: none;
  letter-spacing: 0;
}

/* ThePatioPro's body face is heavy enough that 600 on a question reads as
   shouting. The other two brands are fine bold, so this is scoped. */
body.dmca-brand-patio .cfFaqItem > summary { font-weight: 500; }
.cfFaqIcon {
  flex: 0 0 auto;
  color: var(--cf-accent);
  font-size: 20px;
  line-height: 1;
  font-weight: 700;
  transition: transform 0.25s ease;
}
/* An accordion that shipped without a marker gets an EMPTY span from the
   PHP, and the glyph is drawn here. Putting the "+" in the markup instead
   adds prose that was never in the article, which trips the no-prose-moved
   check and rolls back every repair on the page. */
.cfFaqIcon:empty::after { content: "+"; }
.cfFaqItem[open] > summary { border-bottom: 1px solid var(--cf-line); }
.cfFaqItem[open] .cfFaqIcon { transform: rotate(45deg); }
/* ⚠️ The selector is "#cfFaq .cfFaqBody" — a space, then a dot.
   Writing it as "#cfFaqBody" matches nothing and leaves opened
   answers flush-left and unstyled. */
#cfFaq .cfFaqBody,
.cfFaq .cfFaqBody,
.cfFaqItem .cfFaqBody,
.cfFaqItem > p {
  padding: 16px 18px;
  margin: 0;
  color: var(--cf-ink);
  line-height: 1.7;
  animation: cfFaqReveal 0.28s ease;
}
@keyframes cfFaqReveal {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .cfFaqItem > summary,
  .cfFaqIcon { transition: none; }
  #cfFaq .cfFaqBody, .cfFaqItem .cfFaqBody { animation: none; }
}

/* ── Misc ─────────────────────────────────────────────────────────── */

.cfVideo { margin: 26px 0; }
.cfVideo iframe { width: 100%; aspect-ratio: 16 / 9; height: auto; border: 0; border-radius: var(--cf-radius); }
.cfDiagram { margin: 26px 0; text-align: center; }
.cfDiagram img { max-width: 100%; height: auto; }

.cfPillarNav { margin: 24px 0; }
.cfPillarNav a {
  display: inline-block;
  padding: 7px 15px;
  margin: 4px 6px 4px 0;
  background: var(--cf-surface);
  border: 1px solid var(--cf-line);
  border-radius: 999px;
  color: var(--cf-accent);
  text-decoration: none;
  font-weight: 600;
  font-size: 13.5px;
}
.cfPillarNav a:hover { border-color: var(--cf-accent); }
