body.theme-dark .v2x.atd.atdx .atdx-mx-col a:hover{ filter:brightness(1.12); }
/* ══════════════════════════════════════════════════════════════════════════
   ATD detail pages — the components the shared tool-page kit does not define

   Loaded by every page built on `v2.public.atd.*` and scoped to `.v2x.atd.atdx`,
   one class deeper than `public-tool-atd-styles.css`, so these rules refine the
   shared kit and can never leak back onto /ai-directory/{slug} or /company/{slug}.

   Built entirely on the ATD tokens (--ink / --muted / --line / --accent) and the
   §TONE6 ramp (--t-rgb / --t-1p / --t-bg / --t-ink / --t-line), so it inherits
   contrast decisions already measured over there rather than starting a second
   palette. Every colour is defined in the light block FIRST and re-stated in the
   `body.theme-dark` twin. Washes are written as background-image +
   background-color, never the shorthand: the base sheet's dark card rule resets
   background-image and would silently erase a wash after dark.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── §ATDX-ASIDE) Hero right column — the At a Glance panel ─────────────
   The tool page parks a Swiper gallery here. None of these modules ships a
   gallery, so porting the slider would put an empty half-hero on every page.
   The facts panel goes there instead. Not `.atd-info`: that class carries the
   sidebar's orbit-ring hover, which belongs to a card you point at. */
.v2x.atd.atdx .atdx-aside{ display:flex; flex-direction:column; gap:16px; height:100%; }

