/* ==========================================================================
   Article template v3 — publisher-grade prototype (issue #84)

   Scoped entirely under .article-v3 so nothing here touches any other page.
   Prototype: /consent-order/ only. If Theo approves it at the preview URL,
   the polish-pass children fold this into templates/article.html and the
   rest of the guides. Until then this file is loaded by one page.
   ========================================================================== */

.article-v3 {
  --page-gutter: clamp(20px, 5vw, 48px);
}

/* --------------------------------------------------------------------------
   Vertical rhythm tokens: three distinct steps down the title block.
   eyebrow to h1 tight, h1 to byline medium, byline to the answer box a
   clear section-level gap (roughly 40px at desktop widths).
   -------------------------------------------------------------------------- */
.article-v3 .eyebrow { margin-bottom: .5rem; }
.article-v3 .article-head {
  padding-block: clamp(3rem, 8vw, 5rem) clamp(1.75rem, 4vw, 2.5rem);
}
.article-v3 .article-head h1 { margin-bottom: 1rem; }

.article-v3 .prose { padding-top: .5rem; }
.article-v3 .prose h2 {
  margin-top: 2.25rem;
  padding-top: 0;
}
.article-v3 .disclaimer,
.article-v3 .sources,
.article-v3 .byline,
.article-v3 .related {
  margin-top: 1.5rem;
}

/* --------------------------------------------------------------------------
   Lead photo
   -------------------------------------------------------------------------- */
.article-v3__photo { margin: 0 0 1rem; }
.article-v3__photo picture {
  display: block;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
}
.article-v3__photo img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: 50% 50%;
}
.article-v3__caption {
  margin-top: .6rem;
  font-size: var(--text-sm);
  color: var(--sage);
}

/* --------------------------------------------------------------------------
   Grid: wide main column + sticky sidebar. Single column under 900px, where
   the sidebar drops to a static end-of-article block in DOM order.
   -------------------------------------------------------------------------- */
.article-v3__wrap {
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--page-gutter);
}
.article-v3__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(272px, 320px);
  gap: clamp(2rem, 4vw, 3.5rem);
  align-items: start;
}

/* --------------------------------------------------------------------------
   Answer box inside the left column
   -------------------------------------------------------------------------- */
.article-v3__main > .answer {
  margin: 0 0 1.5rem;
}

/* --------------------------------------------------------------------------
   Inline guidance note
   -------------------------------------------------------------------------- */
.article-v3__guidance {
  margin: 0 0 2rem;
  font-size: var(--text-sm);
  color: var(--sage);
  line-height: 1.6;
}
.article-v3__guidance strong {
  color: var(--ink-soft);
}

/* --------------------------------------------------------------------------
   Prose measure vs. breakout. Direct children of .article-v3__prose default
   to the site's 68ch reading measure; anything marked .article-v3__breakout
   (tables, callouts, the verdict comparison, the lead photo) fills the wider
   main column instead.
   -------------------------------------------------------------------------- */
.article-v3__prose > * { max-width: var(--maxw-prose); }
.article-v3__prose > .article-v3__breakout { max-width: none; }

/* --------------------------------------------------------------------------
   Section dividers
   -------------------------------------------------------------------------- */
.article-v3__divider {
  border: 0;
  border-top: 1px solid var(--border);
  margin-top: 2.75rem;
  max-width: none;
}

/* --------------------------------------------------------------------------
   White card band — the cost-table section, set apart from the cream page.
   -------------------------------------------------------------------------- */
.article-v3__band {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: clamp(1.5rem, 4vw, 2.25rem);
  box-shadow: var(--shadow);
}
.article-v3__band > * + * { margin-top: 1.25rem; }

/* --------------------------------------------------------------------------
   Pull-stat tile
   -------------------------------------------------------------------------- */
.article-v3__stat {
  display: inline-flex;
  flex-direction: column;
  gap: .15rem;
  background: var(--mint);
  border-radius: var(--radius-sm);
  padding: 1rem 1.35rem;
}
.article-v3__stat b {
  font-size: 2rem;
  font-weight: 800;
  letter-spacing: -.02em;
  color: var(--accent);
  line-height: 1;
}
.article-v3__stat span {
  font-size: var(--text-xs);
  color: var(--ink-soft);
  font-weight: 600;
}

/* --------------------------------------------------------------------------
   Two-tone bento verdict — the DIY-vs-pay comparison, the page's centrepiece.
   Bento treatment is sanctioned here only; every other callout on the site
   keeps the plain single-tone style.
   -------------------------------------------------------------------------- */
