/* ==========================================================================
   V2 CUTOVER — WAVE 1 · CONTENT PAGES
   --------------------------------------------------------------------------
   The English content surface: the guides hub and its 23 guide pages, the blog
   index and its posts, the three /examples/* sample reports, the methodology
   page, and the tools directory.

   This sheet is loaded AFTER design-system.css and seo-pages.css and is the
   only place the cutover touches. seo-pages.css still owns the component
   vocabulary (.seo-*); nothing here renames a class, changes a JS hook, or
   moves copy. It restyles.

   SCOPE GUARD: every rule is nested under `.v2-content`, a class carried on the
   <body> of each cut-over template. The same .seo-* classes are used by pages
   this wave does not own (/samples, /ai-search-facts, and the nine localized
   template trees), and they must keep rendering exactly as they do today. The
   guard is what makes that true even if the sheet is ever loaded elsewhere.

   CONTRACT (public/design-system.css, "V2 FOUNDATION"):
     · never light text on mid-green or lime — ink on green is 7.37:1,
       cream on green is 2.26:1. Cream is legal on --ds-green-deep only.
     · emerald is a GROUND. When green has to be the ink it is --ds-green-ink.
     · NO ALPHA FOR TEXT. Dimmed foregrounds come from the --ds-dim-on-* family,
       one solid value per ground.
     · border = interactive; 12px control radii; sentence-case buttons.
     · numerals 1, 2, 3 — never leading zeroes.
     · 44px is a FLOOR. Nothing here sets a min-height that could shrink a
       target a page already made bigger; where a floor is restated it is
       restated as max().
     · focus rings clear 3:1 on the ground they sit on.
     · prefers-reduced-motion is respected.

   RTL: logical properties only. These templates have localized siblings in up
   to nine locales, one of which (/ar/*) renders dir="rtl" against this same
   component vocabulary. Several physical offsets inherited from seo-pages.css
   are corrected to logical ones below and are flagged in the cutover report.
   ========================================================================== */

.v2-content {
  /* Hairlines. Not text, so these are tuned for presence, not for a ratio;
     they replace the 1.5px ink keyline that made every panel read as a
     control. Border still means interactive — see .v2-content .seo-guide-links
     and the cards, which are all real links. */
  --v2-hair: #ddd8c6;          /* on cream */
  --v2-hair-strong: #cdc7b2;
  --v2-hair-on-white: #e3dece;
  --v2-panel: #fffdf7;
  --v2-gap: clamp(14px, 1.6vw, 20px);
}


/* ==========================================================================
   1 · HERO — the one full-bleed ink band
   --------------------------------------------------------------------------
   Before: a 168px-tall band with a 70px display headline, a translucent green
   kicker plate and three translucent mono chips. The headline crowded out the
   page below it at desktop and the chips were alpha-composited text.

   After: the band is flush (no bottom radius, so it reads as a plate rather
   than a floating card), the headline drops to a measured scale, and every
   foreground is a solid token.
   ========================================================================== */
.v2-content .seo-hero {
  padding-block: clamp(84px, 11vh, 124px) clamp(44px, 5.5vw, 66px);
  border-radius: 0;
}

/* Rule 7: the kicker was #80e9c2 on a 14%-alpha green wash. Lime type on the
   ink plate is 14.7:1 with no compositing at all, and the dash carries the
   emphasis the plate was carrying. */
.v2-content .seo-kicker {
  display: flex;
  align-items: center;
  gap: 10px;
  width: fit-content;
  margin: 0 0 14px;
  padding: 0;
  background: none;
  border: 0;
  color: var(--ds-lime);
  font-size: 11px;
  letter-spacing: 0.18em;
}
.v2-content .seo-kicker::before {
  content: "";
  flex: none;
  width: 20px;
  height: 3px;
  border-radius: 2px;
  background: var(--ds-lime);
}

.v2-content .seo-hero h1 {
  font-size: clamp(2rem, 3.9vw, 3.35rem);
  line-height: 1.02;
  letter-spacing: -0.03em;
  max-width: 24ch;
}

/* Rule 7: rgba(244, 240, 226, 0.66) composited to a value that only just held
   on the ink plate and lost outright wherever the plate lightened. */
.v2-content .seo-hero-copy {
  margin-block-start: clamp(16px, 2vw, 22px);
  font-size: clamp(15.5px, 1.05vw, 17.5px);
  color: var(--ds-dim-on-ink);
  max-width: 58ch;
}

/* The meta row was three alpha plates that read as a row of small buttons —
   border/fill is the vocabulary of a control, and none of these is one. They
   become a quiet dotted run: same words, same order, no invented emphasis. */
.v2-content .seo-meta {
  gap: 8px 20px;
  margin-block-start: 22px;
}
.v2-content .seo-meta span {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
  color: var(--ds-dim-on-ink);
  font-size: 10.5px;
  letter-spacing: 0.1em;
}
.v2-content .seo-meta span::before {
  content: "";
  flex: none;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--ds-green);
}
/* The first item is the freshness stamp and keeps the emphasis it had. */
.v2-content .seo-meta span:first-child {
  padding: 0;
  background: none;
  color: var(--ds-lime);
}
.v2-content .seo-meta span:first-child::before {
  background: var(--ds-lime);
}

.v2-content .seo-cta-row {
  margin-block-start: 26px;
  gap: 14px 22px;
}

/* Rule 8: 12px control radius, soft elevation, sentence case (already). The
   hard drop shadow is replaced by the foundation's lift token. */
.v2-content .seo-button {
  border-radius: var(--ds-radius-control);
  box-shadow: var(--ds-lift-1);
  color: var(--ds-on-green);
}
.v2-content .seo-button:hover {
  background: var(--ds-green-hover);
  box-shadow: var(--ds-lift-2);
}


/* ==========================================================================
   2 · ARTICLE — prose, panels and lists
   ========================================================================== */
.v2-content .seo-article h2 {
  font-size: clamp(1.5rem, 2.2vw, 2rem);
  line-height: 1.06;
  margin-block: clamp(38px, 4vw, 52px) 14px;
}
.v2-content .seo-article > h2:first-child {
  margin-block-start: 0;
}

/* RTL: seo-pages.css pads these lists with padding-left. */
.v2-content .seo-article ul,
.v2-content .seo-article ol {
  padding-left: 0;
  padding-inline-start: 22px;
}

/* --------------------------------------------------------------------------
   2a · Numbered process — 1, 2, 3 with NO leading zeroes
   --------------------------------------------------------------------------
   seo-pages.css renders these with counter(seo-step, decimal-leading-zero),
   i.e. 01 / 02 / 03. That is the one numeral rule the brief calls out by name,
   and the reference guide (/instagram-competitor-analysis-tool) already ships
   1-5 unpadded. This aligns the rest of the family with it.

   The chevron-clipped ink tag also becomes a round green counter: ink on green
   is 7.37:1, and a circle stops the number reading as a small button.
   -------------------------------------------------------------------------- */