.v2x.atd.atdx .atdx-profile{
  flex:1 1 auto; padding:20px; border-radius:16px;
  border:1px solid rgba(54,128,237,.22);
  background-image:linear-gradient(150deg,
    rgba(54,128,237,.075) 0%, rgba(54,128,237,0) 46%, rgba(54,128,237,.05) 100%);
  background-color:#fff;
  box-shadow:0 1px 2px rgba(15,23,42,.05), 0 14px 30px -18px rgba(15,23,42,.28);
}
body.theme-dark .v2x.atd.atdx .atdx-profile{
  border-color:rgba(54,128,237,.30);
  background-image:linear-gradient(150deg,
    rgba(54,128,237,.13) 0%, rgba(54,128,237,0) 46%, rgba(54,128,237,.08) 100%);
  background-color:var(--dk-surface-2,#17171B);
  box-shadow:0 1px 2px rgba(0,0,0,.45), 0 18px 36px -20px rgba(0,0,0,.80);
}
.v2x.atd.atdx .atdx-profile-head{ display:flex; align-items:center; gap:11px; margin-bottom:15px; }

.v2x.atd.atdx .atdx-pfs{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:10px; }
.v2x.atd.atdx .atdx-pf{
  display:flex; align-items:flex-start; gap:10px;
  padding:11px 12px; border-radius:12px;
  background-color:var(--t-bg); border:1px solid var(--t-line);
  transition:transform .3s cubic-bezier(.16,1,.3,1), box-shadow .28s ease;
}
.v2x.atd.atdx .atdx-pf-ic{
  flex:0 0 auto; width:30px; height:30px; border-radius:9px;
  display:inline-flex; align-items:center; justify-content:center;
  /* --t-1p is the ramp measured for a white GLYPH at 3:1. Nothing puts text on
     this plate, so the 4.5 label ramp is not needed. */
  background-color:var(--t-1p); color:#fff;
  box-shadow:0 2px 6px rgba(var(--t-rgb),.35);
}
.v2x.atd.atdx .atdx-pf-tx{ min-width:0; display:flex; flex-direction:column; gap:2px; }
.v2x.atd.atdx .atdx-pf-k{
  font-size:.68rem; font-weight:700; letter-spacing:.07em; text-transform:uppercase; color:var(--t-ink);
}
.v2x.atd.atdx .atdx-pf-v{
  font-size:.88rem; font-weight:700; line-height:1.35; color:var(--ink); overflow-wrap:anywhere;
}

/* One-line caveat under the hero CTA row. */
.v2x.atd.atdx .atdx-note{
  display:flex; align-items:flex-start; gap:7px;
  margin:14px 0 0; font-size:.8rem; line-height:1.5; color:var(--muted);
}
.v2x.atd.atdx .atdx-note svg{ flex:0 0 auto; margin-top:2px; opacity:.75; }

@media (hover:hover) and (pointer:fine){
  .v2x.atd.atdx .atdx-pf:hover{ transform:translateY(-2px); box-shadow:0 10px 20px -12px rgba(var(--t-rgb),.55); }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd.atdx .atdx-pf{ transition:none; }
  .v2x.atd.atdx .atdx-pf:hover{ transform:none; }
}

/* ── §ATDX-REL) Related cards in the body column ────────────────────────
   The listing card is a filter-result card — rank, excerpt, sized for a 4-up
   grid — and reads as a foreign object in an 8-column body. Related items get a
   row card on the §CARD-WASH recipe the sidebar already uses. */
.v2x.atd.atdx .atdx-rel-grid{
  display:grid; grid-template-columns:repeat(auto-fit, minmax(min(100%, 272px), 1fr)); gap:12px;
}
.v2x.atd.atdx .atdx-rel{
  display:flex; align-items:flex-start; gap:12px;
  padding:14px; border-radius:14px; text-decoration:none;
  background-color:var(--t-bg); border:1px solid var(--t-line);
  transition:transform .3s cubic-bezier(.16,1,.3,1), box-shadow .28s ease, border-color .22s ease;
}
.v2x.atd.atdx .atdx-rel-lg{
  flex:0 0 auto; width:42px; height:42px; border-radius:12px; overflow:hidden;
  display:inline-flex; align-items:center; justify-content:center;
  background-color:var(--t-1p); color:#fff; font-weight:800; font-size:1.05rem; line-height:1;
  box-shadow:0 3px 8px rgba(var(--t-rgb),.38);
}
.v2x.atd.atdx .atdx-rel-lg img{ width:100%; height:100%; object-fit:contain; display:block; }
.v2x.atd.atdx .atdx-rel-tx{ min-width:0; flex:1 1 auto; display:flex; flex-direction:column; gap:3px; }
.v2x.atd.atdx .atdx-rel-nm{ font-size:.95rem; font-weight:750; line-height:1.3; color:var(--ink); }
.v2x.atd.atdx .atdx-rel-sub{
  font-size:.81rem; line-height:1.45; color:var(--muted);
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
}
.v2x.atd.atdx .atdx-rel-meta{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin-top:3px; }
.v2x.atd.atdx .atdx-rel-pill{
  display:inline-flex; align-items:center; gap:4px; padding:2px 8px; border-radius:999px;
  font-size:.7rem; font-weight:700; color:var(--t-ink);
  background-color:rgba(var(--t-rgb),.14); border:1px solid rgba(var(--t-rgb),.24);
}
body.theme-dark .v2x.atd.atdx .atdx-rel-pill{ background-color:rgba(var(--t-rgb),.22); }
@media (hover:hover) and (pointer:fine){
  .v2x.atd.atdx a.atdx-rel:hover{
    transform:translateY(-3px);
    box-shadow:0 14px 26px -16px rgba(var(--t-rgb),.65);
    border-color:rgba(var(--t-rgb),.45);
  }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd.atdx .atdx-rel{ transition:none; }
  .v2x.atd.atdx a.atdx-rel:hover{ transform:none; }
}

/* ── §ATDX-MEASURE) Body-column prose fills its card ────────────────────
   `.v2-rich > p/ul/ol` is capped at min(100%, 80ch) in the shared kit — 855px
   inside an 1185px card at 2560px. The tool page hides that with wide
   components between its prose blocks; these pages are prose most of the way
   down, so the cap reads as text stopping halfway with a hole beside it. The
   card still limits the line, because `.v2x` caps the container. */
.v2x.atd.atdx .col-lg-8 .v2-rich > p,
.v2x.atd.atdx .col-lg-8 .v2-rich > ul,
.v2x.atd.atdx .col-lg-8 .v2-rich > ol,
.v2x.atd.atdx .col-lg-8 .v2-rich > h2,
.v2x.atd.atdx .col-lg-8 .v2-rich > h3,
.v2x.atd.atdx .col-lg-8 .v2-rich > h4,
.v2x.atd.atdx .col-lg-8 .v2-rich > blockquote{ max-width:100%; }

/* `.atd-langpill` is padded 6px 13px 6px 8px — the tight edge is room for a
   flag. These modules store languages as free text with no code to resolve one
   from, so the pill is evened up rather than left looking off-centre. */
.v2x.atd.atdx .atd-langpill{ padding:6px 13px; gap:0; }

/* ── §ATDX-RESP) Narrow viewports ───────────────────────────────────────
   Two fact tiles across put a long value on four lines once the column drops
   under ~420px. */
@media (max-width:991.98px){ .v2x.atd.atdx .atdx-aside{ height:auto; } }
@media (max-width:575.98px){
  .v2x.atd.atdx .atdx-pfs{ grid-template-columns:1fr; }
  .v2x.atd.atdx .atdx-profile{ padding:16px; }
  .v2x.atd.atdx .atdx-rel-grid{ grid-template-columns:1fr; }
}

/* ══════════════════════════════════════════════════════════════════════════
   §ATDX-MOD) The components the TEN module detail pages need

   Added 2026-08-19 when /templates, /workflows, /ai-projects, /use-cases,
   /collections, /compare, /alternatives, /best, /deals and /events were rebuilt
   on this kit to match /ai-directory/{slug} and /company/{slug}.

   These live HERE rather than in ten module sheets because every one of them is
   wanted by three or more of those pages — a numbered procedure, a checklist, a
   ranked pick, a spec table, a code block. A component only ONE page wants
   still goes in that page's own sheet, one class deeper.

   Same rules as the block above: tone vars from §TONE6, light block first with a
   `body.theme-dark` twin, washes written as background-image + background-color
   so the base sheet's dark card rule cannot erase them.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── §ATDX-STEP) A numbered procedure ───────────────────────────────────
   Workflow steps, "How to use", install instructions and event agendas are all
   the same object: an ordered list where the NUMBER is the anchor. Built on the
   §CHLOG geometry — a rail drawn on the wrapper so it spans exactly the visible
   items and no row has to know whether it is last. */
.v2x.atd.atdx .atdx-steps{ --sx:20px; position:relative; margin:2px 0 0; padding:0; list-style:none; }
.v2x.atd.atdx .atdx-steps::before{
  content:""; position:absolute; z-index:0; pointer-events:none;
  inset-inline-start:calc(var(--sx) - 1px); top:20px; bottom:20px; width:2px; border-radius:2px;
  background:linear-gradient(180deg,
    rgba(54,128,237,.34) 0%, rgba(54,128,237,.15) 62%, rgba(54,128,237,0) 100%);
}
body.theme-dark .v2x.atd.atdx .atdx-steps::before{
  background:linear-gradient(180deg,
    rgba(96,164,245,.40) 0%, rgba(96,164,245,.18) 62%, rgba(96,164,245,0) 100%);
}
.v2x.atd.atdx .atdx-step{
  position:relative; z-index:1;
  display:grid; grid-template-columns:40px minmax(0,1fr); gap:14px;
  padding:0 0 16px;
}
.v2x.atd.atdx .atdx-step:last-child{ padding-bottom:0; }
.v2x.atd.atdx .atdx-step-n{
  grid-column:1; justify-self:center; align-self:start;
  width:40px; height:40px; border-radius:12px;
  display:inline-flex; align-items:center; justify-content:center;
  font-size:.95rem; font-weight:800; line-height:1; color:#fff;
  background-color:var(--t-1p); box-shadow:0 3px 10px rgba(var(--t-rgb),.38);
  /* The rail runs behind the node; the ring is what makes it read as ON the
     line rather than crossed by it. */
  outline:4px solid #fff; outline-offset:0;
}
body.theme-dark .v2x.atd.atdx .atdx-step-n{ outline-color:var(--dk-surface-2,#17171B); }
.v2x.atd.atdx .atdx-step-b{
  min-width:0; padding:13px 15px; border-radius:14px;
  background-color:var(--t-bg); border:1px solid var(--t-line);
  transition:transform .3s cubic-bezier(.16,1,.3,1), box-shadow .28s ease;
}
.v2x.atd.atdx .atdx-step-h{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
.v2x.atd.atdx .atdx-step-t{ margin:0; font-size:.98rem; font-weight:750; line-height:1.35; color:var(--ink); }
.v2x.atd.atdx .atdx-step-p{ margin:6px 0 0; font-size:.87rem; line-height:1.6; color:var(--muted); }
.v2x.atd.atdx .atdx-step-p:first-child{ margin-top:0; }
.v2x.atd.atdx .atdx-step-m{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin-top:9px; }
@media (hover:hover) and (pointer:fine){
  .v2x.atd.atdx .atdx-step:hover .atdx-step-b{ transform:translateY(-2px); box-shadow:0 12px 24px -16px rgba(var(--t-rgb),.6); }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd.atdx .atdx-step-b{ transition:none; }
  .v2x.atd.atdx .atdx-step:hover .atdx-step-b{ transform:none; }
}

/* One pill for every "this step uses X" / "runs in 5 min" chip. Same recipe as
   `.atdx-rel-pill`, standalone so it can sit outside a related card. */
.v2x.atd.atdx .atdx-pill{
  display:inline-flex; align-items:center; gap:5px; padding:3px 9px; border-radius:999px;
  font-size:.71rem; font-weight:700; line-height:1.45; text-decoration:none; color:var(--t-ink);
  background-color:rgba(var(--t-rgb),.14); border:1px solid rgba(var(--t-rgb),.24);
}
body.theme-dark .v2x.atd.atdx .atdx-pill{ background-color:rgba(var(--t-rgb),.22); }
.v2x.atd.atdx a.atdx-pill:hover{ background-color:rgba(var(--t-rgb),.24); }
body.theme-dark .v2x.atd.atdx a.atdx-pill:hover{ background-color:rgba(var(--t-rgb),.32); }
.v2x.atd.atdx .atdx-pill svg,
.v2x.atd.atdx .atdx-pill i{ flex:0 0 auto; opacity:.9; }
/* A pill with no tone class of its own falls back to slate rather than
   inheriting whatever tone the last ancestor happened to set. */
.v2x.atd.atdx .atdx-pill.is-plain{
  color:var(--muted); background-color:rgba(100,116,139,.12); border-color:rgba(100,116,139,.22);
}
body.theme-dark .v2x.atd.atdx .atdx-pill.is-plain{
  color:var(--dk-text-3,#9AA0AB); background-color:rgba(148,163,184,.16); border-color:rgba(148,163,184,.26);
}

/* ── §ATDX-CHECK) A checklist ───────────────────────────────────────────
   "What's included", "What you need first", "What it does" — a flat list of
   short claims. Two across on desktop, one on phones. The mark is the only
   coloured thing: six hues over eight one-line items reads as decoration, so
   the tone is set ONCE on the wrapper by the section, not cycled per row. */
.v2x.atd.atdx .atdx-checks{
  display:grid; grid-template-columns:repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap:10px; margin:0; padding:0; list-style:none;
}
.v2x.atd.atdx .atdx-check{
  display:flex; align-items:flex-start; gap:10px;
  padding:11px 13px; border-radius:12px;
  background-color:var(--t-bg); border:1px solid var(--t-line);
}
.v2x.atd.atdx .atdx-check-ic{
  flex:0 0 auto; width:22px; height:22px; border-radius:7px; margin-top:1px;
  display:inline-flex; align-items:center; justify-content:center;
  background-color:var(--t-1p); color:#fff; box-shadow:0 2px 5px rgba(var(--t-rgb),.32);
}
/* Logo variant — a brand mark in place of the glyph, for a row that names a
   specific tool (the compare page's feature-wins pair). The plate flips to WHITE
   because brand marks are drawn for a light ground, in both themes: a tinted
   plate would put a coloured mark on a coloured tile. It FILLS, per the site's
   plate contract — the 1px border is drawn outside the content box, so at 22px
   the inset was only costing size — and overflow:hidden clips a square mark to
   the radius instead of squaring its corners. A row whose tool has no logo keeps
   the tinted glyph plate, so a mixed pair still lines up. */
.v2x.atd.atdx .atdx-check-ic.is-logo{
  background-color:#fff; border:1px solid var(--t-line);
  overflow:hidden; box-shadow:0 2px 5px rgba(var(--t-rgb),.22);
}
.v2x.atd.atdx .atdx-check-ic.is-logo img{ width:100%; height:100%; object-fit:contain; display:block; }
.v2x.atd.atdx .atdx-check-tx{ min-width:0; font-size:.87rem; line-height:1.55; color:var(--ink); }
.v2x.atd.atdx .atdx-check-tx b{ display:block; font-weight:750; }
.v2x.atd.atdx .atdx-check-tx small{ display:block; margin-top:2px; font-size:.8rem; color:var(--muted); }

/* ── §ATDX-PICK) A ranked pick ──────────────────────────────────────────
   /best and /alternatives are lists where POSITION is the content, so the row
   leads with the rank rather than the logo. Wide by design — one per row — so
   the editorial reason has somewhere to go. */
.v2x.atd.atdx .atdx-picks{ display:flex; flex-direction:column; gap:12px; margin:0; padding:0; list-style:none; }
.v2x.atd.atdx .atdx-pick{
  position:relative;
  display:grid; grid-template-columns:auto auto minmax(0,1fr) auto; align-items:center; gap:14px;
  padding:15px 16px; border-radius:16px;
  background-color:var(--t-bg); border:1px solid var(--t-line);
  transition:transform .3s cubic-bezier(.16,1,.3,1), box-shadow .28s ease, border-color .22s ease;
}
.v2x.atd.atdx .atdx-pick-n{
  flex:0 0 auto; min-width:34px; height:34px; padding:0 8px; border-radius:10px;
  display:inline-flex; align-items:center; justify-content:center;
  font-size:.9rem; font-weight:800; line-height:1; color:#fff;
  background-color:var(--t-1p); box-shadow:0 3px 8px rgba(var(--t-rgb),.38);
}
.v2x.atd.atdx .atdx-pick-lg{
  flex:0 0 auto; width:48px; height:48px; border-radius:13px; overflow:hidden;
  display:inline-flex; align-items:center; justify-content:center;
  background-color:#fff; border:1px solid var(--t-line);
  font-weight:800; font-size:1.1rem; line-height:1; color:var(--t-ink);
}
body.theme-dark .v2x.atd.atdx .atdx-pick-lg{ background-color:rgba(255,255,255,.06); }
.v2x.atd.atdx .atdx-pick-lg img{ width:100%; height:100%; object-fit:contain; display:block; }
.v2x.atd.atdx .atdx-pick-tx{ min-width:0; display:flex; flex-direction:column; gap:4px; }
.v2x.atd.atdx .atdx-pick-nm{
  display:flex; flex-wrap:wrap; align-items:center; gap:8px;
  font-size:1rem; font-weight:770; line-height:1.3; color:var(--ink);
}
.v2x.atd.atdx .atdx-pick-tag{
  padding:2px 8px; border-radius:999px; font-size:.68rem; font-weight:750; letter-spacing:.02em;
  color:#fff; background-color:var(--t-1p);
}
.v2x.atd.atdx .atdx-pick-sub{ font-size:.85rem; line-height:1.5; color:var(--muted); }
.v2x.atd.atdx .atdx-pick-why{
  display:flex; align-items:flex-start; gap:7px; margin-top:3px;
  font-size:.84rem; line-height:1.55; color:var(--ink);
}
.v2x.atd.atdx .atdx-pick-why svg{ flex:0 0 auto; margin-top:3px; color:var(--t-1); }
.v2x.atd.atdx .atdx-pick-m{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin-top:2px; }
.v2x.atd.atdx .atdx-pick-go{ flex:0 0 auto; display:flex; flex-direction:column; align-items:stretch; gap:7px; }
@media (hover:hover) and (pointer:fine){
  .v2x.atd.atdx .atdx-pick:hover{
    transform:translateY(-3px);
    box-shadow:0 16px 28px -18px rgba(var(--t-rgb),.65);
    border-color:rgba(var(--t-rgb),.45);
  }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd.atdx .atdx-pick{ transition:none; }
  .v2x.atd.atdx .atdx-pick:hover{ transform:none; }
}

/* ── §ATDX-MX) A spec table ─────────────────────────────────────────────
   The compare matrix, the alternatives matrix and the event ticket table. The
   WRAPPER scrolls, never the page — a 6-column matrix at 360px would otherwise
   push the whole document sideways. The first column is sticky so a row stays
   identifiable once it does scroll. */
/* The yes / no marks. Sized to the row, not to the text, so a column of them
   reads as a column. */
.v2x.atd.atdx .atdx-mk{
  display:inline-flex; align-items:center; justify-content:center;
  width:22px; height:22px; border-radius:7px;
}
.v2x.atd.atdx .atdx-mk.is-yes{ color:#08795A; background-color:rgba(16,185,129,.16); }
.v2x.atd.atdx .atdx-mk.is-no{ color:#94A3B8; background-color:rgba(148,163,184,.16); }
body.theme-dark .v2x.atd.atdx .atdx-mk.is-yes{ color:#6EE7BE; background-color:rgba(16,185,129,.22); }
body.theme-dark .v2x.atd.atdx .atdx-mk.is-no{ color:#8A94A6; background-color:rgba(148,163,184,.20); }

/* ── §ATDX-CALL) A toned callout ────────────────────────────────────────
   The verdict on /compare, the "why this list" note on /best, the terms note on
   /deals. One paragraph that has to read as a statement, not as body copy. */
.v2x.atd.atdx .atdx-call{
  display:flex; align-items:flex-start; gap:12px;
  padding:15px 17px; border-radius:14px;
  background-color:var(--t-bg);
  border:1px solid var(--t-line); border-inline-start:3px solid var(--t-1p);
}
.v2x.atd.atdx .atdx-call-ic{
  flex:0 0 auto; width:30px; height:30px; border-radius:9px;
  display:inline-flex; align-items:center; justify-content:center;
  background-color:var(--t-1p); color:#fff; box-shadow:0 2px 6px rgba(var(--t-rgb),.35);
}
.v2x.atd.atdx .atdx-call-tx{ min-width:0; font-size:.89rem; line-height:1.65; color:var(--ink); }
.v2x.atd.atdx .atdx-call-tx > b,
.v2x.atd.atdx .atdx-call-h{
  display:block; margin-bottom:3px; font-size:.72rem; font-weight:750;
  letter-spacing:.07em; text-transform:uppercase; color:var(--t-ink);
}
.v2x.atd.atdx .atdx-call-tx p:last-child{ margin-bottom:0; }

/* ── §ATDX-CODE) A copyable block ───────────────────────────────────────
   Install commands on /ai-projects, prompt bodies on /workflows. Dark in BOTH
   themes on purpose: a prompt is quoted material and the plate is what says so.
   The copy button is positioned against the block, so the block is the
   containing element and cannot be `overflow:hidden`. */
.v2x.atd.atdx .atdx-code{ position:relative; border-radius:14px; background-color:#111827; border:1px solid #263043; }
.v2x.atd.atdx .atdx-code-h{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:9px 12px 9px 14px; border-bottom:1px solid #263043;
}
.v2x.atd.atdx .atdx-code-l{
  font-size:.71rem; font-weight:750; letter-spacing:.06em; text-transform:uppercase; color:#94A3B8;
}
.v2x.atd.atdx .atdx-code pre{
  margin:0; padding:14px 16px; overflow-x:auto; -webkit-overflow-scrolling:touch;
  font-family:ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size:.82rem; line-height:1.7; color:#E2E8F0; white-space:pre; tab-size:2;
}
.v2x.atd.atdx .atdx-code.is-wrap pre{ white-space:pre-wrap; overflow-wrap:anywhere; }
.v2x.atd.atdx .atdx-copy{
  display:inline-flex; align-items:center; gap:6px; padding:5px 11px; border-radius:9px;
  font-size:.75rem; font-weight:700; line-height:1.4; cursor:pointer;
  color:#CBD5E1; background-color:rgba(255,255,255,.07); border:1px solid rgba(255,255,255,.14);
  transition:background-color .2s ease, color .2s ease;
}
.v2x.atd.atdx .atdx-copy:hover{ background-color:rgba(255,255,255,.13); color:#fff; }
.v2x.atd.atdx .atdx-copy.is-done{ color:#6EE7BE; border-color:rgba(16,185,129,.45); background-color:rgba(16,185,129,.16); }

/* ── §ATDX-KV) Key/value plates in the BODY column ──────────────────────
   `.atdx-pfs` is the hero panel's two-up grid. The body column is wider and
   takes three or four, so the grid is auto-fit here and the plate itself is the
   shared `.atdx-pf`. */
.v2x.atd.atdx .atdx-kvs{
  display:grid; grid-template-columns:repeat(auto-fit, minmax(min(100%, 190px), 1fr)); gap:10px;
}

/* ── §ATDX-SHOTS) A preview strip ───────────────────────────────────────
   Template previews and project screenshots. `object-fit:cover` on a fixed
   ratio, because these are uploaded at every aspect and a masonry of raw
   heights reads as broken rather than as variety. */
.v2x.atd.atdx .atdx-shots{
  display:grid; grid-template-columns:repeat(auto-fit, minmax(min(100%, 220px), 1fr)); gap:12px;
}
.v2x.atd.atdx .atdx-shot{
  display:block; position:relative; border-radius:14px; overflow:hidden;
  border:1px solid var(--line); background-color:#F1F5F9; aspect-ratio:16/10;
  transition:transform .3s cubic-bezier(.16,1,.3,1), box-shadow .28s ease;
}
body.theme-dark .v2x.atd.atdx .atdx-shot{ background-color:var(--dk-surface-3,#1D1D22); }
.v2x.atd.atdx .atdx-shot img{ width:100%; height:100%; object-fit:cover; display:block; }
.v2x.atd.atdx .atdx-shot-cap{
  position:absolute; inset-inline:0; bottom:0; padding:16px 12px 9px;
  font-size:.78rem; font-weight:650; line-height:1.4; color:#fff;
  background-image:linear-gradient(180deg, rgba(2,6,23,0) 0%, rgba(2,6,23,.78) 100%);
}
@media (hover:hover) and (pointer:fine){
  .v2x.atd.atdx a.atdx-shot:hover{ transform:translateY(-3px); box-shadow:0 16px 28px -18px rgba(15,23,42,.55); }
}

/* ── §ATDX-RESP2) Narrow viewports for the block above ──────────────────
   The pick row's four tracks do not survive a phone: the rank and the logo pair
   up on one line and the CTA drops full width under the text. */
@media (max-width:575.98px){
  .v2x.atd.atdx .atdx-pick{ grid-template-columns:auto minmax(0,1fr); gap:10px 12px; }
  .v2x.atd.atdx .atdx-pick-tx{ grid-column:1 / -1; }
  .v2x.atd.atdx .atdx-pick-go{ grid-column:1 / -1; }
  .v2x.atd.atdx .atdx-steps{ --sx:17px; }
  .v2x.atd.atdx .atdx-step{ grid-template-columns:34px minmax(0,1fr); gap:11px; }
  .v2x.atd.atdx .atdx-step-n{ width:34px; height:34px; border-radius:10px; font-size:.85rem; }
  .v2x.atd.atdx .atdx-kvs{ grid-template-columns:1fr; }
}

/* The matrix's group divider. §FEAT groups features on the tool page and the
   matrix says the same thing about the same data, so it groups too — as a
   spanning row rather than as tab pills, which needed Bootstrap's JS and hid
   every group but one behind a click. */

/* ══════════════════════════════════════════════════════════════════════════
   §ATDX-MX — the feature matrix.  REDESIGNED 2026-08-31.

   One renderer (`v2.public.atd.matrix`), one stylesheet, two callers:
   /compare/{slug} (2 columns + a Winner column) and /alternatives/{slug}
   (up to N columns, no Winner column). /alternatives ran a second, much older
   Blade until this rebuild; it emitted none of the hooks below, which is why
   its table looked nothing like the compare one.

   ── THE TWO THINGS THAT WERE ACTUALLY BROKEN ─────────────────────────────
   1. NOTHING COULD BREATHE. The table was `width:100%` with no floor, so six
      tools split ~1100px into 130px columns and every real answer wrapped to
      three lines. The table now takes a min-width computed from `--mx-cols`
      and SCROLLS instead of crushing. Text is never clamped anywhere in this
      block — a value that needs three lines gets three lines.
   2. THE PHONE CARDS HAD NO LABELS. The card layout reads `attr(data-label)`,
      and the old Blade never wrote one, so every answer sat in a card with no
      column name against it. That is fixed in the markup; the rule stays here.

   ── STRUCTURE ────────────────────────────────────────────────────────────
     .atdx-mx            the card — border, radius, clip. Does NOT scroll.
       .atdx-mx-bar      toolbar — the row/column counts. Stays put.
       .atdx-mx-sc       the scroll port. Sideways only.
         table           thead / one tbody PER GROUP
   The scroller is a separate element on purpose: with the toolbar inside the
   scroller it would slide off the left edge as you pan across the columns.

   ── COLOUR ───────────────────────────────────────────────────────────────
   Every value is declared in the light block and re-stated in the dark twin —
   a token defined only inside `body.theme-dark` renders as nothing by day.
   Colour is never the only signal: a winning cell carries a badge or a named
   pill as well as the green, and a mark carries a glyph as well as a tint.
   ══════════════════════════════════════════════════════════════════════════ */
.v2x.atd.atdx .atdx-mx{
  /* Surfaces */
  --mx-surface:#fff;
  --mx-head:#F4F7FD;
  --mx-bar:#FAFCFF;
  --mx-zebra:rgba(54,128,237,.035);
  --mx-hover:rgba(54,128,237,.085);
  --mx-rail:rgba(54,128,237,.55);
  /* The head link needs its OWN ink, not --accent. --accent on the head is
     3.61:1 at 13px/750 — normal-size text for WCAG, so it needs 4.5.
     --accent-dark clears it at 5.65. The dark twin has to go the OTHER way:
     --accent-dark on a dark head is 2.79, worse than what it replaces.
     One token, opposite directions per theme. */
  --mx-link:#2060C0;
  --mx-chip-bg:rgba(54,128,237,.10);
  --mx-chip-ink:#1B52A6;
  --mx-chip-line:rgba(54,128,237,.20);
  /* Verdict palette — four states, four hues, each with its own ink/fill/edge
     so a badge never leans on the fill alone. */
  --mx-win-bg:rgba(16,150,110,.10);
  --mx-win-ink:#066B50;
  --mx-win-line:rgba(16,150,110,.28);
  --mx-tie-ink:#874F00;  --mx-tie-bg:rgba(217,132,10,.13);  --mx-tie-line:rgba(217,132,10,.34);
  --mx-dep-ink:#1B52A6;  --mx-dep-bg:rgba(54,128,237,.12);  --mx-dep-line:rgba(54,128,237,.34);
  --mx-lose-ink:#B3261E; --mx-lose-bg:rgba(211,47,47,.08);  --mx-lose-line:rgba(211,47,47,.34);
  --mx-yes-ink:#0E8F6C;  --mx-yes-bg:rgba(16,150,110,.12);  --mx-yes-ring:rgba(16,150,110,.20);
  /* #8A8F9C measured 2.90:1 on its own plate, 2.78 on a zebra row and 2.63 on
     a hovered one — under the 3:1 WCAG 1.4.11 floor for a graphical object on
     all three grounds. #787D8B clears it on the worst of them (3.34) and is
     still plainly quieter than the body ink. The DARK twin was already fine at
     4.85:1 and is left alone. */
  --mx-no-ink:#787D8B;   --mx-no-bg:rgba(15,23,42,.055);

  position:relative;
  border-radius:18px;
  border:1px solid var(--line);
  background-color:var(--mx-surface);
  box-shadow:0 1px 2px rgba(15,23,42,.04), 0 8px 24px -18px rgba(15,23,42,.28);
  overflow:hidden;
}

/* ── Toolbar ──────────────────────────────────────────────────────────── */
.v2x.atd.atdx .atdx-mx-bar{
  display:flex; align-items:center; justify-content:space-between;
  gap:12px; flex-wrap:wrap;
  padding:12px 16px;
  background-color:var(--mx-bar);
  border-bottom:1px solid var(--line);
}
.v2x.atd.atdx .atdx-mx-meta{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; min-width:0; }
.v2x.atd.atdx .atdx-mx-chip{
  display:inline-flex; align-items:center; gap:6px;
  padding:4px 10px; border-radius:999px;
  font-size:.72rem; font-weight:700; letter-spacing:.01em; white-space:nowrap;
  color:var(--mx-chip-ink);
  background-color:var(--mx-chip-bg);
  border:1px solid var(--mx-chip-line);
}
.v2x.atd.atdx .atdx-mx-chip svg{ flex:none; opacity:.85; }
/* `.is-hint` — a quieter chip for advice rather than data. Nothing uses it
   today (the scroll hint it was written for could not tell truthfully whether
   the table overflows); kept because the toolbar is the obvious place for the
   next one and the rung is already tuned. */
.v2x.atd.atdx .atdx-mx-chip.is-hint{
  color:var(--muted); background-color:transparent; border-color:var(--line-strong);
  font-weight:650;
}

/* ── Scroll port + table ──────────────────────────────────────────────── */
.v2x.atd.atdx .atdx-mx-sc{
  overflow-x:auto; overflow-y:hidden;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:thin;
}
.v2x.atd.atdx .atdx-mx table{
  width:100%; margin:0;
  border-collapse:separate; border-spacing:0;
  font-size:.87rem; color:var(--ink);
  /* THE FIX for squeezed columns: a floor per tool. Below this the table
     scrolls; it never compresses a value into a three-line stack. */
  min-width:calc(200px + var(--mx-cols,2) * 132px);
}
.v2x.atd.atdx .atdx-mx th,
.v2x.atd.atdx .atdx-mx td{
  padding:13px 16px; text-align:start; vertical-align:middle;
  border-bottom:1px solid var(--line);
}
.v2x.atd.atdx .atdx-mx tbody:last-of-type tr:last-child > *{ border-bottom:0; }

/* ── Head ─────────────────────────────────────────────────────────────── */
.v2x.atd.atdx .atdx-mx thead th{
  padding-block:11px;
  font-size:.7rem; font-weight:750; letter-spacing:.07em; text-transform:uppercase;
  color:var(--muted); background-color:var(--mx-head);
  border-bottom:1px solid var(--line-strong);
  text-align:center;
}
/* The corner cell rides with the pinned column, or the word FEATURE slides
   away from the names it belongs to. */
.v2x.atd.atdx .atdx-mx thead th:first-child{
  position:sticky; inset-inline-start:0; z-index:4;
  text-align:start; background-color:var(--mx-head);
  box-shadow:1px 0 0 var(--line-strong);
}
.v2x.atd.atdx .atdx-mx-col{
  display:inline-flex; align-items:center; gap:9px; white-space:nowrap;
}
.v2x.atd.atdx .atdx-mx-col img,
.v2x.atd.atdx .atdx-mx-mono{
  width:28px; height:28px; border-radius:9px; flex:none;
  background-color:#fff; border:1px solid var(--line);
  object-fit:contain; overflow:hidden; padding:2px;
  transition:transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.v2x.atd.atdx .atdx-mx-mono{
  display:inline-flex; align-items:center; justify-content:center;
  font-size:.8rem; font-weight:800; color:var(--accent); text-transform:none; letter-spacing:0;
  padding:0;
}
.v2x.atd.atdx .atdx-mx-col a,
.v2x.atd.atdx .atdx-mx-col > span:last-child{
  font-size:.82rem; font-weight:750; letter-spacing:.02em;
  color:var(--mx-link); text-decoration:none;
  transition:color .16s ease;
}
.v2x.atd.atdx .atdx-mx thead th:hover .atdx-mx-col img,
.v2x.atd.atdx .atdx-mx thead th:hover .atdx-mx-mono{
  transform:translateY(-2px) scale(1.06);
  border-color:var(--accent);
  box-shadow:0 6px 14px -8px rgba(54,128,237,.85);
}
.v2x.atd.atdx .atdx-mx-col a:hover{ color:var(--accent-dark); text-decoration:underline; text-underline-offset:3px; }
.v2x.atd.atdx .atdx-mx-col a:focus-visible{ outline:2px solid var(--accent); outline-offset:3px; border-radius:4px; }

/* ── Group band ───────────────────────────────────────────────────────── */
/* Same opacity rule as the pinned column, for the same reason: `--t-bg` is a
   solid hex by day but an rgba() by night, so a dark group band would show the
   table scrolling behind it. */
.v2x.atd.atdx .atdx-mx-g th{
  position:static; padding:10px 16px;
  background-color:var(--mx-surface); color:var(--t-ink);
  background-image:linear-gradient(var(--t-bg),var(--t-bg));
  box-shadow:none; border-bottom:1px solid var(--t-line);
  text-align:start;
}
/* The heading, a hairline that runs out to the edge, then the count. Reads as
   a chapter rule rather than another table row.
   ⚠️ The FLEX IS ON THE WRAPPER, never on the <th>. `display:flex` on a table
   cell drops it out of the table model and its colspan with it, so the group
   band would render one column wide instead of spanning the table. */
.v2x.atd.atdx .atdx-mx-gw{ display:flex; align-items:center; gap:12px; width:100%; }
.v2x.atd.atdx .atdx-mx-gtx{
  font-size:.7rem; font-weight:800; letter-spacing:.1em; text-transform:uppercase;
  white-space:nowrap;
}
.v2x.atd.atdx .atdx-mx-gline{
  display:block; flex:1 1 auto; height:1px; min-width:16px;
  background-color:var(--t-line);
}
.v2x.atd.atdx .atdx-mx-gn{
  flex:none; min-width:20px; padding:1px 7px; border-radius:999px;
  font-size:.66rem; font-weight:800;
  color:var(--t-ink); background-color:var(--mx-surface);
  border:1px solid var(--t-line);
}

/* ── Body ─────────────────────────────────────────────────────────────── */
.v2x.atd.atdx .atdx-mx tbody th{
  position:sticky; inset-inline-start:0; z-index:1;
  font-weight:730; color:var(--ink);
  background-color:var(--mx-surface);
  box-shadow:1px 0 0 var(--line);
  transition:color .16s ease, background-color .16s ease, box-shadow .16s ease;
}
/* ⚠️ THE STICKY COLUMN MUST BE OPAQUE. `--mx-zebra` and `--mx-hover` are
   translucent, and a translucent sticky cell lets the columns scrolling behind
   it show THROUGH — on the phone slider that rendered the previous tool's
   values straight over the feature names. The tint therefore rides as a
   background-IMAGE over an opaque background-COLOR on the pinned cells; the
   plain <td>s have nothing behind them and keep the cheaper single layer. */
.v2x.atd.atdx .atdx-mx tbody tr:nth-child(even) td{ background-color:var(--mx-zebra); }
.v2x.atd.atdx .atdx-mx tbody tr:nth-child(even) th{
  background-color:var(--mx-surface);
  background-image:linear-gradient(var(--mx-zebra),var(--mx-zebra));
}
.v2x.atd.atdx .atdx-mx tbody td{ transition:background-color .16s ease; }
/* Row hover reads across the WHOLE row, which is how the eye ties a feature to
   its answers. The sticky first cell has to be repainted or it keeps the zebra
   and the row looks broken at the left edge; it also takes the brand rail, so
   the hover has an anchor and not just a wash. */
.v2x.atd.atdx .atdx-mx tbody tr:not(.atdx-mx-g):hover > td{ background-color:var(--mx-hover); }
.v2x.atd.atdx .atdx-mx tbody tr:not(.atdx-mx-g):hover > th{
  color:var(--accent-dark);
  background-color:var(--mx-surface);
  background-image:linear-gradient(var(--mx-hover),var(--mx-hover));
  box-shadow:inset 3px 0 0 var(--mx-rail), 1px 0 0 var(--line);
}
.v2x.atd.atdx .atdx-mx-cell{
  display:inline-flex; align-items:center; justify-content:center;
  gap:9px; flex-wrap:wrap; width:100%;
}
/* No clamp, no ellipsis, anywhere. A long answer wraps and the row grows. */
.v2x.atd.atdx .atdx-mx-v{
  /* break-word, not anywhere — see the pinned-column note in the PHONE block.
     Both prevent overflow; only `anywhere` also lets the browser size the
     column as if one character were an acceptable line, which is how values
     end up split mid-word. */
  min-width:0; line-height:1.45; overflow-wrap:break-word; word-break:normal; text-align:center;
}
.v2x.atd.atdx .atdx-mx td{ text-align:center; }
.v2x.atd.atdx .atdx-mx tbody th{ text-align:start; }

/* ── Verdict ──────────────────────────────────────────────────────────── */
.v2x.atd.atdx .atdx-mx td.is-win{
  color:var(--mx-win-ink); font-weight:750;
  background-image:linear-gradient(var(--mx-win-bg), var(--mx-win-bg));
  box-shadow:inset 3px 0 0 var(--mx-win-line);
}
.v2x.atd.atdx .atdx-mx-win{
  display:inline-flex; align-items:center; gap:4px; flex:none;
  padding:2px 8px 2px 6px; border-radius:999px;
  font-size:.64rem; font-weight:800; letter-spacing:.05em; text-transform:uppercase;
  color:#fff; background-color:#0E8F6C;
  box-shadow:0 1px 2px rgba(15,23,42,.12);
}
.v2x.atd.atdx .atdx-mx-win svg{ flex:none; }

/* ── Winner column ───────────────────────────────────────────────────── */
/* The verdict, said in words. This is what carries the result for anyone who
   cannot separate the green tint from the body ink, which is why the in-cell
   "Better" badge is dropped whenever this column is present. */
/* Qualified with the element on purpose: `.atdx-mx td` carries an element in
   its selector, so a bare `.atdx-mx-wc` loses the tie and the Winner column
   stays centred. */
.v2x.atd.atdx .atdx-mx thead th.atdx-mx-wh{ text-align:end; }
.v2x.atd.atdx .atdx-mx td.atdx-mx-wc{ text-align:end; white-space:nowrap; }
.v2x.atd.atdx .atdx-mx-w{
  display:inline-flex; align-items:center; justify-content:center;
  min-width:74px; padding:5px 12px; border-radius:999px;
  font-size:.74rem; font-weight:800; letter-spacing:.01em;
  border:1px solid transparent;
}
.v2x.atd.atdx .atdx-mx-w.is-win{ color:var(--mx-win-ink); background-color:var(--mx-win-bg); border-color:var(--mx-win-line); }
.v2x.atd.atdx .atdx-mx-w.is-tie{ color:var(--mx-tie-ink); background-color:var(--mx-tie-bg); border-color:var(--mx-tie-line); }
.v2x.atd.atdx .atdx-mx-w.is-dep{ color:var(--mx-dep-ink); background-color:var(--mx-dep-bg); border-color:var(--mx-dep-line); }

/* The losing side of a decided row. Deliberately LIGHTER than the winner's
   green — both cells shouting equally would flatten the very contrast the row
   exists to draw, and a red wash on 12 of 19 rows reads as an error state. */
.v2x.atd.atdx .atdx-mx td.is-lose{
  color:var(--mx-lose-ink);
  background-image:linear-gradient(var(--mx-lose-bg), var(--mx-lose-bg));
  box-shadow:inset 3px 0 0 var(--mx-lose-line);
}

/* ── Marks ────────────────────────────────────────────────────────────── */
.v2x.atd.atdx .atdx-mx .atdx-mk{
  width:24px; height:24px; border-radius:8px; flex:none;
  display:inline-flex; align-items:center; justify-content:center;
  transition:box-shadow .18s ease, transform .18s ease;
}
.v2x.atd.atdx .atdx-mk.is-yes{ color:var(--mx-yes-ink); background-color:var(--mx-yes-bg); }
.v2x.atd.atdx .atdx-mk.is-no{ color:var(--mx-no-ink); background-color:var(--mx-no-bg); }
.v2x.atd.atdx .atdx-mx tbody tr:not(.atdx-mx-g):hover .atdx-mk.is-yes{
  transform:scale(1.08); box-shadow:0 0 0 4px var(--mx-yes-ring);
}

/* ══ DARK ═══════════════════════════════════════════════════════════════ */
body.theme-dark .v2x.atd.atdx .atdx-mx{
  --mx-surface:var(--dk-surface-2,#17171B);
  --mx-head:var(--dk-surface-3,#1D1D22);
  --mx-bar:var(--dk-surface-3,#1D1D22);
  --mx-zebra:rgba(96,164,245,.05);
  --mx-hover:rgba(96,164,245,.11);
  --mx-rail:rgba(96,164,245,.75);
  --mx-link:#9CC5F9;
  --mx-chip-bg:rgba(96,164,245,.14);
  --mx-chip-ink:#9CC5F9;
  --mx-chip-line:rgba(96,164,245,.28);
  --mx-win-bg:rgba(52,211,153,.13);
  --mx-win-ink:#6EE7BE;
  --mx-win-line:rgba(52,211,153,.42);
  --mx-tie-ink:#F5B95C;  --mx-tie-bg:rgba(217,132,10,.18);  --mx-tie-line:rgba(245,185,92,.40);
  --mx-dep-ink:#9CC5F9;  --mx-dep-bg:rgba(96,164,245,.16);  --mx-dep-line:rgba(96,164,245,.42);
  --mx-lose-ink:#F49B94; --mx-lose-bg:rgba(211,47,47,.13);  --mx-lose-line:rgba(244,155,148,.38);
  --mx-yes-ink:#6EE7BE;  --mx-yes-bg:rgba(52,211,153,.15);  --mx-yes-ring:rgba(52,211,153,.20);
  --mx-no-ink:#8A94A6;   --mx-no-bg:rgba(255,255,255,.07);
  box-shadow:0 1px 2px rgba(0,0,0,.5), 0 10px 28px -20px rgba(0,0,0,.9);
}
/* Brand marks keep their own white plate in dark — a logo drawn for a light
   ground disappears on #17171B. */
body.theme-dark .v2x.atd.atdx .atdx-mx-col img,
body.theme-dark .v2x.atd.atdx .atdx-mx-mono{ background-color:#fff; border-color:var(--dk-line-strong,rgba(255,255,255,.16)); }
body.theme-dark .v2x.atd.atdx .atdx-mx-mono{ color:var(--accent-dark); }
body.theme-dark .v2x.atd.atdx .atdx-mx-win{ background-color:#0E9C74; color:#04241B; }
body.theme-dark .v2x.atd.atdx .atdx-mx-col a:hover{ color:#C7DEFC; }
body.theme-dark .v2x.atd.atdx .atdx-mx tbody tr:not(.atdx-mx-g):hover > th{ color:#9CC5F9; }
body.theme-dark .v2x.atd.atdx .atdx-mx-gn{ background-color:var(--dk-surface-2,#17171B); }

/* ══ TABLET — the table, tighter, always scrolling ══════════════════════ */
@media (max-width:1024px) and (min-width:561px){
  .v2x.atd.atdx .atdx-mx table{ min-width:calc(180px + var(--mx-cols,2) * 124px); font-size:.85rem; }
  .v2x.atd.atdx .atdx-mx th,
  .v2x.atd.atdx .atdx-mx td{ padding:12px 14px; }
  .v2x.atd.atdx .atdx-mx-bar{ padding:11px 14px; }
  .v2x.atd.atdx .atdx-mx-col img,
  .v2x.atd.atdx .atdx-mx-mono{ width:26px; height:26px; }
}

/* ══ PHONE — the column slider ══════════════════════════════════════════
   Was one card per feature: every tool got its own labelled row inside the
   card, so six tools turned 35 features into 210 stacked rows. It never
   truncated anything, but it stopped being a COMPARISON — you cannot hold two
   answers side by side when they are 200px apart vertically.

   It is now a slider. The feature column pins to the left, the tool columns
   become snap targets about 62vw wide, and you swipe (or use the arrows and
   dots below the toolbar) to move one tool at a time with the next one peeking
   at the edge. Nothing is clamped or ellipsised — a long value wraps and the
   row grows, exactly as it does on desktop.

   IT SCROLLS SIDEWAYS ONLY. An earlier pass bounded the scroller with a
   max-height so the head row could pin (sticky resolves against the nearest
   scrollport, so a head can only pin if its container scrolls vertically) —
   that put a scroll region inside the page scroll, which fights a thumb. The
   rows are the page's to scroll; only the columns are the slider's. The head
   therefore scrolls away with everything else, and the rail's dots and n/N
   readout are what say which tool you are on.
   ══════════════════════════════════════════════════════════════════════════ */
/* 560px, not 780px. The slider's whole premise is that one tool column fills
   the port — at 768px (iPad portrait) the port is 659px and 2.4 columns were
   on screen while the rail still read "1/6", so the dots and the counter
   contradicted what the reader could see. Above this width the scrolling
   table is the honest layout. */
@media (max-width:560px){
  /* One slot = one tool column. Both the CSS and the slider script derive
     their offsets from these, so they cannot disagree.
     ⚠️ SIZED AGAINST THE SCROLLER, NOT THE VIEWPORT. `vw` counts the whole
     screen, but the card sits inside the section's padding and the page
     gutter — measured at 390px the scrollport is 309px, so a 40vw/50vw pair
     came to 351px and cut 42px off the tool column. The chrome around the
     scroller is fixed rather than proportional, hence `100vw - 227px`:
     130px pin + column + ~16px peek. --mx-pin stays fixed because it is sized
     off the longest feature WORD ("Personalization", 98px at .8rem) plus its
     20px padding, which does not scale with the screen. */
  /* peek = port − (pin + col) = (vw−81) − (130 + (vw−227)) = a constant 16px,
     for as long as the clamp is not pinned to a bound. The 300px ceiling is
     what keeps that true all the way to the 560px boundary; at 220px the
     column stopped growing at ~527px and the "peek" opened to half a column. */
  .v2x.atd.atdx .atdx-mx{ --mx-pin:130px; --mx-colw:clamp(140px,calc(100vw - 227px),300px); }

  /* Toolbar becomes its own card above the slider. */
  .v2x.atd.atdx .atdx-mx-bar{
    border-bottom:1px solid var(--line);
    padding:11px 12px; gap:10px;
  }
  .v2x.atd.atdx .atdx-mx-meta{ gap:7px; }

  /* ── The slider rail ─────────────────────────────────────────────────── */
  .v2x.atd.atdx .atdx-mx-slider{
    display:flex; align-items:center; gap:10px;
    padding:9px 12px;
    background-color:var(--mx-bar);
    border-bottom:1px solid var(--line);
  }
  .v2x.atd.atdx .atdx-mx-nav{
    flex:none; width:32px; height:32px; padding:0;
    display:inline-flex; align-items:center; justify-content:center;
    border-radius:999px; cursor:pointer;
    color:var(--mx-chip-ink);
    background-color:var(--mx-surface);
    border:1px solid var(--mx-chip-line);
    transition:background-color .16s ease, border-color .16s ease, color .16s ease, transform .16s ease;
  }
  .v2x.atd.atdx .atdx-mx-nav:hover:not(:disabled),
  .v2x.atd.atdx .atdx-mx-nav:active:not(:disabled){
    color:#fff; background-color:var(--accent-dark); border-color:var(--accent-dark);
  }
  .v2x.atd.atdx .atdx-mx-nav:active:not(:disabled){ transform:scale(.94); }
  .v2x.atd.atdx .atdx-mx-nav:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
  /* Disabled says "this is the end of the rail", so it must still be legible —
     an invisible control reads as a rendering bug. */
  .v2x.atd.atdx .atdx-mx-nav:disabled{ opacity:.4; cursor:default; }

  .v2x.atd.atdx .atdx-mx-dots{
    flex:1 1 auto; display:flex; align-items:center; justify-content:center;
    gap:7px; flex-wrap:wrap; min-width:0;
  }
  .v2x.atd.atdx .atdx-mx-dot{
    width:8px; height:8px; padding:0; flex:none;
    border-radius:999px; border:0; cursor:pointer;
    background-color:var(--line-strong);
    transition:background-color .18s ease, width .18s ease;
  }
  /* The active dot lengthens as well as changing colour — position on the rail
     has to survive a reader who cannot separate the two blues. */
  .v2x.atd.atdx .atdx-mx-dot.is-on{ width:22px; background-color:var(--accent); }
  .v2x.atd.atdx .atdx-mx-dot:focus-visible{ outline:2px solid var(--accent); outline-offset:3px; }
  .v2x.atd.atdx .atdx-mx-count{
    flex:none; font-size:.72rem; font-weight:750; color:var(--muted);
    font-variant-numeric:tabular-nums;
  }
  .v2x.atd.atdx .atdx-mx-count b{ color:var(--ink); }

  /* ── The scroller: HORIZONTAL ONLY ───────────────────────────────────── */
  /* No max-height and no inner vertical scroll — the page scrolls the rows,
     the slider scrolls the columns, and there is never a scroll region inside
     a scroll region to fight with a thumb. `overflow-y:hidden` is explicit
     because `overflow-x:auto` alone computes the other axis to `auto` and
     quietly gives the box a second scrollbar. The cost is that the head row
     cannot pin (sticky resolves against a scrollport that now never scrolls
     vertically), which is why the rail above carries the position readout. */
  .v2x.atd.atdx .atdx-mx-sc{
    overflow-x:auto; overflow-y:hidden;
    scroll-snap-type:x mandatory;
    scroll-padding-inline-start:var(--mx-pin);
    overscroll-behavior-x:contain;
    scroll-behavior:smooth;
  }
  .v2x.atd.atdx .atdx-mx table{ min-width:0; }
  .v2x.atd.atdx .atdx-mx th,
  .v2x.atd.atdx .atdx-mx td{ padding:12px 13px; }

  /* Feature column pinned. Fixed width so the snap offset above matches it.
     ⚠️ `break-word`, NOT `anywhere`. Both break a word that cannot fit, but
     `anywhere` also drops min-content to a single character, which is what let
     this column shrink until "Conversational" split as "Conversationa / l".
     With `break-word` the browser keeps the whole word as the floor and only
     splits one that genuinely cannot fit on a line of its own. */
  .v2x.atd.atdx .atdx-mx thead th:first-child,
  .v2x.atd.atdx .atdx-mx tbody th{
    width:var(--mx-pin); min-width:var(--mx-pin); max-width:var(--mx-pin);
    padding-inline:10px;
    font-size:.8rem; line-height:1.35;
    white-space:normal; overflow-wrap:break-word; word-break:normal; hyphens:none;
  }
  .v2x.atd.atdx .atdx-mx thead th:first-child{ z-index:5; box-shadow:1px 0 0 var(--line-strong); }
  .v2x.atd.atdx .atdx-mx tbody th{ z-index:2; }

  /* ⚠️ WIDTH, not just MIN-WIDTH. `table-layout` is auto, so a min-width alone
     leaves the browser free to size a column to its longest line — the column
     grew past the slot, and because the cell centres its content the overflow
     went out BOTH sides, sliding the left half under the pinned feature column.
     Pinning all three of width/min/max makes the column exactly one slot wide
     and sends the text back to wrapping, which is what stops the overlap. */
  .v2x.atd.atdx .atdx-mx thead th:not(:first-child),
  .v2x.atd.atdx .atdx-mx tbody td{
    width:var(--mx-colw); min-width:var(--mx-colw); max-width:var(--mx-colw);
    white-space:normal; overflow-wrap:break-word; word-break:normal;
  }
  .v2x.atd.atdx .atdx-mx thead th:not(:first-child){ scroll-snap-align:start; }
  /* The header name is the one thing allowed to keep its own line. */
  .v2x.atd.atdx .atdx-mx-col{ white-space:normal; }
  /* A flex item defaults to min-width:auto, i.e. it refuses to shrink below its
     longest word — the second half of the same overflow. */
  .v2x.atd.atdx .atdx-mx-cell{ max-width:100%; min-width:0; }
  .v2x.atd.atdx .atdx-mx-v{ min-width:0; max-width:100%; }

  /* The group band spans every column, so it is left to scroll with them
     rather than pinned: a colspan cell forced to viewport width fights the
     table's own layout, and the band is short enough to read on the way past. */
  .v2x.atd.atdx .atdx-mx-g th{ padding:9px 13px; }
  .v2x.atd.atdx .atdx-mx-gtx{ font-size:.68rem; letter-spacing:.1em; }

  /* Values wrap and the row grows — no clamp, no ellipsis, same as desktop. */
  .v2x.atd.atdx .atdx-mx-v{ overflow-wrap:break-word; word-break:normal; }
  .v2x.atd.atdx .atdx-mx td.atdx-mx-wc{ text-align:center; white-space:normal; }
}

/* Desktop and tablet have no slider — the whole table is already on screen or
   one flick away, and a rail of dots under it would be decoration. */
@media (min-width:561px){
  .v2x.atd.atdx .atdx-mx-slider{ display:none; }
}

/* ══ MOTION ═════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion:reduce){
  /* The slider must still MOVE, it just must not animate the move — arrows
     and dots jump straight to the column instead of gliding. */
  .v2x.atd.atdx .atdx-mx-sc{ scroll-behavior:auto; }
  .v2x.atd.atdx .atdx-mx-dot,
  .v2x.atd.atdx .atdx-mx-nav{ transition:none !important; }
  .v2x.atd.atdx .atdx-mx-nav:active:not(:disabled){ transform:none; }
  .v2x.atd.atdx .atdx-mx tbody tr,
  .v2x.atd.atdx .atdx-mx tbody th,
  .v2x.atd.atdx .atdx-mx td,
  .v2x.atd.atdx .atdx-mx .atdx-mk,
  .v2x.atd.atdx .atdx-mx-col img,
  .v2x.atd.atdx .atdx-mx-mono{ transition:none !important; }
  .v2x.atd.atdx .atdx-mx thead th:hover .atdx-mx-col img,
  .v2x.atd.atdx .atdx-mx thead th:hover .atdx-mx-mono,
  .v2x.atd.atdx .atdx-mx tbody tr:not(.atdx-mx-g):hover .atdx-mk.is-yes{ transform:none; }
}