.article-v3__verdict .verdict__col--yes {
  background: var(--paper);
  border: 1px solid var(--border-firm);
  box-shadow: var(--shadow);
}
.article-v3__verdict .verdict__col--no {
  background: linear-gradient(165deg, #232C25, #111813);
  border-color: #232C25;
  color: #fff;
}
.article-v3__verdict .verdict__col--no h3 { color: #F1E7C8; }
.article-v3__verdict .verdict__col--no li { color: #E4E9E2; }
.article-v3__verdict .verdict__col--no li::before { color: #E7A9A2; }

/* --------------------------------------------------------------------------
   Sidebar — "Your next steps" CTA stack

   Spacing between children is margin-driven, not a flex `gap`, so that a
   collapsed card (see .article-v3__cta--hidden below) truly takes up zero
   space instead of still reserving a gap slot next to nothing.
   -------------------------------------------------------------------------- */
.article-v3__sidebar {
  position: sticky;
  top: 5rem;
  display: flex;
  flex-direction: column;
}
.article-v3__sidebar > * + * { margin-top: 1rem; }

/* The heading only makes sense sitting above a visible card. While every
   card is still collapsed (progressive reveal not triggered yet, or a page
   configured with no CTAs at all) hide it instead of floating above dead
   space, and let the offer panel, the next real content, sit flush with
   the top of the sidebar, matching the answer box in the main column. */
.article-v3__sidebar:not(:has(.article-v3__cta:not(.article-v3__cta--hidden))) .article-v3__sidebar-title {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.article-v3__sidebar:not(:has(.article-v3__cta:not(.article-v3__cta--hidden))) .article-v3__offer {
  margin-top: 0;
}

.article-v3__sidebar-title {
  font-size: var(--text-sm);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--sage);
  margin-bottom: .25rem;
}
.article-v3__cta {
  display: block;
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 1rem 1.1rem;
  text-decoration: none;
  box-shadow: var(--shadow);
  transition: box-shadow .15s, opacity .35s ease, transform .35s ease;
}
.article-v3__cta:hover { box-shadow: var(--shadow-hover); }
.article-v3__cta strong {
  display: block;
  color: var(--ink);
  font-size: var(--text-md);
  font-weight: 800;
  margin-bottom: .2rem;
}
.article-v3__cta span {
  display: block;
  color: var(--ink-soft);
  font-size: var(--text-sm);
}

/* --------------------------------------------------------------------------
   Progressive sidebar reveal (JS-enhanced, desktop only)
   -------------------------------------------------------------------------- */
.article-v3__cta--hidden {
  opacity: 0;
  transform: translateY(12px);
  pointer-events: none;
  max-height: 0;
  overflow: hidden;
  padding: 0 1.1rem;
  margin: 0;
  border-width: 0;
  border-color: transparent;
  box-shadow: none;
}
.article-v3__cta--revealed {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
  max-height: 200px;
  padding: 1rem 1.1rem;
  border-color: var(--border);
  box-shadow: var(--shadow);
}

/* --------------------------------------------------------------------------
   Offer panel
   -------------------------------------------------------------------------- */
.article-v3__offer {
  background: linear-gradient(165deg, #232C25, #111813);
  border: 1px solid #2a352c;
  border-radius: var(--radius);
  padding: 1.25rem 1.15rem;
  color: #E4E9E2;
  margin-top: .5rem;
}
.article-v3__offer-title {
  font-size: var(--text-sm);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: #F1E7C8;
  margin-bottom: .5rem;
}
.article-v3__offer-price b {
  font-size: 1.75rem;
  font-weight: 800;
  color: #fff;
  letter-spacing: -.02em;
}
.article-v3__offer-desc {
  margin: .4rem 0 0;
  font-size: var(--text-sm);
  line-height: 1.55;
}
.article-v3__offer-sub {
  margin: .35rem 0 0;
  font-size: var(--text-xs);
  font-style: italic;
  color: #B9C4B8;
  line-height: 1.5;
}
.article-v3__offer-why {
  margin: .75rem 0 0;
  font-size: var(--text-xs);
  color: #93A092;
  line-height: 1.5;
}
.article-v3__offer-upsell {
  margin: 1rem 0 0;
  padding-top: .85rem;
  border-top: 1px solid rgba(255,255,255,.12);
}
.article-v3__offer-upsell b {
  color: #fff;
  font-size: var(--text-sm);
}
.article-v3__offer-upsell p {
  margin: 0;
  font-size: var(--text-sm);
  line-height: 1.55;
}
.article-v3__offer-upsell p + p {
  margin-top: .35rem;
  color: #B9C4B8;
}
.article-v3__offer-form {
  margin-top: 1rem;
}
.article-v3__offer-field {
  margin-bottom: .6rem;
}
.article-v3__offer-field label {
  display: block;
  font-size: var(--text-xs);
  font-weight: 700;
  color: #B9C4B8;
  margin-bottom: .25rem;
}
.article-v3__offer-field .input {
  background: rgba(255,255,255,.1);
  border-color: rgba(255,255,255,.2);
  color: #fff;
  font-size: var(--text-sm);
}
.article-v3__offer-field .input::placeholder {
  color: rgba(255,255,255,.4);
}
.article-v3__offer-field .input:focus {
  border-color: var(--brand-on-dark);
  box-shadow: 0 0 0 3px rgba(143,191,159,.2);
}
.article-v3__offer-btn {
  width: 100%;
}
.article-v3__offer-trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
.article-v3__offer-note {
  margin: .6rem 0 0;
  font-size: var(--text-xs);
  color: #93A092;
  text-align: center;
}
.article-v3__offer-confirmed {
  margin: 0;
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--brand-on-dark);
  text-align: center;
  padding: .5rem 0;
}
.article-v3__offer-status {
  margin: 0;
  font-size: var(--text-sm);
  min-height: 0;
  transition: min-height .15s;
}
.article-v3__offer-status--error {
  color: #F2A8A1;
  font-weight: 600;
  margin-bottom: .5rem;
}
.article-v3__offer-field .input[aria-invalid="true"] {
  border-color: #F2A8A1;
  box-shadow: 0 0 0 3px rgba(242,168,161,.25);
}

/* --------------------------------------------------------------------------
   Single column under 900px — the sidebar drops to a static end-of-article
   block, in DOM order. Kept last in the cascade so it wins over the
   unconditional .article-v3__sidebar rule above at equal specificity.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
  .article-v3__grid { grid-template-columns: minmax(0, 1fr); }
  .article-v3__sidebar { position: static; }
  .article-v3__cta--hidden {
    opacity: 1;
    transform: none;
    pointer-events: auto;
    max-height: none;
    overflow: visible;
    padding: 1rem 1.1rem;
    margin-top: 1rem;
    border-width: 1px;
    border-color: var(--border);
    box-shadow: var(--shadow);
  }
}