.v2-content .seo-step-list {
  gap: 10px;
}
.v2-content .seo-step-list li {
  padding: 16px 18px;
  padding-inline-start: 60px;
  background: var(--v2-panel);
  border: 1px solid var(--v2-hair);
  border-radius: 14px;
  box-shadow: var(--ds-lift-1);
}
.v2-content .seo-step-list li::before {
  content: counter(seo-step);
  left: auto;
  inset-inline-start: 16px;
  top: 15px;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border-radius: 50%;
  clip-path: none;
  background: var(--ds-green);
  color: var(--ds-on-green);
  font-size: 12.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   2b · Callouts — pullout, proof, template box
   --------------------------------------------------------------------------
   All three were full-bleed ink label bars over a keylined body, plus (on
   .seo-proof) a 6px hard green offset. Three heavy panels in a row is what
   made the guide pages read as a stack of alerts. They become one restrained
   family: hairline panel, soft lift, and a small solid label.
   -------------------------------------------------------------------------- */
.v2-content .seo-pullout,
.v2-content .seo-proof {
  background: var(--v2-panel);
  border: 1px solid var(--v2-hair);
  border-radius: 16px;
  box-shadow: var(--ds-lift-1);
  padding: 18px 20px 20px;
}
.v2-content .seo-pullout strong,
.v2-content .seo-proof strong {
  padding: 0;
  margin-block-end: 10px;
  background: none;
  color: var(--ds-green-ink);
  font-size: 10.5px;
  letter-spacing: 0.15em;
}
.v2-content .seo-pullout p,
.v2-content .seo-proof p {
  padding: 0;
  color: var(--ds-ink);
}

/* The one ink plate the article keeps: it is a verbatim example read, and the
   inversion is what marks it as quoted material rather than page voice. */
.v2-content .seo-template-box {
  border-radius: 16px;
  padding: 18px 20px 20px;
  box-shadow: var(--ds-lift-1);
}

/* --------------------------------------------------------------------------
   2c · Tables
   --------------------------------------------------------------------------
   The ledger header stays — it is legible and it is how a figure column is
   read. What changes: the 1.5px ink frame drops to a hairline, and the wrap
   gets real scroll shadows. `min-width: 520px` means these tables scroll on a
   phone, and before this the only cue was a truncated word.
   -------------------------------------------------------------------------- */
.v2-content .seo-table-wrap {
  border: 1px solid var(--v2-hair);
  border-radius: 16px;
  box-shadow: var(--ds-lift-1);
  /* Two fixed edge fades pinned to the scroll port, two scrolling shadows that
     slide under them. Purely presentational; the wrap keeps its tabindex and
     aria-label from the template. */
  background:
    linear-gradient(to right, #fff 30%, rgba(255, 255, 255, 0)) left center / 34px 100% no-repeat local,
    linear-gradient(to left, #fff 30%, rgba(255, 255, 255, 0)) right center / 34px 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, rgba(14, 17, 16, 0.16), rgba(14, 17, 16, 0)) left center / 16px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, rgba(14, 17, 16, 0.16), rgba(14, 17, 16, 0)) right center / 16px 100% no-repeat scroll,
    #fff;
}
.v2-content .seo-table th {
  background: var(--ds-green-deep);
  color: var(--ds-cream);
  font-size: 10.5px;
  letter-spacing: 0.12em;
}
.v2-content .seo-table td {
  border-bottom: 1px solid var(--v2-hair-on-white);
}

/* --------------------------------------------------------------------------
   2d · FAQ
   --------------------------------------------------------------------------
   Rule 7 (the answer text was rgba(14, 17, 16, 0.7)) and RTL: the summary's
   padding and the +/x dot were pinned with `right`, so in Arabic the glyph
   landed on top of the question.
   -------------------------------------------------------------------------- */
.v2-content .seo-faq {
  border-top: 1px solid var(--v2-hair-strong);
}
.v2-content .seo-faq details {
  border-bottom: 1px solid var(--v2-hair-strong);
}
.v2-content .seo-faq summary {
  padding: 18px 0;
  padding-inline: 2px 52px;
  min-height: max(var(--ds-tap), 0px);
  font-size: clamp(1rem, 1.3vw, 1.18rem);
}
.v2-content .seo-faq summary::after {
  right: auto;
  inset-inline-end: 4px;
  width: 26px;
  height: 26px;
  margin-top: -13px;
  background: var(--ds-green);
}
.v2-content .seo-faq summary::before {
  right: auto;
  inset-inline-end: 10px;
  width: 14px;
  height: 14px;
  margin-top: -7px;
  /* Ink on green (7.37:1), never cream on green (2.26:1). */
  background:
    linear-gradient(var(--ds-ink), var(--ds-ink)) center / 12px 2px no-repeat,
    linear-gradient(var(--ds-ink), var(--ds-ink)) center / 2px 12px no-repeat;
}
.v2-content .seo-faq p {
  padding: 0 0 22px;
  padding-inline: 2px 56px;
  color: var(--ds-dim-on-light);
}

/* 2e · Definition list — border-left is a physical offset. */
.v2-content .seo-definition-list div {
  border-left: 0;
  border-inline-start: 3px solid var(--ds-green);
  padding-left: 0;
  padding-inline-start: 16px;
}
.v2-content .seo-definition-list dd {
  color: var(--ds-dim-on-light);
}

/* --------------------------------------------------------------------------
   2f · Media — the /examples/* post strip
   --------------------------------------------------------------------------
   Only the three /examples/* pages use this grid, and each holds three public
   post stills. `repeat(auto-fit, minmax(230px, 1fr))` put two on the first row
   and orphaned the third, and the stills have different native aspect ratios,
   so the row read as a mismatched collage rather than as posts.

   Locking the thumb to one portrait ratio and fitting the still inside it is
   how the real report presents a post grid — which is what these pages are
   sampling. The caption strip stays exactly as written.
   -------------------------------------------------------------------------- */
.v2-content .seo-media-grid {
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
}
.v2-content .seo-media-grid img {
  aspect-ratio: 4 / 5;
  object-fit: cover;
  display: block;
}
.v2-content .seo-media-grid figure {
  border: 1px solid var(--v2-hair);
  border-radius: 16px;
  background: var(--v2-panel);
  box-shadow: var(--ds-lift-1);
}
.v2-content .seo-media-grid figcaption {
  border-top: 1px solid var(--v2-hair);
  color: var(--ds-dim-on-light);
}


/* ==========================================================================
   3 · SIDEBAR RAIL
   --------------------------------------------------------------------------
   Before: every third card took a saturated violet / sun / coral fill with a
   1.5px ink frame and a 6px hard offset shadow, under a full-bleed ink label
   bar. Three of them stacked beside a cream article column pulled the eye off
   the guide entirely, and the rotation meant a card's colour carried no
   meaning — a rail on one page was violet and the same rail on the next was
   coral.

   After: one restrained card, a lime rule under a solid label, hairline and
   soft lift. Accent is now carried by the lime rule and the list markers only.

   THE :not() IS LORE, NOT TIDINESS. /instagram-competitor-analysis-tool has
   already had its design pass, and it re-plates these same two cards itself
   (.competitor-related-card is an ink plate carrying cream links;
   .competitor-strengths-card is a white card with lime checks). Both of those
   page rules sit at (0,2,0). An earlier draft of this block restated the
   rotation it was replacing —

       .v2-content .seo-side-card:nth-of-type(3n + 1) { background: … }

   — which is (0,3,0), so it silently outranked the page and repainted the ink
   related-card white while its links kept `color: var(--ds-cream)`. Cream on
   white is 1.14:1, and tests/v2-foundation.spec.js caught all seven links.

   The fix is not more specificity, it is less scope: this rail restyle is for
   the pages that never got one. The nth-of-type rotation still loses without
   being restated, because a plain `.v2-content .seo-side-card` ties it at
   (0,2,0) and this sheet loads later.
   ========================================================================== */
.v2-content .seo-sidebar {
  gap: 14px;
}
.v2-content:not(.instagram-competitor-tool-page) .seo-side-card {
  background: var(--v2-panel);
  border: 1px solid var(--v2-hair);
  border-radius: 16px;
  box-shadow: var(--ds-lift-1);
  padding: 16px 0 18px;
}
.v2-content:not(.instagram-competitor-tool-page) .seo-side-card h2,
.v2-content:not(.instagram-competitor-tool-page) .seo-side-card h3 {
  margin: 0 18px 12px;
  padding: 0 0 10px;
  background: none;
  color: var(--ds-ink);
  font-size: 10.5px;
  letter-spacing: 0.15em;
  border-bottom: 2px solid var(--ds-lime);
}
.v2-content:not(.instagram-competitor-tool-page) .seo-side-card > p {
  margin-inline: 18px;
  color: var(--ds-dim-on-light);
}
.v2-content:not(.instagram-competitor-tool-page) .seo-side-card > ul {
  padding-inline: 18px;
  gap: 9px;
}
.v2-content:not(.instagram-competitor-tool-page) .seo-side-card > ul li::before {
  width: 6px;
  height: 6px;
  margin-top: 6px;
  border-radius: 50%;
  transform: none;
  background: var(--ds-green);
}

/* Rail links: still real links, so they still take a keyline — but a hairline
   pill with a directional arrow, matching the tap rows on the reference guide.
   The 44px floor from seo-pages.css is left to do its own work; the max() here
   only guarantees the floor is never lowered by this rule. */
.v2-content:not(.instagram-competitor-tool-page) .seo-guide-links {
  margin-inline: 18px;
  gap: 7px;
}
.v2-content:not(.instagram-competitor-tool-page) .seo-guide-links a {
  min-height: max(var(--ds-tap), 0px);
  padding: 10px 12px;
  background: #fff;
  border: 1px solid var(--v2-hair-on-white);
  border-radius: var(--ds-radius-control);
  font-family: var(--ds-font-ui);
  font-size: 13px;
  font-weight: 550;
  letter-spacing: -0.005em;
  line-height: 1.3;
  box-shadow: var(--ds-lift-1);
}
.v2-content:not(.instagram-competitor-tool-page) .seo-guide-links a::after {
  content: "\2192";
  flex: none;
  color: var(--ds-green-ink);
  font-size: 15px;
  line-height: 1;
}
.v2-content:not(.instagram-competitor-tool-page) .seo-guide-links a:hover {
  transform: none;
  border-color: var(--ds-green);
  box-shadow: var(--ds-lift-2);
}
/* RTL: the arrow is directional, so it mirrors with the text. */
[dir="rtl"] .v2-content:not(.instagram-competitor-tool-page) .seo-guide-links a::after {
  content: "\2190";
}


/* ==========================================================================
   4 · INDEX CARDS — the guides grid, the examples grid, the blog archive
   --------------------------------------------------------------------------
   Before: a full-bleed ink bar across the top of every card carrying the
   category, then a 1.5px ink frame and a 5px hard green offset on hover. Nine
   of them on the guides hub is nine black bars.

   After: the category becomes a quiet chip inside the card, the frame is a
   hairline, and hover lifts. A directional arrow marks the card as a link.
   ========================================================================== */
.v2-content .seo-card-grid {
  gap: var(--v2-gap);
  margin-block: 22px 8px;
}

.v2-content .seo-link-card {
  position: relative;
  padding: 16px 16px 46px;
  background: var(--v2-panel);
  border: 1px solid var(--v2-hair);
  border-radius: 16px;
  box-shadow: var(--ds-lift-1);
  transition: box-shadow 160ms var(--ds-ease), transform 160ms var(--ds-ease), border-color 160ms var(--ds-ease);
}
.v2-content .seo-link-card:hover {
  transform: translateY(-2px);
  border-color: var(--ds-green);
  box-shadow: var(--ds-lift-2);
}
.v2-content .seo-link-card span {
  align-self: flex-start;
  padding: 5px 9px;
  background: var(--ds-cream-2);
  color: var(--ds-dim-on-light);
  border-radius: 7px;
  font-size: 9.5px;
  letter-spacing: 0.13em;
}
.v2-content .seo-link-card strong {
  margin: 12px 0 7px;
  font-size: 16.5px;
  line-height: 1.24;
}
.v2-content .seo-link-card p {
  margin: 0;
  /* Rule 7: was rgba(14, 17, 16, 0.66). */
  color: var(--ds-dim-on-light);
}
/* The affordance, drawn rather than written: no copy is added to the card. */
.v2-content .seo-link-card::after {
  content: "→";
  position: absolute;
  inset-block-end: 14px;
  inset-inline-start: 16px;
  color: var(--ds-green-ink);
  font-size: 17px;
  line-height: 1;
  transition: transform 160ms var(--ds-ease);
}
[dir="rtl"] .v2-content .seo-link-card::after {
  content: "←";
}
.v2-content .seo-link-card:hover::after {
  transform: translateX(3px);
}
[dir="rtl"] .v2-content .seo-link-card:hover::after {
  transform: translateX(-3px);
}


/* ==========================================================================
   5 · BLOG ARCHIVE — the lead post
   --------------------------------------------------------------------------
   Seven cards of identical weight give a reader no entry point, and the
   archive is ordered newest-first, so the first card IS the lead. It takes the
   full row and the ink plate.

   There is deliberately NO topic rail. The seven posts in blogPosts.json carry
   seven distinct freeform kickers, so a rail built from them would be seven
   chips filtering one post each. The agreed rule is one chip per kicker with
   two or more posts, and no rail until two kickers qualify; today none does.
   Nothing here is per-post JavaScript, and adding a post stays a data-only
   change to the manifest plus its template.
   ========================================================================== */
.v2-content.v2-blog-index .seo-card-grid {
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.v2-content.v2-blog-index .seo-link-card:first-child {
  grid-column: 1 / -1;
  padding: 20px 22px 50px;
  background: var(--ds-ink);
  border-color: var(--ds-ink);
  color: var(--ds-cream);
}
.v2-content.v2-blog-index .seo-link-card:first-child span {
  background: var(--ds-lime);
  /* Rule 1: ink on lime, never a light foreground. */
  color: var(--ds-dim-on-lime);
}
.v2-content.v2-blog-index .seo-link-card:first-child strong {
  font-family: var(--ds-font-display);
  font-weight: 800;
  font-size: clamp(19px, 2.3vw, 27px);
  line-height: 1.12;
  letter-spacing: -0.02em;
  max-width: 26ch;
}
.v2-content.v2-blog-index .seo-link-card:first-child p {
  color: var(--ds-dim-on-ink);
  max-width: 68ch;
}
.v2-content.v2-blog-index .seo-link-card:first-child::after {
  color: var(--ds-lime);
}
.v2-content.v2-blog-index .seo-link-card:first-child:hover {
  border-color: var(--ds-lime);
}
/* Foundation rule 6, worked through rather than assumed. This is a new dark
   plate, so the first instinct is the lime override .seo-nav / .seo-hero /
   .seo-footer / .seo-cta carry. That would be WRONG here, and measurably so:
   those four are full-bleed plates, and a ring drawn on them sits ON the ink.
   This card is an island on the cream page, and :focus-visible is drawn at
   --ds-focus-offset OUTSIDE the card — so the ring lands on cream, where lime
   measures 1.13:1 and the default deep green measures 9.6:1.

   So the card deliberately takes NO override and inherits the default ring.
   Recording it here because "new dark plate => lime ring" is the rule of thumb
   this one breaks, and the next person to touch this card will reach for it. */


/* ==========================================================================
   6 · GUIDES HUB — the resource table on a phone
   --------------------------------------------------------------------------
   `.seo-table { min-width: 520px }` means the ten-row resource table scrolls
   sideways inside its wrap on a 390px screen, and the "Best for" column is cut
   mid-word. The wrap keeps its scroll shadows everywhere else; here the table
   restacks as one card per row, because this table is a link list wearing a
   table's clothes and the reader has no reason to scroll it.

   The stack is opt-in (`.v2-stack-table`) and each cell carries its own
   data-label, so the header text is never dropped — the reason this is not
   applied to every table in the family is that several of them (the tools
   directory in particular) answer "No" in a cell, and a "No" with its column
   heading removed would be a different claim.
   ========================================================================== */
@media (max-width: 720px) {
  .v2-content .seo-table-wrap:has(.v2-stack-table),
  .v2-content.sample-report-page .seo-table-wrap:has(.v2-stack-table) {
    border: 0;
    background: none;
    box-shadow: none;
    overflow: visible;
  }
  .v2-content .v2-stack-table,
  .v2-content.sample-report-page .v2-stack-table {
    min-width: 0;
    display: block;
  }
  .v2-content .v2-stack-table thead,
  .v2-content.sample-report-page .v2-stack-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }
  .v2-content .v2-stack-table tbody,
  .v2-content.sample-report-page .v2-stack-table tbody {
    display: grid;
    gap: 10px;
  }
  .v2-content .v2-stack-table tr,
  .v2-content.sample-report-page .v2-stack-table tr {
    display: block;
    padding: 14px 16px;
    background: var(--v2-panel);
    border: 1px solid var(--v2-hair);
    border-radius: 16px;
    box-shadow: var(--ds-lift-1);
  }
  .v2-content .v2-stack-table td,
  .v2-content.sample-report-page .v2-stack-table td {
    display: block;
    padding: 0;
    border-bottom: 0;
  }
  .v2-content .v2-stack-table td + td,
  .v2-content.sample-report-page .v2-stack-table td + td {
    margin-block-start: 8px;
  }
  .v2-content .v2-stack-table td::before,
  .v2-content.sample-report-page .v2-stack-table td::before {
    content: attr(data-label);
    display: block;
    margin-block-end: 3px;
    color: var(--ds-dim-on-light);
    font-family: var(--ds-font-mono);
    font-size: 9.5px;
    letter-spacing: 0.13em;
    text-transform: uppercase;
  }
  .v2-content .v2-stack-table td:first-child,
  .v2-content.sample-report-page .v2-stack-table td:first-child {
    font-family: var(--ds-font-ui);
    font-weight: 700;
    font-size: 16px;
    letter-spacing: -0.01em;
  }
  .v2-content .v2-stack-table td:first-child::before,
  .v2-content.sample-report-page .v2-stack-table td:first-child::before {
    content: none;
  }
}


/* ==========================================================================
   7 · NARROW SCREENS
   ========================================================================== */
@media (max-width: 680px) {
  .v2-content .seo-hero {
    padding-block: clamp(72px, 9vh, 96px) 34px;
  }
  .v2-content .seo-hero h1 {
    font-size: clamp(1.85rem, 7.6vw, 2.3rem);
    max-width: none;
  }
  .v2-content .seo-meta {
    gap: 6px 16px;
  }
  .v2-content .seo-card-grid {
    grid-template-columns: minmax(0, 1fr);
  }
  .v2-content.v2-blog-index .seo-card-grid {
    grid-template-columns: minmax(0, 1fr);
  }
  .v2-content .seo-side-card,
  .v2-content .seo-link-card,
  .v2-content .seo-step-list li,
  .v2-content .seo-pullout,
  .v2-content .seo-proof,
  .v2-content .seo-table-wrap {
    border-radius: 14px;
  }
}


/* ==========================================================================
   8 · REDUCED MOTION
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .v2-content .seo-link-card,
  .v2-content .seo-link-card::after,
  .v2-content .seo-guide-links a,
  .v2-content .seo-button {
    transition-duration: 0.01ms !important;
    transform: none !important;
  }
  .v2-content .seo-link-card:hover,
  .v2-content .seo-link-card:hover::after,
  .v2-content .seo-guide-links a:hover {
    transform: none !important;
  }
}


/* ==========================================================================
   9 · LONG UNBREAKABLE RUNS
   --------------------------------------------------------------------------
   Pre-existing, and surfaced by the 320px check in tests/v2-content.spec.js:
   an inline <code> run (an MCP command, a JSON field name) is one unbreakable
   token, so at 320px it pushed /instagram-analysis-in-claude-chatgpt 106px and
   /blog/mcp-social-media-competitor-research 22px past the viewport. Nothing in
   seo-pages.css lets a code run wrap, and the guide family is where every code
   run lives.
   ========================================================================== */
.v2-content .seo-article code,
.v2-content .seo-article kbd,
.v2-content .seo-article samp,
.v2-content .seo-template-box {
  overflow-wrap: anywhere;
}
.v2-content .seo-article p,
.v2-content .seo-article li,
.v2-content .seo-table td {
  overflow-wrap: break-word;
}


/* ==========================================================================
   10 · THE COMPETITOR TOOL PAGE — the analyze control and the sample picker
   --------------------------------------------------------------------------
   TRACK E, defects E1 and E2. Both components live in
   templates/guides/instagram-competitor-analysis-tool.html, which this track
   may not edit, so every fix below is CSS-only and is scoped tightly enough to
   win against `.seo-article a:not(.seo-button):not(.seo-text-link)
   :not(.seo-link-card):not(.sample-report-card)` in seo-pages.css — that rule
   is (0,5,1) and is what was painting the underlines.
   ========================================================================== */

/* --------------------------------------------------------------------------
   10a · E1 · "Explore a finished report" cards
   --------------------------------------------------------------------------
   Before: each card is an <a>, so `text-decoration: underline` from the
   article link rule propagated into EVERY in-flow descendant — a 2px
   #0c4531 rule under the brand name AND a second one under the → glyph, which
   is aria-hidden decoration. Two stray rules, no designed control.

   After: the CARD is the control, so the card carries the interactive signals
   (keyline, hover lift, focus ring) and the inline decoration is off. Text
   decoration cannot be cancelled on a descendant, so it is removed at the <a>.

   Jobs pass on the rest of the card:
     · the arrow is cut. Six identical → glyphs repeated down a grid of six
       links is decoration that says nothing the card does not already say,
       and it was half the defect. It is aria-hidden, so nothing is lost.
     · the brand name goes ink (14.51:1 on the sand) instead of green-deep
       (8.40:1). Green was doing "this is a link" work the card now does.
     · the handle grows 9px -> 11px mono. 9px was not a size, it was a smudge.
     · the header's right-aligned subline drops under the title instead of
       floating at the far edge of a 606px column.
   -------------------------------------------------------------------------- */
.v2-content.instagram-competitor-tool-page .competitor-sample-picker > header {
  display: block;
}
.v2-content.instagram-competitor-tool-page .competitor-sample-picker > header strong {
  display: block;
  font-size: 16px;
}
.v2-content.instagram-competitor-tool-page .competitor-sample-picker > header span {
  display: block;
  margin-block-start: 4px;
  color: var(--ds-dim-on-light);   /* #4e564f — 7.59:1 on white */
  font-size: 13px;
}

.v2-content.instagram-competitor-tool-page .competitor-sample-links {
  /* 3 across at desktop, 2 in the mid range, 1 at 320. auto-fit does this
     without a single media query, and never leaves a 130px card. */
  grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  gap: 10px;
}

.v2-content.instagram-competitor-tool-page .seo-article .competitor-sample-picker .seo-guide-links.competitor-sample-links a {
  /* (0,6,1) — beats the (0,5,1) article-link rule that owns the underline. */
  text-decoration: none;
  grid-template-columns: 40px minmax(0, 1fr);
  gap: 11px;
  min-block-size: 64px;
  padding-block: 11px;
  padding-inline: 12px;
  color: var(--ds-ink);
  background: var(--ds-cream-2);
  border: 1px solid var(--v2-hair-strong);
  border-radius: var(--ds-radius-control);
  box-shadow: none;
  transition: transform 140ms var(--ds-ease), box-shadow 140ms var(--ds-ease),
    background-color 140ms var(--ds-ease);
}
.v2-content.instagram-competitor-tool-page .seo-article .competitor-sample-picker .seo-guide-links.competitor-sample-links a:hover {
  /* Hover LIFTS. The ground goes lighter (sand -> cream), never darker. */
  transform: translateY(-2px);
  background: var(--ds-cream);
  box-shadow: var(--ds-lift-1);
}
.v2-content.instagram-competitor-tool-page .seo-article .competitor-sample-picker .seo-guide-links.competitor-sample-links a:focus-visible {
  outline: var(--ds-focus-width) solid var(--ds-focus);  /* #0c4531 — 8.40:1 on the sand */
  outline-offset: 2px;
}

/* The arrow was the second underline. It is decoration; it goes. */
.v2-content.instagram-competitor-tool-page .competitor-sample-links a > i {
  display: none;
}

.v2-content.instagram-competitor-tool-page .competitor-sample-links .competitor-sample-logo {
  width: 40px;
  height: 40px;
  border-radius: 11px;
}
.v2-content.instagram-competitor-tool-page .competitor-sample-links b {
  color: var(--ds-ink);            /* 14.51:1 on #e7e1cd */
  font-size: 14px;
  font-weight: 650;
  letter-spacing: -0.01em;
}
.v2-content.instagram-competitor-tool-page .competitor-sample-links small {
  margin-block-start: 3px;
  color: var(--ds-dim-on-light);   /* #4e564f — 5.80:1 on #e7e1cd */
  font-family: var(--ds-font-mono);
  font-size: 11px;
  font-weight: 450;
  letter-spacing: 0;
}

/* --------------------------------------------------------------------------
   10b · E2 · the handle field and the submit
   --------------------------------------------------------------------------
   Before: a 54px white box with a solid ink "@" slab welded to its start edge,
   a 9px gap, then a detached green pill. Three grounds, two radii, two
   silhouettes — adjacent, not composed. Worse, the only focus signal was
   `.follower-field:focus-within { border-color: var(--ds-green) }`, and emerald
   on white measures 2.57:1: an illegal ring under a design law that requires
   3:1, on the one control the page exists for.

   After: ONE control. Field and submit share a single silhouette — the field
   loses its end radius and end border, the submit loses its start radius, and
   the gap goes to zero — so the pair reads as a single object with an action
   welded to its end. Logical properties throughout, so /ar mirrors it.
     · the "@" stops being an ink slab and becomes a quiet mono prefix inside
       the field, which is what a prefix affordance is.
     · the keyline resolves to a real hex at 4.22:1 instead of a composited
       rgba(14,17,16,.28) that painted #bcbcbc (1.90:1).
     · focus is a 3px --ds-focus ring on the whole composed control at
       10.99:1, drawn from the field's :focus-within so the ring surrounds the
       object the user is typing into.
     · below 560px the pair stacks and both halves go full width with their
       radii restored, because a 130px submit next to a 150px field at 320px
       is neither.
   The one thing CSS cannot fix here is that the field's only label is a
   placeholder plus an aria-label. That needs markup; the diff is in the
   Track E report.
   -------------------------------------------------------------------------- */
.v2-content.instagram-competitor-tool-page .competitor-checker-intro h2 {
  /* The headline was clamping to 52px and owned the eye. The input is what
     the page is for, so the headline steps back to a measured scale. */
  max-width: 18ch;
  font-size: clamp(1.75rem, 3.4vw, 2.5rem);
  line-height: 1.02;
}

/* Three 9px uppercase pill plates ahead of the input were noise at a size
   nobody can read. They become one quiet mono line. */
.v2-content.instagram-competitor-tool-page .seo-article .competitor-checker-intro > ul {
  /* seo-pages.css indents every article <ul> by 22px; this one is a chip row,
     not prose, and was hanging 22px off the headline's start edge. */
  padding-inline-start: 0;
  gap: 0 10px;
  margin-block-start: 12px;
}
.v2-content.instagram-competitor-tool-page .competitor-checker-intro > ul li {
  padding: 0;
  background: none;
  border-radius: 0;
  color: var(--ds-dim-on-light);   /* 7.59:1 on white */
  font-family: var(--ds-font-mono);
  font-size: 11.5px;
  font-weight: 450;
  letter-spacing: 0;
  text-transform: none;
}
/* The separator hangs off the END of each item, never the start of the next,
   so a wrapped line can never open with a stray middot. */
.v2-content.instagram-competitor-tool-page .competitor-checker-intro > ul li:not(:last-child)::after {
  content: "·";
  margin-inline-start: 10px;
  color: var(--ds-dim-on-light);
}

/* The visible label. A placeholder is not a label, and `aria-label` is a name
   for assistive tech only — sighted users got nothing but grey "nike" sitting
   in the field, which reads as a value that is already there.
   It is deliberately a sibling of <form>, not a child: .follower-form is a
   flex row, and a label inside it would have become a third flex item and
   broken the fused field+submit silhouette. As a block above the pair it
   labels the whole control, which stays true below 560px where the field and
   the submit stack.
   #4e564f on the white panel — 7.59:1, and it is 11.5px, so it is held to the
   small-text 4.5:1 bar, not the 3:1 large-text allowance. */
.v2-content.instagram-competitor-tool-page .competitor-checker .follower-form-label {
  display: block;
  margin-block: 24px 8px;
  color: var(--ds-dim-on-light);
  font-family: var(--ds-font-mono);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.02em;
  cursor: pointer;
}

.v2-content.instagram-competitor-tool-page .competitor-checker .follower-form {
  gap: 0;
  margin-block-start: 24px;
  align-items: stretch;
  /* The pair is fused, so it must not be allowed to wrap on its own.
     Belt to the braces below: above 680px this stays a single flex line, so a
     future container change cannot wrap the pair into the half-flat corners
     the stacked block is there to undo. */
  flex-wrap: nowrap;
}
/* The label now carries the run-in space, so the form drops its own. */
.v2-content.instagram-competitor-tool-page .competitor-checker .follower-form-label + .follower-form {
  margin-block-start: 0;
}

.v2-content.instagram-competitor-tool-page .competitor-checker .follower-field {
  flex: 1 1 260px;
  min-block-size: 56px;
  background: #fff;
  border: 1.5px solid #767d79;     /* 4.22:1 on white — a real boundary */
  /* Physical reset FIRST, logical after, or the logical one is overwritten. */
  border-radius: var(--ds-radius-control);
  border-start-end-radius: 0;
  border-end-end-radius: 0;
  border-inline-end: 0;
}
.v2-content.instagram-competitor-tool-page .competitor-checker .follower-field:focus-within {
  border-color: var(--ds-focus);
  outline: var(--ds-focus-width) solid var(--ds-focus);  /* 10.99:1 on white */
  outline-offset: 2px;
  /* Lift the focused half above the submit so the ring is never clipped. */
  position: relative;
  z-index: 1;
}
.v2-content.instagram-competitor-tool-page .competitor-checker .follower-field span {
  padding-inline: 14px 0;
  background: none;
  /* Ink, not dim: the "@" is a standing part of the value, and at dim it read
     as the first character of the placeholder. 18.98:1 on white. */
  color: var(--ds-ink);
  font-family: var(--ds-font-mono);
  font-size: 17px;
  font-weight: 450;
}
.v2-content.instagram-competitor-tool-page .competitor-checker .follower-field input {
  padding-inline: 6px 14px;
  font-size: 17px;
  font-weight: 550;
}
.v2-content.instagram-competitor-tool-page .competitor-checker .follower-field input::placeholder {
  color: var(--ds-dim-on-light);   /* 7.59:1 — never an alpha, never a smudge */
  font-weight: 400;
  opacity: 1;
}

.v2-content.instagram-competitor-tool-page .competitor-checker .follower-form button {
  flex: 0 0 auto;
  min-block-size: 56px;
  padding-inline: 26px;
  color: var(--ds-on-green);       /* ink on emerald — 7.37:1 */
  background: var(--ds-green);
  border: 1.5px solid var(--ds-green);
  border-radius: var(--ds-radius-control);
  border-start-start-radius: 0;
  border-end-start-radius: 0;
  font-size: 15px;
  font-weight: 700;
}
.v2-content.instagram-competitor-tool-page .competitor-checker .follower-form button:hover:not(:disabled) {
  /* Hover lifts to #1cc582 (8.46:1 under ink). It does not darken and it does
     not move, because the button is welded to the field now. */
  transform: none;
  background: var(--ds-green-hover);
  border-color: var(--ds-green-hover);
  box-shadow: none;
}
.v2-content.instagram-competitor-tool-page .competitor-checker .follower-form button:disabled {
  opacity: 1;
  color: var(--ds-disabled-ink);
  background: var(--ds-disabled-bg);
  border-color: var(--ds-disabled-line);
}
.v2-content.instagram-competitor-tool-page .competitor-checker .follower-form button:focus-visible:not(:disabled) {
  outline: var(--ds-focus-width) solid var(--ds-focus);
  outline-offset: 2px;
  position: relative;
  z-index: 1;
}

/* Error / empty state.
   Two measured bugs here, both pre-existing:
   1. `.follower-status-bad { color: #9c4530 }` is (0,1,0) and loses to
      `.seo-article p` (0,1,1), so every error on this page rendered in plain
      ink. The one state that has to look different looked identical.
   2. The state lived only in a line of text 14px below the control, and the
      control itself never changed. The status <p> is a later sibling of the
      form, so the field is reached through :has() on the section. */
.v2-content.instagram-competitor-tool-page .seo-article .follower-status.follower-status-bad {
  color: #9c4530;                  /* 6.35:1 on white */
}
.v2-content.instagram-competitor-tool-page .seo-article .follower-status.follower-status-warn {
  color: #a45b12;                  /* 5.14:1 on white */
}
.v2-content.instagram-competitor-tool-page .seo-article .follower-status.follower-status-good {
  color: var(--ds-green-deep);     /* 10.99:1 on white */
}
.v2-content.instagram-competitor-tool-page .seo-article .follower-status {
  margin-block-start: 10px;
  font-size: 13.5px;
  font-weight: 500;
}
.v2-content.instagram-competitor-tool-page .competitor-checker:has(.follower-status-bad:not([hidden])) .follower-field,
.v2-content.instagram-competitor-tool-page .competitor-checker .follower-field:has(input[aria-invalid="true"]) {
  border-color: #9c4530;           /* 6.35:1 on white */
}

/* 680px, NOT 559px, and the number is not a taste call: seo-pages.css:1620
   (`@media (max-width: 680px)`) turns `.follower-form` into a single-column
   GRID, so the pair stacks from 680 down no matter what flex says. An earlier
   pass of this work put the restore at 559 and left a 121px band (560-680)
   where the two halves rendered stacked but still carried the fused geometry:
   no gap between them, the field missing its end border, and both of them
   flat-cornered on the side that used to face the other one. Measured across
   14 widths; this query is pinned to the breakpoint that actually stacks. */
@media (max-width: 680px) {
  /* seo-pages.css:1629 also turns the limit row into a 2-column grid inside
     this same query. That was right for three pill plates; it is wrong for the
     single middot-separated line they became, which landed each item in its
     own column with the separators floating in the gutter. Back to a wrapping
     line. */
  .v2-content.instagram-competitor-tool-page .seo-article .competitor-checker-intro > ul {
    display: flex;
    flex-wrap: wrap;
    grid-template-columns: none;
  }
  .v2-content.instagram-competitor-tool-page .seo-article .competitor-checker-intro > ul li:last-child {
    grid-column: auto;
  }

  /* Two full-width halves stacked. Each keeps its own full radius, because
     stacked they are two objects again and pretending otherwise is worse. */
  .v2-content.instagram-competitor-tool-page .competitor-checker .follower-form {
    flex-wrap: wrap;
    gap: 10px;
  }
  .v2-content.instagram-competitor-tool-page .competitor-checker .follower-field {
    flex: 1 1 100%;
    border-radius: var(--ds-radius-control);
    border-inline-end: 1.5px solid #767d79;
  }
  .v2-content.instagram-competitor-tool-page .competitor-checker .follower-form button {
    flex: 1 1 100%;
    inline-size: 100%;
    border-radius: var(--ds-radius-control);
  }
}


/* ==========================================================================
   11 · SAMPLE REPORTS — the long row problem
   --------------------------------------------------------------------------
   TRACK E, defect E3.

   Measured before: /samples/nike renders a seven-column ledger (#, Date,
   Format, Likes, Comments, Caption, Source) whose natural width is 634px
   inside a 606px article column at 1280px. So it scrolled sideways ON THE
   DESKTOP, not only on a phone — 320px and 390px had a 634px table in a 278px
   and 348px port. The /examples/* three-column tables were 520px (the
   inherited `min-width`) in the same 278px port.

   Strategy — (b) then a fitted table, NOT (c):
     · <= 720px the table restacks as one card per post using the existing
       `.v2-stack-table` vocabulary from section 6, with every cell carrying
       its column heading as a data-label so no figure is left unlabelled.
       Each post card is read top to bottom the way a phone reads.
     · > 720px it stays a real table, but `table-layout: fixed` with declared
       column widths gives the five short columns exactly what they need and
       hands every remaining pixel to the caption, which then wraps instead of
       forcing the table wide. Padding drops 16px -> 10px inline.
     · the `.seo-table-wrap` keeps `overflow-x: auto` and its `tabindex="0"`
       as a fallback, but after this it has nothing to scroll at any width, so
       the discoverability question that comes with option (c) never arises.
       That is why no edge fade is added: an always-on gradient over the cells
       would also put every text run in the table on a gradient ground, which
       is exactly what the contrast harness cannot measure.
     · long runs break at sensible points: `overflow-wrap: break-word` on the
       cells generally, `anywhere` only on the caption and the source link,
       where an @mention or a permalink can genuinely exceed a column.

   The stack rules themselves live in section 6 and are shared. This section
   adds the sample-page scope tokens, the fitted desktop table, and the
   post-card layout.
   ========================================================================== */

.v2-content.sample-report-page {
  /* The six /samples/<brand> report pages join the wave: they are the same
     .seo-* content template as /examples/*, and leaving them on the pre-v2
     sheet while their /examples/ siblings were cut over was the visible
     inconsistency underneath E3. They carry BOTH `v2-content` (so every rule
     in this sheet stays scoped, as the sheet's contract and
     tests/v2-content.spec.js require) and `sample-report-page` (the hook the
     post ledger below needs).
     NOTE: /samples — the index — is deliberately NOT included. It has its own
     shipped responsive-table treatment in seo-pages.css and it is one of the
     three routes the scope-guard test pins. */
}

/* Long runs never shred mid-word in prose, but a permalink or a long @mention
   has no break opportunity at all. */
.v2-content.sample-report-page .seo-table td,
.v2-content .seo-table td {
  overflow-wrap: break-word;
}
/* Only the caption can hold a token with no break opportunity (a long
   @mention or hashtag). Nothing else gets `anywhere`, because `anywhere` on a
   figure column breaks 1,913,465 across two lines and on the source column it
   shredded "Instagram" into "Instagra / m". */
.v2-content.sample-report-page .v2-post-table td[data-label="Caption"] {
  overflow-wrap: anywhere;
}

/* --------------------------------------------------------------------------
   11a · > 720px — a table that actually fits its column
   -------------------------------------------------------------------------- */
@media (min-width: 721px) {
  .v2-content.sample-report-page .v2-post-table {
    min-width: 0;
    inline-size: 100%;
    table-layout: fixed;
    font-size: 13px;
  }
  .v2-content.sample-report-page .v2-post-table th {
    padding-block: 10px;
    padding-inline: 8px;
    font-size: 9.5px;
    letter-spacing: 0.05em;
  }
  .v2-content.sample-report-page .v2-post-table td {
    padding-block: 11px;
    padding-inline: 8px;
  }
  /* Six declared columns; the caption takes every pixel that is left. Each
     width is set so its own content never has to break: 1,913,465 stays on
     one line, "Carousel" stays one word, "Open post" stays one line. The date
     is the one column allowed to wrap, and it wraps at its space. */
  .v2-content.sample-report-page .v2-post-table th:nth-child(1),
  .v2-content.sample-report-page .v2-post-table td:nth-child(1) { inline-size: 30px; }
  .v2-content.sample-report-page .v2-post-table th:nth-child(2),
  .v2-content.sample-report-page .v2-post-table td:nth-child(2) { inline-size: 88px; }
  .v2-content.sample-report-page .v2-post-table th:nth-child(3),
  .v2-content.sample-report-page .v2-post-table td:nth-child(3) { inline-size: 72px; }
  .v2-content.sample-report-page .v2-post-table th:nth-child(4),
  .v2-content.sample-report-page .v2-post-table td:nth-child(4) { inline-size: 82px; }
  .v2-content.sample-report-page .v2-post-table th:nth-child(5),
  .v2-content.sample-report-page .v2-post-table td:nth-child(5) { inline-size: 70px; }
  .v2-content.sample-report-page .v2-post-table th:nth-child(7),
  .v2-content.sample-report-page .v2-post-table td:nth-child(7) { inline-size: 80px; }
  .v2-content.sample-report-page .v2-post-table td:nth-child(2),
  .v2-content.sample-report-page .v2-post-table td:nth-child(3),
  .v2-content.sample-report-page .v2-post-table td:nth-child(4),
  .v2-content.sample-report-page .v2-post-table td:nth-child(5),
  .v2-content.sample-report-page .v2-post-table td:nth-child(7) {
    white-space: nowrap;
  }
  /* seo-pages.css gives every in-table link the 44px tap floor as an
     inline-flex box and centres the label in it, which parked "Open post"
     14px below the caption's first line. The floor stays; only the label
     moves back up to the row's first baseline. */
  .v2-content.sample-report-page .v2-post-table td:nth-child(7) a {
    align-items: flex-start;
  }
  .v2-content.sample-report-page .v2-post-table td:nth-child(6) {
    color: var(--ds-dim-on-light);   /* 7.59:1 on the white table ground */
    line-height: 1.45;
  }
}

/* --------------------------------------------------------------------------
   11b · <= 720px — one card per post
   --------------------------------------------------------------------------
   The generic stack in section 6 puts every cell on its own line. For a post
   that is nine stacked lines for what is really a header (rank + date +
   format), a pair of figures, a caption and a link. So the row becomes a
   two-column grid and the cells are placed.
   -------------------------------------------------------------------------- */
@media (max-width: 720px) {
  .v2-content.sample-report-page .v2-post-table tr {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px 12px;
    padding: 14px;
  }
  .v2-content.sample-report-page .v2-post-table td + td {
    margin-block-start: 0;
  }
  /* Rank — a lime counter with ink on it (14.70:1). Lime is for exactly this:
     a small counter chip, never a text colour. */
  .v2-content.sample-report-page .v2-post-table td:first-child {
    grid-column: 1 / -1;
    inline-size: 30px;
    min-block-size: 30px;
    display: grid;
    place-items: center;
    color: var(--ds-ink);
    background: var(--ds-lime);
    border-radius: 9px;
    font-family: var(--ds-font-mono);
    font-size: 13px;
    font-weight: 600;
  }
  .v2-content.sample-report-page .v2-post-table td:nth-child(6),
  .v2-content.sample-report-page .v2-post-table td:nth-child(7) {
    grid-column: 1 / -1;
  }
  .v2-content.sample-report-page .v2-post-table td:nth-child(4),
  .v2-content.sample-report-page .v2-post-table td:nth-child(5) {
    font-family: var(--ds-font-ui);
    font-size: 17px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.02em;
  }
  .v2-content.sample-report-page .v2-post-table td:nth-child(6) {
    padding-block-start: 10px;
    border-block-start: 1px solid var(--v2-hair-on-white);
    color: var(--ds-dim-on-light);
    font-size: 14px;
    line-height: 1.45;
  }
  /* "SOURCE" over a button that says "Open post" is the same word twice. */
  .v2-content.sample-report-page .v2-post-table td:nth-child(7)::before {
    content: none;
  }
  /* The permalink is the point of the row, so on a phone it becomes a real
     target rather than a 14px run of text at the bottom of a card. It is a
     keyline control, not a filled one: eight filled emerald bars down a
     phone screen is eight primary actions, which is none.
     The selector is deliberately (0,6,2) — it has to beat
     `.seo-article a:not()...:not()` (0,5,1), which owns the underline. */
  .v2-content.sample-report-page .seo-article .seo-table-wrap .seo-table.v2-post-table td:nth-child(7) a {
    min-block-size: var(--ds-tap);
    display: flex;
    align-items: center;
    justify-content: center;
    padding-inline: 14px;
    color: var(--ds-ink);            /* 18.66:1 on the panel */
    background: #fff;
    border: 1.5px solid var(--ds-ink);
    border-radius: var(--ds-radius-control);
    font-size: 14px;
    font-weight: 650;
    text-decoration: none;
  }
  .v2-content.sample-report-page .seo-article .seo-table-wrap .seo-table.v2-post-table td:nth-child(7) a:hover {
    background: var(--ds-cream);     /* lifts, never darkens */
  }
  .v2-content.sample-report-page .seo-article .seo-table-wrap .seo-table.v2-post-table td:nth-child(7) a:focus-visible {
    outline: var(--ds-focus-width) solid var(--ds-focus);
    outline-offset: 2px;
  }
}

/* --------------------------------------------------------------------------
   11c · sample-page chrome the shared sheet would otherwise miss
   -------------------------------------------------------------------------- */
.v2-content.sample-report-page .seo-table-wrap {
  border: 1px solid var(--v2-hair);
  border-radius: 16px;
  box-shadow: var(--ds-lift-1);
  background: #fff;
}
.v2-content.sample-report-page .seo-table-wrap:focus-visible {
  outline: var(--ds-focus-width) solid var(--ds-focus);
  outline-offset: 2px;
}
/* Ledger chrome is the LEDGER's, so it is inside the wide query: below 720px
   the table is a stack of cards and a row rule there is a stray line under
   every value. */
@media (min-width: 721px) {
  .v2-content.sample-report-page .seo-table th {
    background: var(--ds-green-deep);   /* cream on deep green — 9.63:1 */
    color: var(--ds-cream);
  }
  .v2-content.sample-report-page .seo-table td {
    border-bottom: 1px solid var(--v2-hair-on-white);
  }
  .v2-content.sample-report-page .seo-table tr:last-child td {
    border-bottom: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .v2-content.sample-report-page .v2-post-table td:nth-child(7) a,
  .v2-content.instagram-competitor-tool-page .competitor-sample-links a,
  .v2-content.instagram-competitor-tool-page .competitor-checker .follower-form button {
    transition-duration: 0.01ms !important;
    transform: none !important;
  }
  .v2-content.instagram-competitor-tool-page .competitor-sample-links a:hover,
  .v2-content.instagram-competitor-tool-page .competitor-checker .follower-form button:hover {
    transform: none !important;
  }
}
