
/* ==========================================================================
   GLOBAL THEME ISOLATION — force a light, theme-independent canvas
   ========================================================================== */
body:has(.v2x){ background:var(--dk-bg, #FFFFFF) !important; color:#0F0F12 !important; }
body:has(.v2x) .page,
body:has(.v2x) .page-wrapper,
body:has(.v2x) .page-body{ background:transparent !important; }
body:has(.v2x) .navbar{ background:#fff !important; border-bottom:1px solid #e7eaf1 !important; }
body:has(.v2x) .navbar .nav-link,
body:has(.v2x) .navbar .navbar-brand{ color:#0F0F12 !important; }
body:has(.v2x) .footer{ background:#fff !important; border-top:1px solid #e7eaf1 !important; }
body:has(.v2x) .seo-breadcrumbs .breadcrumb{ font-size:.88rem; }
body:has(.v2x) .seo-breadcrumbs .breadcrumb-item,
body:has(.v2x) .seo-breadcrumbs .breadcrumb-item a{ color:#4A4A5A; }
body:has(.v2x) .seo-breadcrumbs .breadcrumb-item a:hover{ color:#3680ED; }
body:has(.v2x) .seo-breadcrumbs .breadcrumb-item.active{ color:#0F0F12; font-weight:600; }

/* Mirror for browsers without :has() — body.v2-host added via JS above */
body.v2-host{ background:var(--dk-bg, #FFFFFF) !important; color:#0F0F12 !important; }
body.v2-host .page,
body.v2-host .page-wrapper,
body.v2-host .page-body{ background:transparent !important; }
body.v2-host .navbar{ background:#fff !important; border-bottom:1px solid #e7eaf1 !important; }
body.v2-host .navbar .nav-link,
body.v2-host .navbar .navbar-brand{ color:#0F0F12 !important; }
body.v2-host .footer{ background:#fff !important; border-top:1px solid #e7eaf1 !important; }
body.v2-host .seo-breadcrumbs .breadcrumb{ font-size:.88rem; }
body.v2-host .seo-breadcrumbs .breadcrumb-item,
body.v2-host .seo-breadcrumbs .breadcrumb-item a{ color:#4A4A5A; }
body.v2-host .seo-breadcrumbs .breadcrumb-item a:hover{ color:#3680ED; }
body.v2-host .seo-breadcrumbs .breadcrumb-item.active{ color:#0F0F12; font-weight:600; }

/* ==========================================================================
   Design tokens (design.md). --v2-* aliases keep the shared V2 partials
   (reviews-section, faq-accordion, stars, …) on the same palette.
   ========================================================================== */
.v2x.atd{
  --accent:#3680ED;
  --accent-dark:#2060C0;
  --accent-light:#60A4F5;
  --accent-soft:#eef4fe;
  --accent-soft2:#f6f9ff;
  --ink:#0F0F12;
  --muted:#4A4A5A;
  --muted2:#8a8a9a;
  --line:#e7eaf1;
  --line-strong:#d7dbe6;
  --bg:#f6f8fc;
  --green:#22C55E;
  --green-ink:#15803d;
  --amber:#F59E0B;
  --violet:#8B5CF6;
  --red:#EF4444;

  --grad-brand:linear-gradient(135deg,#2060C0 0%,#3680ED 50%,#60A4F5 100%);

  --r-card:12px; --r-hero:16px; --r-logo:16px; --r-btn:8px; --r-pill:999px;

  --sh-sm:0 1px 3px rgba(15,15,18,.10), 0 1px 2px rgba(15,15,18,.06);
  --sh-md:0 4px 6px rgba(15,15,18,.07), 0 2px 4px rgba(15,15,18,.06);
  --sh-lg:0 10px 15px rgba(15,15,18,.10), 0 4px 6px rgba(15,15,18,.05);
  --sh-brand:0 8px 24px rgba(54,128,237,.28);

  --font:'Inter',system-ui,-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  --mono:'JetBrains Mono',ui-monospace,'SF Mono',Menlo,monospace;
  letter-spacing:-.011em; font-feature-settings:'cv11','ss01';

  /* aliases for shared v2 partials */
  --v2-accent:var(--accent); --v2-accent2:var(--accent-dark); --v2-accent-light:var(--accent-light);
  --v2-accent-soft:var(--accent-soft); --v2-accent-soft2:var(--accent-soft2);
  --v2-ink:var(--ink); --v2-muted:var(--muted); --v2-line:var(--line); --v2-bg:var(--bg);
  --v2-amber:var(--amber); --v2-green:var(--green); --v2-red:var(--red); --v2-violet:var(--violet);

  font-family:var(--font);
  font-size:16px; line-height:1.6; color:var(--ink);
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
}
/* ==========================================================================
   §0a) Content width — fill the layout container, do not re-cap it.

   This used to be `max-width:1240px` inside the site's 1600px shell, which
   centred the page ~130px inside the breadcrumb sitting directly above it
   (and ~164px inside the header brand above that) — three different left
   edges stacked down the first viewport. The shell is the single source of
   width; the shared gutter is applied to the container in §0b.
   ========================================================================== */
.v2x.atd{ max-width:none; margin-inline:0; padding-inline:0; }

/* §0b) Gutter alignment lived here briefly as a page-scoped :has() override.
   It is now sitewide in partials/shell-cap.blade.php — `--seo-shell-pad`
   mirrors the header's 24/20/14/11 ramp for every public page — so this
   page needs nothing of its own. Do not re-add a local override here; it
   would silently diverge from the header the next time the ramp changes. */

.v2x.atd img{ max-width:100%; }
.v2x.atd a{ color:var(--accent); text-decoration:none; transition:color 150ms ease; }
.v2x.atd a:hover{ color:var(--accent-dark); text-decoration:none; }
.v2x.atd .mono,
.v2x.atd .atd-mono{ font-family:var(--mono); font-feature-settings:"ss01"; }

/* Visible focus rings */
.v2x.atd :is(a,button,summary,[tabindex]):focus-visible{
  outline:none; box-shadow:0 0 0 3px rgba(54,128,237,.30); border-radius:8px;
}

/* ==========================================================================
   Cards / sections / titles (re-skins the shared .v2-card/.v2-section too)
   ========================================================================== */
.v2x.atd .v2-card{ background:#fff; border:1px solid var(--line); border-radius:var(--r-card); box-shadow:var(--sh-sm); }
.v2x.atd .v2-card.pad{ padding:26px; }
.v2x.atd .v2-section{ margin-bottom:26px; scroll-margin-top:104px; }
.v2x.atd .v2-divider{ height:1px; background:var(--line); margin:22px 0; }
/* Section titles are real <h2> elements (they used to be <div>s, which left the
   whole main column with no heading outline). The class carries every visual
   property, so the element swap is invisible — this just neutralises the UA /
   Bootstrap-reboot <h2> margin-top and font-size that now come along with it. */
.v2x.atd .v2-section-title{
  display:flex; align-items:center; gap:11px;
  font-family:var(--font); font-size:1.5rem; font-weight:700; letter-spacing:-.02em;
  color:var(--ink); margin-top:0; margin-bottom:20px; line-height:1.2;
}
.v2x.atd .v2-section-title i{ color:var(--accent); font-size:1.05rem; opacity:1; }

/* ⚠️ THIS RAMP WAS MISSING, AND ITS ABSENCE WAS INVISIBLE IN THE SOURCE.
   The shared kit ships a phone step-down — `@media (max-width:575px){ .v2x
   .v2-section-title{ font-size:var(--text-xl) } }` in partials/styles, i.e.
   1.5rem -> 1.25rem. The base rule directly above is `.v2x.atd` at (0,3,0)
   and beats that (0,2,0) rule AT EVERY WIDTH, so the step-down never fired
   here and all 528 section headings on these three page types stayed a flat
   24px on a 360px phone. Overriding a shared rule silently inherits
   responsibility for its whole ramp, not just the value you meant to change.

   The steps mirror the breakpoints the rest of this kit already uses. Only
   font-size and margin-bottom are touched: `gap` belongs to the (0,4,0)
   main-column rule near §CARD-ICON and setting it here would lose to that on
   exactly the headings that carry an icon tile — a half-applied rule is worse
   than none. Nothing at or above 768px moves. */
@media (max-width:767.98px){
  .v2x.atd .v2-section-title{ font-size:1.34rem; margin-bottom:16px; }
}
@media (max-width:575.98px){
  .v2x.atd .v2-section-title{ font-size:1.22rem; margin-bottom:14px; }
}
@media (max-width:399.98px){
  .v2x.atd .v2-section-title{ font-size:1.13rem; }
}
.v2x.atd .v2-muted{ color:var(--muted); }
.v2x.atd .v2-rich{ font-size:1.06rem; line-height:1.8; color:#39414d; }
/* Reading measure. §0a widened the page from 1240px to the 1600px shell,
   which took the About/longform column from ~87 to ~113 characters a line —
   past the ~45-90ch comfortable range. Cap the TEXT, not the card, so the
   card edges stay aligned with the hero and breadcrumb while the prose keeps
   a readable line. Block children (tables, figures, embeds) are untouched
   and still use the card's full width. */
.v2x.atd .v2-rich > p,
.v2x.atd .v2-rich > ul,
.v2x.atd .v2-rich > ol,
.v2x.atd .v2-rich > h2,
.v2x.atd .v2-rich > h3,
.v2x.atd .v2-rich > h4,
.v2x.atd .v2-rich > blockquote{ max-width:min(100%, 80ch); }
.v2x.atd .v2-rich p{ margin-bottom:1rem; }
.v2x.atd .v2-rich h2,.v2x.atd .v2-rich h3,.v2x.atd .v2-rich h4{ font-family:var(--font); font-weight:700; color:var(--ink); letter-spacing:-.01em; margin:1.4rem 0 .6rem; }
.v2x.atd .v2-rich strong{ color:var(--ink); font-weight:700; }
.v2x.atd .v2-rich ul,.v2x.atd .v2-rich ol{ padding-left:1.1rem; margin-bottom:1rem; }
.v2x.atd .v2-rich li{ margin-bottom:.4rem; }

/* Accent link with arrow */
.v2x.atd .atd-link{
  color:var(--accent); font-weight:600; font-size:.95rem;
  display:inline-flex; align-items:center; gap:7px; transition:color 150ms ease,gap 150ms ease;
}
.v2x.atd .atd-link:hover{ color:var(--accent-dark); gap:10px; }

/* ==========================================================================
   Buttons (also re-skins shared .v2-btn so reviews/share partials match)
   ========================================================================== */
.v2x.atd .v2-btn,
.v2x.atd .atd-btn{
  display:inline-flex; align-items:center; justify-content:center; gap:9px;
  font-family:var(--font); font-weight:600; font-size:.97rem; line-height:1.2;
  border-radius:var(--r-btn); padding:13px 24px; cursor:pointer;
  transition:all 180ms ease; border:1px solid transparent; text-decoration:none;
}
.v2x.atd .v2-btn-primary,
.v2x.atd .atd-btn-primary{ background:var(--accent); color:#fff; box-shadow:var(--sh-sm); }
.v2x.atd .v2-btn-primary:hover,
.v2x.atd .atd-btn-primary:hover{ background:var(--accent-dark); color:#fff; box-shadow:var(--sh-brand); }
.v2x.atd .v2-btn-outline,
.v2x.atd .atd-btn-outline{ background:#fff; color:var(--accent); border-color:var(--accent); }
.v2x.atd .v2-btn-outline:hover,
.v2x.atd .atd-btn-outline:hover{ background:var(--accent-soft); color:var(--accent-dark); }
.v2x.atd .atd-btn-ghost{ background:#fff; color:var(--ink); border-color:var(--line-strong); font-weight:600; }
.v2x.atd .atd-btn-ghost:hover{ border-color:var(--accent); color:var(--accent); }
.v2x.atd .atd-btn-sm{ padding:9px 16px; font-size:.88rem; white-space:nowrap; }

/* ==========================================================================
   §CLAIM) Sidebar ownership card — "Own this listing?" / "Owner managed"

   Moved out of the hero. Bespoke markup (see sidebar.blade.php) rather than
   the shared x-public.tool-type component's `aitt-cta`, because that component
   also serves the ~2,000 INTERNAL tool pages, which must never gain a claim
   affordance.

   ⚠️ Never write an `x-…` component tag in angle brackets anywhere in a .blade
   file — not even inside a CSS or JS comment. Blade's component compiler runs
   over the RAW template, so it happily compiled one from this comment and the
   page 500'd with "unexpected end of file, expecting endif".
   ========================================================================== */
.v2x.atd .atd-claim{
  position:relative; overflow:hidden;
  background:linear-gradient(150deg,#f7faff 0%,#fff 46%,#f4f8ff 100%);
  border-color:#d9e6fb;
  transition:border-color 260ms ease, box-shadow 320ms cubic-bezier(.16,1,.3,1),
             transform 320ms cubic-bezier(.16,1,.3,1);
}
/* Corner bloom. Anchored to the card, `pointer-events:none`, and OUT of flow
   so it can never become a stray grid/flex item. */
.v2x.atd .atd-claim-glow{
  position:absolute; inset-inline-end:-70px; top:-80px; z-index:0;
  width:210px; height:210px; border-radius:50%; pointer-events:none;
  background:radial-gradient(circle, rgba(54,128,237,.22) 0%, rgba(54,128,237,0) 70%);
  transition:opacity 360ms ease, transform 520ms cubic-bezier(.16,1,.3,1);
}
.v2x.atd .atd-claim > *:not(.atd-claim-glow){ position:relative; z-index:1; }

.v2x.atd .atd-claim-head{ display:flex; align-items:center; gap:11px; margin-bottom:10px; }
.v2x.atd .atd-claim-ic{
  flex:0 0 auto; width:36px; height:36px; border-radius:11px;
  display:flex; align-items:center; justify-content:center;
  background:linear-gradient(135deg,#4C8DF2,#2060C0); color:#fff; font-size:.92rem;
  box-shadow:0 5px 14px rgba(32,96,192,.34);
  transition:transform 380ms cubic-bezier(.16,1,.3,1), box-shadow 300ms ease;
}
/* Redundant since the head-row list in §SIDE owns this — and it was NOT
   enough on its own: the mobile step re-states `margin-bottom:14px` on
   `.atd-side-title` at the SAME (0,2,0) specificity but LATER in the file, so
   under 768px this lost and the claim heading rode 7px above its icon. Kept
   only so the class is not silently unstyled. */
.v2x.atd .atd-claim-title{ margin:0; }
.v2x.atd .atd-claim-text{
  margin:0 0 14px; color:var(--muted); font-size:.9rem; line-height:1.6;
}

/* CTA — label left, arrow right, so a long translated label wraps against the
   arrow instead of pushing it out of the button. */
.v2x.atd .atd-claim-btn{
  position:relative; overflow:hidden; isolation:isolate;
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  width:100%; padding:12px 16px; border-radius:12px;
  background:linear-gradient(135deg,#4C8DF2 0%,#3680ED 52%,#2060C0 100%);
  border:1px solid transparent;
  font-family:var(--font); font-size:.9rem; font-weight:700; line-height:1.35;
  box-shadow:0 8px 20px rgba(54,128,237,.28);
  transition:transform 300ms cubic-bezier(.16,1,.3,1), box-shadow 300ms ease, filter 240ms ease;
}
/* The label colour is pinned on every state: an <a> in this layout inherits a
   link colour, and the sitewide inline `.card a:hover{color:#2060C0}` (0,2,0)
   would otherwise repaint it brand-blue ON a brand-blue fill — invisible. */
.v2x.atd .atd-claim-btn,
.v2x.atd .atd-claim-btn:hover,
.v2x.atd .atd-claim-btn:focus,
.v2x.atd .atd-claim-btn:active,
.v2x.atd .atd-claim-btn:visited{ color:#fff !important; text-decoration:none; }
.v2x.atd .atd-claim-btn-l{ display:inline-flex; align-items:center; gap:9px; min-width:0; }
.v2x.atd .atd-claim-btn-l span{ white-space:normal; }   /* never clip the label */
.v2x.atd .atd-claim-btn-l i{ flex:0 0 auto; font-size:.88rem; }
.v2x.atd .atd-claim-btn-go{
  flex:0 0 auto; font-size:.78rem; opacity:.85;
  transition:transform 320ms cubic-bezier(.16,1,.3,1), opacity 240ms ease;
}
/* Sheen — parked off-canvas; transition lives in :hover so it snaps back. */
.v2x.atd .atd-claim-btn::after{
  content:''; position:absolute; top:0; bottom:0; z-index:0;
  inset-inline-start:-60%; width:40%; pointer-events:none;
  background:linear-gradient(100deg, transparent, rgba(255,255,255,.42), transparent);
  transform:skewX(-18deg); opacity:0;
}
.v2x.atd .atd-claim-btn > *{ position:relative; z-index:1; }

.v2x.atd .atd-claim-foot{
  margin:10px 0 0; display:flex; align-items:center; gap:6px;
  color:var(--muted2); font-size:.76rem; line-height:1.45;
}
.v2x.atd .atd-claim-foot i{ font-size:.68rem; color:var(--accent); }

/* Owner-managed variant — green, no CTA. */
.v2x.atd .atd-claim.is-owned{ background:linear-gradient(150deg,#f4fdf8 0%,#fff 50%,#f2fbf7 100%); border-color:#c9ecdb; }
.v2x.atd .atd-claim.is-owned .atd-claim-ic{ background:linear-gradient(135deg,#22C55E,#0E7A55); box-shadow:0 5px 14px rgba(14,122,85,.30); }
.v2x.atd .atd-claim.is-owned .atd-claim-glow{ background:radial-gradient(circle, rgba(34,197,94,.20) 0%, rgba(34,197,94,0) 70%); }

@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-claim:hover{
    border-color:#b9d4f8; box-shadow:0 14px 32px rgba(32,96,192,.14); transform:translateY(-2px);
  }
  .v2x.atd .atd-claim:hover .atd-claim-glow{ opacity:1; transform:scale(1.18); }
  .v2x.atd .atd-claim:hover .atd-claim-ic{ transform:scale(1.06) rotate(-4deg); }
  .v2x.atd .atd-claim-btn:hover{
    transform:translateY(-2px); filter:saturate(1.06);
    box-shadow:0 14px 30px rgba(54,128,237,.40);
  }
  .v2x.atd .atd-claim-btn:hover::after{
    inset-inline-start:130%; opacity:1;
    transition:inset-inline-start 760ms cubic-bezier(.16,1,.3,1), opacity 220ms ease;
  }
  .v2x.atd .atd-claim-btn:hover .atd-claim-btn-go{ transform:translateX(4px); opacity:1; }
  .v2x.atd .atd-claim.is-owned:hover{ border-color:#a8e0c6; box-shadow:0 14px 32px rgba(14,122,85,.13); }
}
.v2x.atd .atd-claim-btn:active{ transform:translateY(0) scale(.985); }

body:not(.admin-shell) .v2x.atd .atd-claim-btn:focus-visible{
  outline:none; border-radius:12px;
  box-shadow:0 0 0 3px rgba(54,128,237,.9), 0 0 0 6px rgba(54,128,237,.24);
}

@media (max-width:575.98px){
  .v2x.atd .atd-claim-ic{ width:32px; height:32px; border-radius:10px; font-size:.84rem; }
  .v2x.atd .atd-claim-text{ font-size:.87rem; }
  .v2x.atd .atd-claim-btn{ padding:12px 14px; font-size:.87rem; }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-claim,.v2x.atd .atd-claim-glow,.v2x.atd .atd-claim-ic,
  .v2x.atd .atd-claim-btn,.v2x.atd .atd-claim-btn::after,.v2x.atd .atd-claim-btn-go{ transition:none !important; }
  .v2x.atd .atd-claim:hover,.v2x.atd .atd-claim-btn:hover{ transform:none; }
  .v2x.atd .atd-claim:hover .atd-claim-ic{ transform:none; }
  .v2x.atd .atd-claim-btn:hover::after{ opacity:0; }
}

/* Dark twins */
body.theme-dark .v2x.atd .atd-claim{
  background:linear-gradient(150deg,rgba(54,128,237,.10) 0%,var(--dk-surface-2,#17171B) 46%,rgba(54,128,237,.07) 100%);
  border-color:rgba(54,128,237,.34);
}
body.theme-dark .v2x.atd .atd-claim-glow{ background:radial-gradient(circle, rgba(54,128,237,.26) 0%, rgba(54,128,237,0) 70%); }
body.theme-dark .v2x.atd .atd-claim-foot i{ color:#7FB4F7; }
body.theme-dark .v2x.atd .atd-claim.is-owned{
  background:linear-gradient(150deg,rgba(34,197,94,.12) 0%,var(--dk-surface-2,#17171B) 50%,rgba(34,197,94,.07) 100%);
  border-color:rgba(34,197,94,.34);
}
body.theme-dark .v2x.atd .atd-claim.is-owned .atd-claim-glow{ background:radial-gradient(circle, rgba(34,197,94,.24) 0%, rgba(34,197,94,0) 70%); }
@media (hover:hover) and (pointer:fine){
  body.theme-dark .v2x.atd .atd-claim:hover{ border-color:rgba(54,128,237,.55); box-shadow:0 14px 32px rgba(0,0,0,.55); }
  body.theme-dark .v2x.atd .atd-claim.is-owned:hover{ border-color:rgba(34,197,94,.55); }
}

/* ==========================================================================
   1) Top action toolbar (Share + favorite, beside the breadcrumb)
   ========================================================================== */
.v2x.atd .atd-topbar-actions{ display:flex; align-items:center; justify-content:flex-end; gap:10px; flex-wrap:wrap; margin-bottom:14px; }
/* The -52px is a PULL-UP ONTO THE BREADCRUMB ROW, so it may only apply when
   there is a breadcrumb to pull up beside. It used to be unconditional, and
   /cheat-sheet/{slug} ships no breadcrumb at all — the Share pill rose 52px
   into whatever sat above it, which for a signed-in user with an unverified
   address is the email-verification banner. It overlapped its last 20px.

   `.page-wrapper` is the nearest ancestor that holds BOTH the breadcrumb and
   this toolbar on every layout that has one — `.page-content` does not, the
   two live in different containers on the tool page. Where :has() is missing
   the pull-up simply does not apply, which is the safe direction. */
@media (min-width:992px){
  .page-wrapper:has(.seo-breadcrumbs) .v2x.atd .atd-topbar-actions{ margin-top:-52px; margin-bottom:18px; }
}

/* Base pill. `overflow:hidden` clips the wash + sheen to the radius; the two
   pseudo-elements sit at z-index 0 and the icon/label are lifted to 1, which
   is why the sweep never paints over the text. Colour is deliberately split:
   SHARE is brand blue, FAVOURITE is rose — a heart is a universally red
   affordance and using brand blue for it reads as a second "share". */
.v2x.atd .atd-pillbtn{
  position:relative; overflow:hidden;
  display:inline-flex; align-items:center; justify-content:center; gap:9px;
  min-height:40px; padding:0 18px;
  background:#fff; border:1px solid var(--line-strong); border-radius:var(--r-pill);
  font-family:var(--font); font-size:.875rem; font-weight:600; letter-spacing:-.005em;
  color:var(--muted); cursor:pointer; white-space:nowrap;
  box-shadow:0 1px 2px rgba(15,23,42,.05);
  transition:color 220ms ease, border-color 220ms ease, background 220ms ease,
             box-shadow 300ms cubic-bezier(.16,1,.3,1),
             transform 300ms cubic-bezier(.16,1,.3,1);
}
.v2x.atd .atd-pillbtn > *{ position:relative; z-index:1; }
/* Wash — scales up out of the label, same motion as the mega row hover. */
.v2x.atd .atd-pillbtn::before{
  content:''; position:absolute; inset:0; z-index:0; border-radius:inherit;
  background:linear-gradient(135deg, rgba(54,128,237,.16), rgba(124,58,237,.10));
  opacity:0; transform:scale(.86);
  transition:opacity 260ms ease, transform 340ms cubic-bezier(.16,1,.3,1);
}

@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-pillbtn:hover{
    color:var(--accent-dark); border-color:rgba(54,128,237,.55); transform:translateY(-2px);
    box-shadow:0 8px 20px rgba(54,128,237,.20), 0 2px 6px rgba(15,23,42,.06);
  }
  .v2x.atd .atd-pillbtn:hover::before{ opacity:1; transform:scale(1); }
}
.v2x.atd .atd-pillbtn:active{ transform:translateY(0) scale(.975); }


/* Copied — set for 1.6s by atdShare(). Success is green on purpose: the site's
   --red/--danger tokens are remapped to brand blue elsewhere, so a blue
   confirmation would be indistinguishable from the resting state. */
.v2x.atd .atd-pillbtn.is-copied{
  color:#0E7A55; border-color:rgba(18,166,111,.5);
  background:linear-gradient(135deg,#ecfdf5,#d7f5e7);
  box-shadow:0 2px 10px rgba(18,166,111,.18);
}
.v2x.atd .atd-pillbtn.is-copied::before{ opacity:0; }

/* Busy, not dead — wire:loading.attr="disabled" covers the in-flight save. */
.v2x.atd .atd-pillbtn[disabled]{ opacity:.62; cursor:default; transform:none; box-shadow:none; }
.v2x.atd .atd-pillbtn[disabled]::before{ opacity:0; }

/* Focus. The site-wide reset is (0,3,2) and forces radius:6px — the body
   prefix lands these at (0,5,1) and the radius is restated. */
body:not(.admin-shell) .v2x.atd .atd-pillbtn:focus-visible{
  outline:none; border-radius:var(--r-pill);
  box-shadow:0 0 0 3px rgba(54,128,237,.9), 0 0 0 6px rgba(54,128,237,.24);
}

@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-pillbtn,.v2x.atd .atd-pillbtn .ic,
  .v2x.atd .atd-pillbtn::before,.v2x.atd .atd-pillbtn::after{ transition:none !important; }
  .v2x.atd .atd-pillbtn:hover{ transform:none; }
}

/* Dark twins. The shared dark block further down already gives .atd-pillbtn a
   #171922 panel; these carry the accents, which it does not. */
body.theme-dark .v2x.atd .atd-pillbtn{ box-shadow:none; }
@media (hover:hover) and (pointer:fine){
  body.theme-dark .v2x.atd .atd-pillbtn:hover{
    color:#9CC5F9; border-color:rgba(54,128,237,.55);
    box-shadow:0 8px 22px rgba(0,0,0,.5);
  }
}
body.theme-dark .v2x.atd .atd-pillbtn.is-copied{
  background:rgba(18,166,111,.18); border-color:rgba(18,166,111,.45);
  color:#6EE7B7; box-shadow:none;
}

/* ==========================================================================
   2) HERO
   ========================================================================== */
.v2x.atd .atd-hero{
  background:#fff;
  border:1px solid var(--line); border-radius:var(--r-hero);
  box-shadow:var(--sh-sm); padding:clamp(20px,3vw,36px);
}
.v2x.atd .atd-hero-grid{ align-items:center; }
/* The hero head, the logo tile and the letter plate were defined here before
   §HERO-X. That section restates every one of these declarations at the same
   (0,2,0) specificity further down the file, so source order has been handing
   it the win ever since and this block painted nothing. Removed 2026-08-13
   while resizing the mobile logo — it is what a grep for `atd-logo-tile`
   finds first, so a size change made here would have looked correct and
   changed nothing on screen. §HERO-X is the only definition now. */
/* `.atd-title-row` and `.atd-h1` were defined here too, before §HERO-X. Both
   are restated there at the same (0,2,0) specificity — including the `!important`
   on the H1 clamp — so source order handed §HERO-X every declaration and this
   pair never painted. Removed 2026-08-13 while retuning the mobile heading
   sizes: leaving a dead `.atd-h1{font-size:…}` ABOVE the live one is how the
   next person edits the wrong number. */
.v2x.atd .atd-badge-featured,
.v2x.atd .atd-badge-trending,
.v2x.atd .atd-badge-certificate,
.v2x.atd .atd-badge-editors,
.v2x.atd .atd-badge-live,
.v2x.atd .atd-badge-verified{
  display:inline-flex; align-items:center; gap:6px;
  font-family:var(--font); font-size:.78rem; font-weight:600;
  border-radius:var(--r-pill); padding:5px 12px;
}
.v2x.atd .atd-badge-featured{ background:linear-gradient(135deg,#fff4d6,#ffe7a8); border:1px solid rgba(245,158,11,.45); color:#8a5a06; }
.v2x.atd .atd-badge-featured i,.v2x.atd .atd-badge-featured .lcd{ color:#F59E0B; }
.v2x.atd .atd-badge-verified{ background:#eaf4ff; border:1px solid #cfe6ff; color:#1d9bf0; }
.v2x.atd .atd-badge-verified svg{ width:15px; height:15px; display:inline-block; vertical-align:-3px; }
/* `.atd-byline` lived here. The hero rebuild (§HERO-PRO) replaced it with the
   .atd-meta-row strip — category pill + owner link + trust badges — so the rules
   were removed rather than left to look editable. Same for the rating row below. */
.v2x.atd .atd-desc{ color:var(--muted); max-width:62ch; margin:0 0 18px; font-size:1.05rem; line-height:1.75; }

/* Capability chips */
.v2x.atd .atd-chips{ display:flex; flex-wrap:wrap; gap:9px; margin-bottom:20px; }
.v2x.atd .atd-chip{
  display:inline-flex; align-items:center; gap:7px;
  font-family:var(--font); font-size:.85rem; font-weight:500; border-radius:var(--r-pill);
  padding:7px 14px; border:1px solid;
}
.v2x.atd .atd-chip i{ font-size:.76rem; }
.v2x.atd .atd-chip-green { color:var(--green-ink); border-color:rgba(34,197,94,.22); background:#e7f8ee; }
.v2x.atd .atd-chip-blue  { color:var(--accent-dark); border-color:#dbe8fd; background:var(--accent-soft); }
.v2x.atd .atd-chip-violet{ color:#6d28d9; border-color:rgba(139,92,246,.22); background:#f0ebfd; }
.v2x.atd .atd-chip-amber { color:#b45309; border-color:rgba(245,158,11,.22); background:#fdf2dd; }

/* Stars. `.atd-rating-row`, `-num`, `-sep` and `.atd-visits` were removed with
   the inline rating line they styled — the figures now live in the §HERO-PRO
   stat rail. `.v2-stars` stays: the rail's rating cell still renders it, and so
   do the shared review partials. */
.v2x.atd .v2-stars{ color:var(--gold); letter-spacing:2px; white-space:nowrap; }

/* Hero CTAs */
.v2x.atd .atd-cta-row{ display:flex; flex-wrap:wrap; gap:13px; align-items:flex-start; }
.v2x.atd .atd-cta-col{ display:flex; flex-direction:column; align-items:center; gap:7px; }
.v2x.atd .atd-nocard{ font-size:.8rem; color:var(--muted2); }
.v2x.atd .atd-cta-row .atd-btn{ padding:14px 26px; font-size:1rem; }

/* ==========================================================================
   §GAL) Hero media gallery — stage · branded video facade · thumb rail

   Replaces the old flat slider. Three things drove the rebuild:
   · The YouTube iframe painted its OWN chrome (red button, title bar, the
     "Watch on YouTube" pill) over the design and none of it is styleable.
     Videos are now a facade — poster + our play control — and the real
     iframe is injected on click, so first paint is fully ours.
   · Every slide is a 16:9 window (`aspect-ratio`), so there is ONE ratio at
     every breakpoint and no layout shift as media loads.
   · Chips and captions sit on a painted scrim, never on bare artwork, so
     text stays readable over any screenshot.
   Colour comes from the shared --accent ramp; dark mode is token-driven
   plus the explicit twins at the end of this block.
   ========================================================================== */

/* ── Stage ─────────────────────────────────────────────────────────────── */
.v2x.atd .atd-gal-main{
  position:relative;
  border:1px solid var(--line); border-radius:16px; overflow:hidden;
  background:linear-gradient(140deg,#eef4fe,#f6f9ff 55%,#eaf1fd);
  box-shadow:var(--sh-md);
  transition:box-shadow 300ms cubic-bezier(.16,1,.3,1), border-color 260ms ease;
}
.v2x.atd .atd-gal-main:hover{ box-shadow:var(--sh-lg); border-color:#cddffb; }
.v2x.atd .atd-gal-main .swiper-slide{
  display:block; position:relative; aspect-ratio:16/9; overflow:hidden; background:#0c1220;
}
@supports not (aspect-ratio:16/9){
  .v2x.atd .atd-gal-main .swiper-slide{ height:clamp(210px,26vw,330px); }
}
/* Cover-image-only fallback: a tool with no videos AND no screenshots renders
   `<div class="atd-gal-main"><img></div>` with no .swiper-slide at all, so the
   bare <img> needs the same 16:9 window or it lays out at its natural size.
   32 of the 33 directory tools currently take this path — it is the common
   case here, not an edge case. */
.v2x.atd .atd-gal-main > img{
  display:block; width:100%; height:auto; aspect-ratio:16/9; object-fit:cover;
}
@supports not (aspect-ratio:16/9){
  .v2x.atd .atd-gal-main > img{ height:clamp(210px,26vw,330px); }
}

/* ── Media layer (shared by video facade + screenshot slides) ──────────── */
.v2x.atd .atd-media{ position:absolute; inset:0; display:block; text-decoration:none; cursor:pointer; }
.v2x.atd .atd-media-img{
  width:100%; height:100%; object-fit:cover; display:block;
  transition:transform 560ms cubic-bezier(.16,1,.3,1);
}
.v2x.atd .atd-media-ph{ position:absolute; inset:0; display:block; background:linear-gradient(135deg,#1a1d27,#2a2f3e); }
/* Scrim — top lane for the chips, bottom lane for the caption. Always
   painted: this is what guarantees the text never lands on bare artwork. */
.v2x.atd .atd-media-veil{
  position:absolute; inset:0; pointer-events:none; transition:opacity 320ms ease;
  background:
    linear-gradient(180deg, rgba(8,12,22,.50) 0%, rgba(8,12,22,.14) 24%, rgba(8,12,22,0) 44%),
    linear-gradient(0deg,   rgba(8,12,22,.82) 0%, rgba(8,12,22,.36) 28%, rgba(8,12,22,0) 60%);
}

/* ── Glass chips: media kind (top-left) + slide counter (top-right) ────── */
.v2x.atd .atd-media-kind,
.v2x.atd .atd-gal-count{
  position:absolute; top:12px; z-index:4;
  display:inline-flex; align-items:center; gap:6px;
  padding:6px 11px; border-radius:var(--r-pill);
  font-family:var(--font); font-size:.72rem; font-weight:700; letter-spacing:.02em;
  color:#fff !important; background:rgba(10,14,24,.58);
  border:1px solid rgba(255,255,255,.22);
  -webkit-backdrop-filter:blur(10px) saturate(1.3); backdrop-filter:blur(10px) saturate(1.3);
}
.v2x.atd .atd-media-kind{ left:12px; }
.v2x.atd .atd-media-kind i{ font-size:.6rem; }
.v2x.atd .atd-gal-count{ right:12px; font-variant-numeric:tabular-nums; }
.v2x.atd .atd-gal-count b{ color:#fff; font-weight:800; }

/* ── Caption — always visible, clamped to two lines ────────────────────── */
.v2x.atd .atd-media-cap{
  position:absolute; left:14px; right:14px; bottom:13px; z-index:3;
  color:#fff !important; font-family:var(--font);
  font-size:.92rem; font-weight:600; line-height:1.35; letter-spacing:-.01em;
  text-shadow:0 1px 3px rgba(0,0,0,.6);
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
}
/* Screenshot slides carry a View pill in the same lane — reserve its width. */
.v2x.atd .atd-shot-slide .atd-media-cap{ padding-inline-end:104px; }

/* ── Play control — brand gradient + halo that expands on hover ────────── */
.v2x.atd .atd-play{
  position:absolute; top:50%; left:50%; z-index:4;
  width:74px; height:74px; margin:-37px 0 0 -37px;
  display:flex; align-items:center; justify-content:center; border-radius:50%;
  background:linear-gradient(135deg,#4C8DF2 0%,#3680ED 52%,#2060C0 100%);
  box-shadow:0 10px 30px rgba(32,96,192,.46), inset 0 0 0 1px rgba(255,255,255,.30);
  color:#fff; font-size:1.4rem; padding-left:5px;
  transition:transform 340ms cubic-bezier(.16,1,.3,1), box-shadow 340ms ease;
}
.v2x.atd .atd-play::after{
  content:''; position:absolute; inset:-10px; border-radius:50%;
  border:2px solid rgba(255,255,255,.55); opacity:.5;
  transition:transform 460ms cubic-bezier(.16,1,.3,1), opacity 460ms ease;
}

/* ── View pill on screenshot slides ────────────────────────────────────── */
.v2x.atd .atd-media-zoom{
  position:absolute; right:14px; bottom:13px; z-index:4;
  display:inline-flex; align-items:center; gap:7px;
  padding:8px 14px; border-radius:var(--r-pill);
  font-family:var(--font); font-size:.78rem; font-weight:700;
  color:#0F0F12 !important; background:rgba(255,255,255,.95);
  border:1px solid rgba(255,255,255,.7);
  box-shadow:0 6px 18px rgba(8,12,22,.30);
  opacity:0; transform:translateY(9px) scale(.96);
  transition:opacity 260ms ease, transform 300ms cubic-bezier(.16,1,.3,1), background 200ms ease;
}
.v2x.atd .atd-media-zoom i{ font-size:.7rem; color:var(--accent); }

/* ── Prev / next ───────────────────────────────────────────────────────── */
.v2x.atd .atd-gal-nav{
  position:absolute; top:50%; z-index:5;
  width:38px; height:38px; border-radius:50%; padding:0;
  display:flex; align-items:center; justify-content:center;
  border:1px solid rgba(255,255,255,.28); background:rgba(10,14,24,.52);
  color:#fff; cursor:pointer; font-size:.8rem;
  -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px);
  opacity:0; transform:translateY(-50%) scale(.9);
  transition:opacity 240ms ease, transform 260ms cubic-bezier(.16,1,.3,1), background 200ms ease, border-color 200ms ease;
}
.v2x.atd .atd-gal-nav.is-prev{ left:10px; }
.v2x.atd .atd-gal-nav.is-next{ right:10px; }
.v2x.atd .atd-gal-nav:hover{ background:var(--accent); border-color:rgba(255,255,255,.5); }
.v2x.atd .atd-gal-nav.swiper-button-disabled{ opacity:0 !important; pointer-events:none; }

/* ── Hover choreography — fine pointers only, so a tap never sticks ────── */
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-media:hover .atd-media-img{ transform:scale(1.055); }
  .v2x.atd .atd-media:hover .atd-media-veil{ opacity:1; }
  .v2x.atd .atd-media:hover .atd-media-zoom{ opacity:1; transform:translateY(0) scale(1); }
  .v2x.atd .atd-media-zoom:hover{ background:#fff; }
  .v2x.atd .atd-media:hover .atd-play{
    transform:scale(1.09);
    box-shadow:0 16px 40px rgba(32,96,192,.58), inset 0 0 0 1px rgba(255,255,255,.44);
  }
  .v2x.atd .atd-media:hover .atd-play::after{ transform:scale(1.18); opacity:0; }
  .v2x.atd .atd-gal-main:hover .atd-gal-nav{ opacity:1; transform:translateY(-50%) scale(1); }
}
/* Touch has no hover state — the affordances must be visible at rest. */
@media (hover:none), (pointer:coarse){
  .v2x.atd .atd-media-zoom{ opacity:1; transform:none; }
  .v2x.atd .atd-gal-nav{ opacity:1; transform:translateY(-50%); }
}

/* ── Focus. The site-wide reset is (0,3,2) and also forces radius:6px, so
      these need the body prefix AND an explicit radius. ─────────────────── */
body:not(.admin-shell) .v2x.atd .atd-media:focus-visible,
body:not(.admin-shell) .v2x.atd .atd-gal-nav:focus-visible,
body:not(.admin-shell) .v2x.atd .atd-gal-thumbs .swiper-slide:focus-visible{
  outline:none; border-radius:inherit;
  box-shadow:0 0 0 3px rgba(54,128,237,.9), 0 0 0 6px rgba(54,128,237,.26);
}

/* ── Thumbnail rail ────────────────────────────────────────────────────── */
.v2x.atd .atd-gal-thumbs{ margin-top:12px; }
.v2x.atd .atd-gal-thumbs .swiper-slide{
  position:relative; aspect-ratio:16/10; height:auto;
  border-radius:11px; overflow:hidden;
  border:1px solid var(--line); cursor:pointer; background:#fff;
  opacity:.68; filter:saturate(.88);
  transition:opacity 240ms ease, transform 300ms cubic-bezier(.16,1,.3,1),
             border-color 240ms ease, box-shadow 300ms ease, filter 240ms ease;
}
.v2x.atd .atd-gal-thumbs img{ width:100%; height:100%; object-fit:cover; display:block; }
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-gal-thumbs .swiper-slide:hover{
    opacity:1; filter:none; transform:translateY(-3px);
    border-color:var(--accent); box-shadow:0 8px 18px rgba(15,23,42,.15);
  }
}
.v2x.atd .atd-gal-thumbs .swiper-slide-thumb-active{
  opacity:1; filter:none; border-color:var(--accent);
  box-shadow:0 0 0 3px rgba(54,128,237,.22), 0 6px 16px rgba(32,96,192,.20);
}
/* Accent bar that wipes in under the active thumb. */
.v2x.atd .atd-thumb-ring{
  position:absolute; left:0; right:0; bottom:0; height:3px; z-index:2;
  background:linear-gradient(90deg,#4C8DF2,#3680ED,#2060C0);
  transform:scaleX(0); transform-origin:50% 100%;
  transition:transform 360ms cubic-bezier(.16,1,.3,1);
}
.v2x.atd .atd-gal-thumbs .swiper-slide-thumb-active .atd-thumb-ring{ transform:scaleX(1); }
.v2x.atd .atd-thumb-more{
  position:absolute; inset:0; z-index:3;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:1px;
  background:rgba(8,12,22,.66);
  -webkit-backdrop-filter:blur(3px); backdrop-filter:blur(3px);
  color:#fff !important; font-family:var(--font);
  font-size:.6rem; font-weight:600; letter-spacing:.05em; text-transform:uppercase;
}
.v2x.atd .atd-thumb-more b{ font-size:.95rem; font-weight:800; line-height:1.05; color:#fff; }

/* ── Responsive ────────────────────────────────────────────────────────── */
@media (max-width:991.98px){ .v2x.atd .atd-gallery{ margin-top:20px; } }
@media (max-width:575.98px){
  .v2x.atd .atd-play{ width:58px; height:58px; margin:-29px 0 0 -29px; font-size:1.08rem; }
  .v2x.atd .atd-media-kind,.v2x.atd .atd-gal-count{ font-size:.66rem; padding:5px 9px; top:10px; }
  .v2x.atd .atd-media-kind{ left:10px; } .v2x.atd .atd-gal-count{ right:10px; }
  /* The caption is the content; the pill is only an affordance, and tapping
     the slide already opens the lightbox. Caption wins the lane. */
  .v2x.atd .atd-media-zoom{ display:none; }
  .v2x.atd .atd-shot-slide .atd-media-cap{ padding-inline-end:0; }
  .v2x.atd .atd-media-cap{ font-size:.82rem; left:11px; right:11px; bottom:11px; }
  .v2x.atd .atd-gal-nav{ width:32px; height:32px; font-size:.72rem; }
  .v2x.atd .atd-gal-thumbs{ margin-top:9px; }
  .v2x.atd .atd-gal-thumbs .swiper-slide{ border-radius:9px; }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-media-img,.v2x.atd .atd-play,.v2x.atd .atd-play::after,
  .v2x.atd .atd-media-zoom,.v2x.atd .atd-gal-nav,.v2x.atd .atd-media-veil,
  .v2x.atd .atd-gal-thumbs .swiper-slide,.v2x.atd .atd-thumb-ring{ transition:none !important; }
  .v2x.atd .atd-media:hover .atd-media-img{ transform:none; }
  .v2x.atd .atd-media:hover .atd-play{ transform:none; }
}

/* ── Dark twins. `body.theme-dark …` is (0,4,1) so it outranks the base
      rules above regardless of source order. ───────────────────────────── */
body.theme-dark .v2x.atd .atd-gal-main:hover{ border-color:var(--dk-line-solid-2,#3A3A42); }
body.theme-dark .v2x.atd .atd-media-zoom{
  background:rgba(29,29,34,.95); color:var(--dk-text,#F4F5F7) !important;
  border-color:var(--dk-line-strong,rgba(255,255,255,.16)); box-shadow:0 6px 18px rgba(0,0,0,.5);
}
body.theme-dark .v2x.atd .atd-media-zoom:hover{ background:#1E2230; }
body.theme-dark .v2x.atd .atd-media-zoom i{ color:#7FB4F7; }
body.theme-dark .v2x.atd .atd-media-kind,
body.theme-dark .v2x.atd .atd-gal-count,
body.theme-dark .v2x.atd .atd-gal-nav{ background:rgba(6,9,16,.66); border-color:var(--dk-line-strong,rgba(255,255,255,.16)); }
body.theme-dark .v2x.atd .atd-gal-thumbs .swiper-slide{ border-color:var(--line); }
.v2x.atd .atd-noshot{
  min-height:240px; background:var(--accent-soft); border-color:#dbe8fd;
  display:flex; align-items:center; justify-content:center;
}

/* ==========================================================================
   3) §TABS) Section rail — "On this page"

   Rebuilt on the design language of the footer's Popular Categories card
   (`.aitsft-qblock` in components/public/footer.blade.php), which is the
   reference this rail was asked to match: a rounded card with a tinted top
   wash and 999px chips that light up under the pointer.

   THE HOVER IS A ROTATING LIGHT. Rest / hover / active are three visibly
   different things, because a rail has to tell "where I am" apart from
   "where I'd go", which a card of equal chips never has to do:

     rest    quiet raised-glass chip, muted ink, hairline edge
     hover   tinted-glass fill + a comet of light ORBITING the chip edge
     active  saturated brand fill (painted by the sliding thumb) + white ink

   The orbit is one recipe used at three scales, so the whole rail reads as
   one system: the RAIL card orbits slowly (7.5s) the moment the pointer is
   anywhere near it, a CHIP orbits fast (2.9s) when it is the actual target,
   and the ARROWS orbit at 2.4s. Two speeds at once is deliberate — the slow
   ambient sweep on the container and the crisp spark on the target read as
   depth rather than noise — and the rail's own orbit DIMS to 34% while a
   chip is hovered, so the thing under the pointer always wins.

   Three things it deliberately does NOT do:

   · Lift the whole card on hover. This is a NAVIGATION rail — lifting it
     while the pointer is already aimed at a tab drags the target out from
     under the cursor. The rail answers hover with LIGHT; only chips move.

   · Paint a hover chip white-on-#60A4F5. #60A4F5 under white is 2.59:1 — an
     INK token used as a FILL, the exact inversion that
     [[dark-mode-contrast-layer]] exists to prevent. Hover is tinted glass
     carrying #1B54A8 ink (5.7:1 measured on the composite); the saturated
     fill is kept for the ACTIVE tab on the measured ramp (#2F72DA = 4.63:1
     under white).

   · Truncate a label, at any width. Labels are the payload; the rail sheds
     padding, then gap, then the decorative icons (below 400px) and finally
     just scrolls. Nothing is ever half a word.

   Count badges (Reviews 2K / Alternatives 5 / FAQ 12) were removed from the
   markup on request; the counts still decide WHICH tabs render. Nothing named
   `.atd-tab-cnt` exists any more.

   OVERFLOW is signposted, not hidden: the scroller masks its own edges (from
   the `can-l` / `can-r` classes the script sets off the real scroll position),
   arrows appear on precise pointers, and the active tab is scrolled into view.
   The mask replaced a pair of `#fff` gradient fades — those only matched a
   plain white card, so the tinted wash behind them showed as a pale seam, and
   each fade needed a hand-written dark twin. A mask is colour-blind: it fades
   whatever the card happens to be.

   STICKY on desktop and tablet (2026-08-13). It used to be deliberately NOT
   sticky — the shared kit's `.v2x .v2-tabs` sets position:sticky and the
   (0,3,0) rule below overrides it — because a top:0 rail slid under the
   site header. The header is sticky itself now, so the rail pins beneath it
   instead. The offset, the breakpoints and why phones are excluded are all
   in §TABS-STICK, further down this section. `.v2-tabs` stays position:
   relative (it is the thumb's offsetLeft origin) — the sticky is on the
   OUTER `.atd-tabsbar`, which is the card you actually see pinned.
   ========================================================================== */

/* The orbit angle is a REGISTERED custom property, and registration is the
   whole trick: an UNregistered `--x` animates DISCRETELY — it flips at the
   50% mark — so the comet would teleport rather than travel. Registering it
   as an <angle> makes it interpolable.

   It also shapes the fallback. Every rule that animates it also DECLARES
   `--atd-spin:0deg` on the same pseudo, so a browser that never learned
   the at-rule still resolves the conic and paints a static gradient edge
   instead of dropping the background entirely. Nothing vanishes; it stops
   moving. `inherits:false` is required — the value has to be per-pseudo, or
   one animation would drive every ring on the page in lockstep. */
@property --atd-spin{ syntax:"<angle>"; inherits:false; initial-value:0deg; }
@keyframes atd-orbit{ to{ --atd-spin:360deg; } }

/* ══════════════════════════════════════════════════════════════════════════
   §TABS-STICK) The rail pins BELOW the sticky site header, clear of it
                — desktop + tablet, phones excluded

   ⚠️ THE SECTION BANNER ABOVE USED TO SAY "NOT sticky, deliberately". That was
   correct while the site header was NOT sticky: a rail pinned at top:0 slid
   straight underneath it and disappeared. **The header became sticky on
   2026-08-13** (`.aitshd[data-sticky="1"]`, z-index 60), so the rail pins
   BELOW it instead of being disabled. The offset has to be the header BAR's
   height at the moment it is pinned.

   That height is not a constant and cannot be hard-coded:
     · `--hd-h-base` steps 76 -> 68 -> 62px across breakpoints,
     · the bar shaves 6px more in its scrolled state (`[data-scrolled="1"]`),
       which it enters at just 24px of scroll — long before this rail arrives,
     · and `--hd-h` is declared ON `.aitshd`, a different subtree, so it does
       NOT inherit down here.
   `--atd-stick` is measured from the live element instead and kept in sync by
   a ResizeObserver — the same measure-don't-guess call the header makes for
   its own `--hd-ann-h`. It falls back to 0px, so a JS-less render still pins,
   just flush to the viewport top.

   z-index 20: over the page, under the header's 60. Anything >= 60 would put
   the rail on top of the site nav and its mega panels.

   ⚠️ THE STICKY WORKS ONLY BECAUSE THE ANCESTOR CHAIN ALLOWS IT.
   `body{overflow-x:hidden}` in custom.ltr.css does NOT break it: with `html`'s
   overflow left visible, the body's value is propagated to the VIEWPORT and
   body's own used value becomes visible, so body never becomes a scroll
   container. `.page` uses `overflow-x:clip` rather than `hidden` for the same
   reason. If either is ever changed to `hidden` on an element that is NOT the
   body, this rail — and the site header with it — silently stops pinning.

   Phones are excluded on purpose: below 768px the rail is a full-width
   horizontal scroller and pinning it would spend ~64px of a short viewport on
   navigation that is already one thumb-scroll away.

   ⚠️ THIS IS THE ONE DEFINITION, FOR ALL THREE PAGES. It lived at
   `.v2x.atd.cmp` in company/cmp-styles first (the company page got sticky
   before the other two) and was moved up here on 2026-08-13 when the tool and
   AI-model pages were asked for the same behaviour. Restating it per page
   would have left three copies of one surface to keep in step — the trap that
   `--card`/`--surface` and the hero already taught. Each page's script sets
   `--atd-stick` / `--atd-rail-h` with its own measurements.
   ══════════════════════════════════════════════════════════════════════════ */
@media (min-width:768px){
  /* CLEARANCE (2026-08-13, second pass). `top` was the header bar's measured
     height and nothing else, which welded the rail to the header's underside:
     two stacked bars reading as one 130px slab. It now clears the header by
     `--atd-stick-gap` as well.

     The gap is a REAL gap — the page scrolls through it. That is deliberate:
     it is what makes the pinned rail read as a floating card (its own radius,
     border and cast shadow all become legible again) instead of a second
     header bar. Painting the strip opaque would give back exactly the slab
     this change removes. Nothing is lost behind it: the rail's own surface is
     opaque (#fff / #171922 under the tint, see §TABS), so content passes
     under the card cleanly and only crosses the thin slot above it.

     It is a TOKEN, not a literal, because three figures have to agree: this
     `top`, the anchor `scroll-margin-top` below, and the scroll-spy's
     headroom() — which reads this very property back off the page element
     with getComputedStyle rather than keeping its own copy.

     ⚠️ Declared INSIDE this media query on purpose. Below 768px the rail is
     not pinned; the property then resolves to "" and the script's parseFloat
     lands on its 0 fallback, so the phone breakpoint needs no second rule and
     there is no third figure to keep in step. */
  .v2x.atd{ --atd-stick-gap:14px; }

  /* ⚠️⚠️ `.atd-tabsbar` IS DOUBLED, AND THAT IS THE WHOLE FIX. ⚠️⚠️
     This block shipped on 2026-08-13 as a plain `.v2x.atd .atd-tabsbar` and
     the rail never pinned once. The base card rule ~30 lines below declares
     `position:relative` (it has to — ::before is the orbit ring and ::after
     the shine bar, both absolutely positioned against this box) at the SAME
     (0,3,0) specificity, and **@media adds no specificity at all**. Equal
     weight, so the LATER declaration won: `relative` overwrote `sticky`
     silently, in a file where the two rules are far enough apart to read as
     unrelated. Everything downstream — the measured offsets, the scroll-spy
     headroom, the `.is-stuck` shadow — was correct and simply never fired.

     Repeating the class lifts this to (0,4,0) so it wins on WEIGHT rather
     than on position in the file. Deliberately not `.atd-tabsbar.v2-section`
     (that co-class is markup the rail could lose) and deliberately not
     `!important` (which would also beat the breakpoint overrides below it).
     `top` and `z-index` ride along in the same rule; only `position` was
     ever contested. */
  .v2x.atd .atd-tabsbar.atd-tabsbar{
    position:sticky; top:calc(var(--atd-stick, 0px) + var(--atd-stick-gap, 14px)); z-index:20;
  }
  /* Jump targets must clear BOTH pinned bars. This is the no-JS path — the
     scroll-spy computes the same figure at runtime for its own scrollTo.
     `[id]` matters: the rail itself carries `.v2-section` and must not be
     handed a scroll margin. */
  .v2x.atd .v2-section[id]{
    scroll-margin-top:calc(var(--atd-stick, 0px) + var(--atd-stick-gap, 14px) + var(--atd-rail-h, 74px) + 18px);
  }
  /* Pinned, the rail has page content sliding underneath it, so it earns a
     deeper cast shadow to separate the two planes. The inner top hairline and
     the contact shadow are RESTATED rather than dropped: box-shadow is a
     single property and naming only the new layer would delete the other two.
     The rest of §TABS — wash, border, radius, orbit ring — is untouched. */
  .v2x.atd .atd-tabsbar.is-stuck{
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,.75),
      0 1px 2px rgba(15,23,42,.04),
      0 16px 34px -16px rgba(15,23,42,.28);
  }
  body.theme-dark .v2x.atd .atd-tabsbar.is-stuck{
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,.05),
      0 1px 2px rgba(0,0,0,.45),
      0 18px 38px -18px rgba(0,0,0,.85);
  }

  /* Tablet spends the gap more carefully. The header bar is 62-68px there on
     a viewport that is often 800px tall in landscape, and the rail already
     costs ~64px of it; 14px of clearance that reads as generous at 1440 reads
     as a hole at 1024. Nested @media is plain CSS (conditional group rules
     nest) and keeps the token's every value in one block. */
  @media (max-width:1279.98px){ .v2x.atd{ --atd-stick-gap:11px; } }
}

.v2x.atd .atd-tabsbar{
  --atd-qc:#3680ED;                  /* shine bar, brand */
  --atd-qc2:#60A4F5;                 /* shine bar, brand light */
  --atd-qtint:rgba(54,128,237,.07);  /* top wash */
  --atd-tab-r:999px;
  --atd-r:20px;                      /* card radius — the orbit ring reads it */
  --atd-gut:8px;                     /* scroller inset — the room ring glow gets */
  --atd-fade:56px;                   /* edge-mask length */
  --atd-ring:1.6px;                  /* comet thickness on a chip */
  --atd-ring-lg:1.5px;               /* …and on the card */
  --atd-orbit:2.9s;                  /* chip orbit period */
  --atd-orbit-lg:7.5s;               /* card orbit — slower reads as bigger */
  /* isolate: the ring, the mask, the thumb and the arrows all carry z-index.
     A local stacking context keeps those indices from competing with the
     page, and keeps the chips' own negative-z ring layers contained. */
  position:relative; isolation:isolate; display:flex; align-items:center; gap:10px;
  padding:5px 10px; border:1px solid var(--line); border-radius:var(--atd-r);
  /* The wash is a background LAYER rather than a pseudo-element because both
     pseudos are spoken for — ::before is the orbit ring, ::after the shine
     bar. The stop is a PERCENTAGE, not the reference card's 100px: this rail
     is only ~68px tall, so a px stop meant for a 300px card never resolved
     inside it and left a residual tint on the bottom edge — and it would need
     re-tuning at every breakpoint the rail shrinks at. */
  background:
    linear-gradient(180deg, var(--atd-qtint) 0%, rgba(54,128,237,0) 72%) no-repeat,
    #fff;
  /* Three layers, as on the reference card: a hairline of light along the top
     inner edge so the card catches the page light, a contact shadow to seat
     it, and a wide soft one for lift. */
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.75),
    0 1px 2px rgba(15,23,42,.04),
    0 10px 28px -14px rgba(15,23,42,.18);
  transition:border-color .3s ease, box-shadow .3s ease;
}
body.theme-dark .v2x.atd .atd-tabsbar{
  --atd-qtint:rgba(54,128,237,.11);
  background:
    linear-gradient(180deg, var(--atd-qtint) 0%, rgba(54,128,237,0) 72%) no-repeat,
    var(--dk-surface-2,#17171B);
  border-color:var(--dk-line-solid,#2C2C31);
  /* A 75%-white inner hairline is a lit edge on a white card and a scratch on
     a dark one; the ink shadow simply does not register on near-black. */
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.05),
    0 1px 2px rgba(0,0,0,.45),
    0 14px 32px -18px rgba(0,0,0,.85);
}

/* Shine bar — lights the top edge on hover or on keyboard focus anywhere
   inside the rail. `top:-1px` so it sits ON the border, not below it. This is
   also the ORBIT'S FALLBACK: where mask-composite is missing the ring never
   paints, and this is the light the card answers hover with instead. Where
   the ring does paint, the block further down steps this back to 45% so two
   lights do not compete for the same top edge. */
.v2x.atd .atd-tabsbar::after{
  content:""; position:absolute; left:26px; right:26px; top:-1px; height:2px; z-index:4;
  border-radius:0 0 3px 3px; pointer-events:none;
  background:linear-gradient(90deg, rgba(54,128,237,0), var(--atd-qc), var(--atd-qc2), rgba(96,164,245,0));
  opacity:0; transform:translateY(-3px);
  transition:opacity .34s ease, transform .34s cubic-bezier(.16,1,.3,1);
}
.v2x.atd .atd-tabsbar:focus-within::after{ opacity:1; transform:translateY(0); }

/* The rail carried a lead group here — the reference card's gradient tile plus
   an "On this page" label, behind a hairline divider — removed on request.
   `--atd-qc2` outlives it: the shine bar above still uses that stop. */

/* ── Scroller ──────────────────────────────────────────────────────────── */
.v2x.atd .v2-tabs{
  position:relative;                 /* offsetLeft origin for the thumb */
  z-index:1;
  display:flex; align-items:center; gap:8px; flex:1 1 auto; min-width:0;
  overflow-x:auto; overflow-y:hidden; scrollbar-width:none;
  -webkit-overflow-scrolling:touch; scroll-behavior:smooth;
  background:none; border:0; border-radius:0;
  /* Vertical padding, not zero: `overflow-y:hidden` clips at the padding box,
     so without it the chips' lift, their ring bloom and the thumb's glow
     would all be sliced off flat along their own bottom edge. 8px is sized to
     the bloom (a 6px drop-shadow plus the 2px hover lift). The HORIZONTAL
     padding stays 0 — the thumb is positioned from `a.offsetLeft`, and a left
     inset would have to be mirrored there by hand. */
  padding:var(--atd-gut) 0;
  -webkit-backdrop-filter:none; backdrop-filter:none;
  box-shadow:none;
}
.v2x.atd .v2-tabs::-webkit-scrollbar{ display:none; }
@media (prefers-reduced-motion:reduce){ .v2x.atd .v2-tabs{ scroll-behavior:auto; } }

/* ── Sliding thumb ─────────────────────────────────────────────────────── */
.v2x.atd .atd-tabs-thumb{
  position:absolute; top:var(--atd-gut); bottom:var(--atd-gut); left:0; width:0; z-index:0;
  border-radius:var(--atd-tab-r); pointer-events:none; opacity:0;
  background:linear-gradient(135deg,#2F72DA 0%,#2261C4 55%,#1A4FA6 100%);
  /* No drop shadow — removed on request. The inset stays: it is a highlight
     along the top edge, not a glow underneath. */
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22);
  transition:transform .46s cubic-bezier(.34,1.28,.64,1), width .46s cubic-bezier(.34,1.28,.64,1), opacity .22s ease;
}
.v2x.atd .v2-tabs.has-thumb .atd-tabs-thumb{ opacity:1; }
/* The thumb carried a rotating interior sheen here. It was cut on measurement,
   not taste: white ink on #2F72DA — the light end of this very gradient — is
   4.63:1, which leaves no headroom at all, and a wash of just 5% white takes
   it to 4.25:1. The active tab gets its light from its own comet ring instead,
   which rides the pill's EDGE and never crosses the label. */
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-tabs-thumb{ transition:opacity .2s ease; }
}

/* ── Tabs — the reference card's chips ─────────────────────────────────── */
.v2x.atd .v2-tabs a{
  position:relative; z-index:1; flex:0 0 auto;
  display:inline-flex; align-items:center; gap:8px;
  padding:10px 17px; min-height:40px; border:1px solid #E4EAF4; border-radius:var(--atd-tab-r);
  /* Raised glass, not a flat fill: on a white card a flat #f6f8fc chip has
     almost no edge of its own and the row reads as text, not as controls. */
  background:linear-gradient(180deg,#FFFFFF 0%,#F3F7FD 100%);
  box-shadow:0 1px 1px rgba(15,23,42,.03);
  color:var(--muted);
  font-family:var(--font); font-size:.92rem; font-weight:700; line-height:1.35;
  letter-spacing:-.005em; white-space:nowrap; text-decoration:none;
  transition:color .22s ease, background .26s ease, border-color .26s ease,
             transform .3s cubic-bezier(.16,1,.3,1), box-shadow .3s ease;
}
/* Hover tint as an overlay rather than a background swap, so the fill can be
   a GRADIENT and still cross-fade. z-index:-1 inside the chip's own stacking
   context paints it over the chip's background and under its text — which is
   also where the orbit ring lives, one layer later. */
.v2x.atd .v2-tabs a::before{
  content:""; position:absolute; inset:0; z-index:-1; border-radius:inherit;
  background:linear-gradient(180deg, rgba(54,128,237,.10) 0%, rgba(96,164,245,.19) 100%);
  opacity:0; transition:opacity .26s ease;
}
.v2x.atd .atd-tab-ic{
  /* No colour of its own — it INHERITS the chip ink, so it tracks --muted
     across both themes and through every state change for free. The .75 is
     MEASURED, not picked: it lands the glyph at 4.2:1 light / 3.9:1 dark on
     the composited chip, over the 3:1 non-text bar while staying visibly
     subordinate to the label beside it (8.1:1 / 5.7:1). The pass before this
     one had it at .62 over --muted2, which composited to 1.9:1 — a glyph
     faint enough to read as a rendering fault rather than a hierarchy. */
  display:inline-flex; flex:none; opacity:.75;
  transition:opacity .2s ease, transform .35s cubic-bezier(.16,1,.3,1), color .2s ease;
}
.v2x.atd .atd-tab-lbl{ min-width:0; }
body.theme-dark .v2x.atd .v2-tabs a{
  background:linear-gradient(180deg, rgba(255,255,255,.055) 0%, rgba(255,255,255,.022) 100%);
  border-color:var(--dk-line,rgba(255,255,255,.10)); box-shadow:none;
}
body.theme-dark .v2x.atd .v2-tabs a::before{
  background:linear-gradient(180deg, rgba(54,128,237,.30) 0%, rgba(96,164,245,.16) 100%);
}

/* Active — the thumb paints the fill, so the link only carries the ink.
   Without JS the thumb never gets `.has-thumb`, so the tab paints its own
   background here and the active state still reads. */
.v2x.atd .v2-tabs a.active{
  color:#fff; border-color:transparent;
  background:linear-gradient(135deg,#2F72DA 0%,#2261C4 55%,#1A4FA6 100%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22);
}
.v2x.atd .v2-tabs.has-thumb a.active{ background:transparent; box-shadow:none; }
.v2x.atd .v2-tabs a.active::before{ opacity:0; }
.v2x.atd .v2-tabs a.active .atd-tab-ic{ opacity:1; color:#fff; }
/* The dark chip rule above is `body.theme-dark … .v2-tabs a` — (0,4,2), which
   OUT-SPECIFIES `.v2x.atd .v2-tabs a.active` at (0,4,1) on element count. So
   the active tab has to restate its fill and its transparent border here or
   dark mode hands both straight back to the resting chip: a light hairline
   ringing the thumb, and (with JS off, where `.has-thumb` never lands) an
   active tab with no fill at all. The same trap is answered again for the
   orbit ring inside the @supports block below — every dark twin written at
   `… a` level must be answered at `… a.active` level. */
body.theme-dark .v2x.atd .v2-tabs a.active{
  color:#fff; border-color:transparent;
  background:linear-gradient(135deg,#2F72DA 0%,#2261C4 55%,#1A4FA6 100%);
}
body.theme-dark .v2x.atd .v2-tabs.has-thumb a.active{ background:transparent; }

/* ══ THE ORBIT ═════════════════════════════════════════════════════════════
   A comet of light travelling around an edge, built as a conic gradient the
   width of the whole box, then MASKED down to a ring: two full-box mask
   layers, one clipped to the content box and one to the border box, composited
   with xor — what survives is exactly the padding band, and because mask-clip
   follows border-radius the inner cut is a pill on a pill, not a rectangle.

   The whole thing is gated on @supports for a reason that is not cosmetic:
   without mask-composite the two layers UNION instead of subtracting, and the
   conic paints as a solid block across the chip — over the label. The brief
   was that text is never hidden, so where the mask is unavailable the ring
   simply does not exist and the shine bar carries the hover instead.

   Each ring declares `--atd-spin:0deg` next to its animation so the conic
   still resolves without that registration (static ring, see the note at top of
   this section), and each is `animation-play-state:paused` at rest — a paused
   animation does not tick, so seven idle chips cost nothing, and re-entering
   a chip RESUMES the orbit where it left off instead of snapping back to 0.
   ══════════════════════════════════════════════════════════════════════════ */
@supports ((-webkit-mask-composite:xor) or (mask-composite:exclude)){
  /* Card orbit. inset:-1px puts the ring ON the border rather than inside it,
     so the radius has to be the card's plus that 1px — hence --atd-r, which
     is the one value every breakpoint below re-points. No drop-shadow here:
     blooming a ~1200px-wide box every frame is real cost for a glow the
     card's own hover box-shadow already provides. */
  .v2x.atd .atd-tabsbar::before{
    content:""; position:absolute; inset:-1px; z-index:6; pointer-events:none;
    border-radius:calc(var(--atd-r) + 1px); padding:var(--atd-ring-lg);
    --atd-spin:0deg;
    background:conic-gradient(from var(--atd-spin),
      rgba(54,128,237,0)      0deg,
      rgba(96,164,245,.30)   34deg,
      rgba(127,182,248,.85)  62deg,
      rgba(255,255,255,.95)  76deg,
      rgba(47,114,218,.85)   92deg,
      rgba(54,128,237,.25)  124deg,
      rgba(54,128,237,0)    170deg,
      rgba(54,128,237,0)    190deg,
      rgba(96,164,245,.28)  224deg,
      rgba(127,182,248,.80) 252deg,
      rgba(255,255,255,.90) 266deg,
      rgba(47,114,218,.80)  282deg,
      rgba(54,128,237,.22)  314deg,
      rgba(54,128,237,0)    350deg,
      rgba(54,128,237,0)    360deg);
    -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite:xor;
            mask-composite:exclude;
    opacity:0; transition:opacity .42s ease;
    animation:atd-orbit var(--atd-orbit-lg) linear infinite; animation-play-state:paused;
  }
  /* On near-black the white core is the only stop that still reads as light;
     the mid blues are lifted so the comet does not dissolve into the border. */
  body.theme-dark .v2x.atd .atd-tabsbar::before{
    background:conic-gradient(from var(--atd-spin),
      rgba(96,164,245,0)      0deg,
      rgba(96,164,245,.34)   34deg,
      rgba(157,200,255,.90)  62deg,
      rgba(255,255,255,.98)  76deg,
      rgba(54,128,237,.90)   92deg,
      rgba(96,164,245,.28)  124deg,
      rgba(96,164,245,0)    170deg,
      rgba(96,164,245,0)    190deg,
      rgba(96,164,245,.32)  224deg,
      rgba(157,200,255,.85) 252deg,
      rgba(255,255,255,.92) 266deg,
      rgba(54,128,237,.85)  282deg,
      rgba(96,164,245,.25)  314deg,
      rgba(96,164,245,0)    350deg,
      rgba(96,164,245,0)    360deg);
  }

  /* Chip orbit. Two comets 180deg apart at 2.9s means one passes any given
     point every ~1.45s — fast enough to read as alive, slow enough not to
     strobe. The drop-shadow is the bloom: it follows the RENDERED alpha of
     the masked ring, so only the lit arc glows, and it travels with it. That
     is why the scroller keeps 8px of vertical padding. */
  .v2x.atd .v2-tabs a::after{
    content:""; position:absolute; inset:-1px; z-index:-1; pointer-events:none;
    border-radius:inherit; padding:var(--atd-ring);
    --atd-spin:0deg;
    background:conic-gradient(from var(--atd-spin),
      rgba(54,128,237,0)     0deg,
      rgba(96,164,245,.55)  26deg,
      #7FB6F8               44deg,
      #FFFFFF               56deg,
      #2F72DA               70deg,
      rgba(54,128,237,.35)  92deg,
      rgba(54,128,237,0)   132deg,
      rgba(54,128,237,0)   180deg,
      rgba(96,164,245,.50) 206deg,
      #7FB6F8              224deg,
      #FFFFFF              236deg,
      #2F72DA              250deg,
      rgba(54,128,237,.30) 272deg,
      rgba(54,128,237,0)   312deg,
      rgba(54,128,237,0)   360deg);
    -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite:xor;
            mask-composite:exclude;
    filter:drop-shadow(0 0 6px rgba(54,128,237,.55));
    opacity:0; transition:opacity .3s ease;
    animation:atd-orbit var(--atd-orbit) linear infinite; animation-play-state:paused;
  }
  /* Over the saturated active fill a blue comet is invisible — the ring goes
     white-cored with a pale blue tail so it reads as light ON the brand
     rather than more brand. */
  .v2x.atd .v2-tabs a.active::after{
    background:conic-gradient(from var(--atd-spin),
      rgba(255,255,255,0)     0deg,
      rgba(255,255,255,.45)  30deg,
      rgba(255,255,255,1)    54deg,
      rgba(186,216,255,.90)  72deg,
      rgba(255,255,255,.25)  98deg,
      rgba(255,255,255,0)   140deg,
      rgba(255,255,255,0)   190deg,
      rgba(255,255,255,.40) 216deg,
      rgba(255,255,255,1)   240deg,
      rgba(186,216,255,.85) 258deg,
      rgba(255,255,255,.20) 284deg,
      rgba(255,255,255,0)   326deg,
      rgba(255,255,255,0)   360deg);
    filter:drop-shadow(0 0 7px rgba(255,255,255,.55));
  }
  body.theme-dark .v2x.atd .v2-tabs a::after{
    background:conic-gradient(from var(--atd-spin),
      rgba(96,164,245,0)     0deg,
      rgba(96,164,245,.50)  26deg,
      #9DC8FF               44deg,
      #FFFFFF               56deg,
      #3680ED               70deg,
      rgba(96,164,245,.32)  92deg,
      rgba(96,164,245,0)   132deg,
      rgba(96,164,245,0)   180deg,
      rgba(96,164,245,.46) 206deg,
      #9DC8FF              224deg,
      #FFFFFF              236deg,
      #3680ED              250deg,
      rgba(96,164,245,.28) 272deg,
      rgba(96,164,245,0)   312deg,
      rgba(96,164,245,0)   360deg);
    filter:drop-shadow(0 0 7px rgba(96,164,245,.5));
  }
  /* (0,5,2) — has to out-rank the dark resting ring at (0,4,2) directly above,
     exactly as the fill does. Without this the active tab wears the blue
     comet on its blue fill in dark mode and the ring disappears. */
  body.theme-dark .v2x.atd .v2-tabs a.active::after{
    background:conic-gradient(from var(--atd-spin),
      rgba(255,255,255,0)     0deg,
      rgba(255,255,255,.45)  30deg,
      rgba(255,255,255,1)    54deg,
      rgba(186,216,255,.90)  72deg,
      rgba(255,255,255,.25)  98deg,
      rgba(255,255,255,0)   140deg,
      rgba(255,255,255,0)   190deg,
      rgba(255,255,255,.40) 216deg,
      rgba(255,255,255,1)   240deg,
      rgba(186,216,255,.85) 258deg,
      rgba(255,255,255,.20) 284deg,
      rgba(255,255,255,0)   326deg,
      rgba(255,255,255,0)   360deg);
    filter:drop-shadow(0 0 7px rgba(255,255,255,.5));
  }

  /* Arrow orbit — same recipe, tightest scale. */
  .v2x.atd .atd-tabs-arrow::after{
    content:""; position:absolute; inset:-1px; z-index:0; pointer-events:none;
    border-radius:999px; padding:1.5px;
    --atd-spin:0deg;
    background:conic-gradient(from var(--atd-spin),
      rgba(54,128,237,0)     0deg,
      rgba(96,164,245,.5)   28deg,
      #7FB6F8               48deg,
      #FFFFFF               60deg,
      #2F72DA               74deg,
      rgba(54,128,237,0)   118deg,
      rgba(54,128,237,0)   208deg,
      rgba(96,164,245,.45) 236deg,
      #FFFFFF              254deg,
      #2F72DA              268deg,
      rgba(54,128,237,0)   312deg,
      rgba(54,128,237,0)   360deg);
    -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite:xor;
            mask-composite:exclude;
    filter:drop-shadow(0 0 5px rgba(54,128,237,.5));
    opacity:0; transition:opacity .3s ease;
    animation:atd-orbit 2.4s linear infinite; animation-play-state:paused;
  }
  body.theme-dark .v2x.atd .atd-tabs-arrow::after{
    background:conic-gradient(from var(--atd-spin),
      rgba(96,164,245,0)     0deg,
      rgba(96,164,245,.5)   28deg,
      #9DC8FF               48deg,
      #FFFFFF               60deg,
      #3680ED               74deg,
      rgba(96,164,245,0)   118deg,
      rgba(96,164,245,0)   208deg,
      rgba(96,164,245,.45) 236deg,
      #FFFFFF              254deg,
      #3680ED              268deg,
      rgba(96,164,245,0)   312deg,
      rgba(96,164,245,0)   360deg);
    filter:drop-shadow(0 0 5px rgba(96,164,245,.45));
  }

  /* Keyboard gets the same premium treatment as the pointer — the orbit runs
     on focus-visible too. Deliberately OUTSIDE the hover media query: a
     keyboard on a touch screen is a real combination. */
  .v2x.atd .v2-tabs a:focus-visible::after{ opacity:1; animation-play-state:running; }
  .v2x.atd .atd-tabs-arrow:focus-visible::after{ opacity:1; animation-play-state:running; }
  .v2x.atd .atd-tabsbar:focus-within::before{ opacity:.85; animation-play-state:running; }

  @media (hover:hover) and (pointer:fine){
    .v2x.atd .atd-tabsbar:hover::before{ opacity:1; animation-play-state:running; }
    /* The card steps back while a chip owns the pointer, so the two orbits
       never read as equal claims on attention. Without :has() support the
       card just stays at full — a degradation, not a break. */
    .v2x.atd .atd-tabsbar:has(.v2-tabs a:hover)::before,
    .v2x.atd .atd-tabsbar:has(.atd-tabs-arrow:hover)::before{ opacity:.34; }
    .v2x.atd .v2-tabs a:hover::after,
    .v2x.atd .atd-tabs-arrow:hover::after{ opacity:1; animation-play-state:running; }
  }
  /* Touch: no hover to speak of, so the orbit fires on the press itself. It
     lasts as long as the finger is down, which is exactly the moment the
     feedback is wanted. */
  @media (hover:none){
    .v2x.atd .v2-tabs a:active::after{ opacity:1; animation-play-state:running; }
  }
  /* Reduced motion keeps the LIGHT and drops the TRAVEL — the ring freezes at
     135deg, which is a designed-looking gradient edge rather than an arbitrary
     one, and the bloom goes with it since a static glow on one arc looks like
     a rendering fault. */
  @media (prefers-reduced-motion:reduce){
    .v2x.atd .atd-tabsbar::before,
    .v2x.atd .v2-tabs a::after,
    .v2x.atd .atd-tabs-arrow::after{
      --atd-spin:135deg; animation:none !important; filter:none;
    }
  }
}

@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-tabsbar:hover{
    border-color:rgba(54,128,237,.34);
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,.75),
      0 1px 2px rgba(15,23,42,.04),
      0 18px 38px -18px rgba(32,96,192,.32);
  }
  body.theme-dark .v2x.atd .atd-tabsbar:hover{
    border-color:rgba(54,128,237,.44);
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,.05),
      0 1px 2px rgba(0,0,0,.45),
      0 18px 38px -18px rgba(0,0,0,.9);
  }
  .v2x.atd .atd-tabsbar:hover::after{ opacity:1; transform:translateY(0); }

  /* #1B54A8 on the tinted-glass composite measures 5.7:1 at the fill's darkest
     stop and better above it. The border under the comet is kept at 42% brand
     so the 3/4 of the ring the comet is not currently lighting still has an
     edge to travel along. */
  .v2x.atd .v2-tabs a:not(.active):hover{
    color:#1B54A8; border-color:rgba(54,128,237,.42);
    transform:translateY(-2px);
    box-shadow:0 10px 22px -10px rgba(32,96,192,.62), 0 0 0 4px rgba(54,128,237,.07);
    text-decoration:none;
  }
  .v2x.atd .v2-tabs a:not(.active):hover::before{ opacity:1; }
  .v2x.atd .v2-tabs a:not(.active):hover .atd-tab-ic{ opacity:1; color:#1B54A8; transform:translateY(-1px) scale(1.14); }
  body.theme-dark .v2x.atd .v2-tabs a:not(.active):hover{
    color:#D6E6FE; border-color:rgba(54,128,237,.58);
    box-shadow:0 10px 22px -10px rgba(0,0,0,.9), 0 0 0 4px rgba(54,128,237,.12);
  }
  body.theme-dark .v2x.atd .v2-tabs a:not(.active):hover .atd-tab-ic{ color:#D6E6FE; }

  /* Active on hover — it is already the destination, so it brightens in place
     instead of lifting. `.v2x .v2-tabs a:hover` in the shared kit (0,3,0)
     would otherwise repaint it accent-soft. */
  .v2x.atd .v2-tabs a.active:hover{ color:#fff; text-decoration:none; transform:none; }
  .v2x.atd .v2-tabs.has-thumb a.active:hover{ background:transparent; }
  .v2x.atd .v2-tabs a.active:hover .atd-tab-ic{ transform:scale(1.14); }
}
/* Where the orbit exists it leads, so the shine bar steps back to a
   supporting wash rather than fighting it for the same top edge. This has to
   sit AFTER the hover block above: both selectors are (0,4,1), so the tie
   breaks on source order, and inside the @supports block higher up it lost
   every time. Where the orbit does NOT exist the shine bar keeps opacity:1 and
   carries the hover on its own. */
@supports ((-webkit-mask-composite:xor) or (mask-composite:exclude)){
  .v2x.atd .atd-tabsbar:hover::after,
  .v2x.atd .atd-tabsbar:focus-within::after{ opacity:.45; }
}

.v2x.atd .v2-tabs a:active{ transform:translateY(0) scale(.97); }
.v2x.atd .v2-tabs a:focus-visible{
  outline:none; border-radius:var(--atd-tab-r);
  box-shadow:0 0 0 3px rgba(54,128,237,.85), 0 0 0 6px rgba(54,128,237,.22);
}

/* ── Overflow affordances ──────────────────────────────────────────────────
   Edge MASK, not a colour fade: it hides whatever the card is painted with,
   so it needs no dark twin and survives the tinted wash above. Applied only
   on the side that can actually scroll — a permanently-masked edge would eat
   the first tab on a wide screen where nothing is clipped. */
.v2x.atd .atd-tabsbar.can-l .v2-tabs{
  -webkit-mask-image:linear-gradient(90deg, transparent 0, #000 var(--atd-fade));
          mask-image:linear-gradient(90deg, transparent 0, #000 var(--atd-fade));
}
.v2x.atd .atd-tabsbar.can-r .v2-tabs{
  -webkit-mask-image:linear-gradient(270deg, transparent 0, #000 var(--atd-fade));
          mask-image:linear-gradient(270deg, transparent 0, #000 var(--atd-fade));
}
.v2x.atd .atd-tabsbar.can-l.can-r .v2-tabs{
  -webkit-mask-image:linear-gradient(90deg, transparent 0, #000 var(--atd-fade), #000 calc(100% - var(--atd-fade)), transparent 100%);
          mask-image:linear-gradient(90deg, transparent 0, #000 var(--atd-fade), #000 calc(100% - var(--atd-fade)), transparent 100%);
}

.v2x.atd .atd-tabs-arrow{
  position:relative; flex:none; z-index:3; display:none;
  width:36px; height:36px; padding:0; border-radius:999px;
  align-items:center; justify-content:center;
  background:linear-gradient(180deg,#FFFFFF 0%,#F3F7FD 100%);
  border:1px solid var(--line-strong); color:#1B54A8; cursor:pointer;
  box-shadow:0 1px 2px rgba(15,23,42,.06);
  transition:background .22s ease, border-color .22s ease, color .2s ease, transform .28s cubic-bezier(.16,1,.3,1), box-shadow .28s ease;
}
.v2x.atd .atd-tabs-arrow.is-prev .lcd{ transform:rotate(180deg); }
body.theme-dark .v2x.atd .atd-tabs-arrow{
  background:linear-gradient(180deg, rgba(255,255,255,.07) 0%, rgba(255,255,255,.03) 100%);
  border-color:var(--line-strong); color:#9DC0F6; box-shadow:none;
}
/* Arrows are a precise-pointer affordance only — a touch device swipes, and a
   36px control inside a scroller is a worse target than the scroller itself. */
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-tabsbar.can-l .atd-tabs-arrow.is-prev,
  .v2x.atd .atd-tabsbar.can-r .atd-tabs-arrow.is-next{ display:inline-flex; }
  .v2x.atd .atd-tabs-arrow:hover{
    background:var(--accent-soft); border-color:rgba(54,128,237,.42); color:#164896;
    transform:translateY(-1px); box-shadow:0 8px 16px -8px rgba(32,96,192,.55);
  }
  body.theme-dark .v2x.atd .atd-tabs-arrow:hover{
    background:rgba(54,128,237,.18); border-color:rgba(54,128,237,.7); color:#D6E6FE; box-shadow:0 8px 16px -8px rgba(0,0,0,.85);
  }
}
.v2x.atd .atd-tabs-arrow:active{ transform:translateY(0) scale(.94); }
.v2x.atd .atd-tabs-arrow:focus-visible{
  outline:none; box-shadow:0 0 0 3px rgba(54,128,237,.85), 0 0 0 6px rgba(54,128,237,.22);
}

/* ── Responsive ────────────────────────────────────────────────────────────
   The rail tightens as width runs out, and tab LABELS are the last thing
   touched — never truncated at any width, because a half-word is a worse
   affordance than a scroll. Each step re-points --atd-r rather than
   restating border-radius, because the card orbit derives its own radius
   from it (`calc(--atd-r + 1px)`) and the two must never drift apart.
   min-height holds at 40px down to the phone step and then RISES to 42px:
   below 576px the pointer is a finger, and the chip is the target. */
@media (max-width:1199.98px){
  .v2x.atd .v2-tabs a{ padding:10px 16px; }
}
@media (max-width:991.98px){
  .v2x.atd .atd-tabsbar{ --atd-fade:48px; --atd-r:18px; --atd-gut:7px; }
  .v2x.atd .v2-tabs{ gap:7px; }
  .v2x.atd .v2-tabs a{ padding:9px 15px; font-size:.9rem; gap:7px; }
}
@media (max-width:767.98px){
  .v2x.atd .atd-tabsbar{ gap:8px; }
  .v2x.atd .v2-tabs a{ padding:9px 14px; }
}
@media (max-width:575.98px){
  .v2x.atd .atd-tabsbar{ --atd-gut:6px; --atd-fade:38px; --atd-r:16px; padding:4px 8px; gap:0; }
  .v2x.atd .atd-tabsbar::after{ left:16px; right:16px; }
  .v2x.atd .v2-tabs{ gap:6px; }
  .v2x.atd .v2-tabs a{ padding:9px 14px; min-height:42px; font-size:.88rem; gap:7px; }
}
@media (max-width:359.98px){
  /* Icons are decorative (aria-hidden), and below 360px the saving is real —
     ~22px a tab, so more LABELS fit. Not done at 400px: the rail scrolls at
     phone widths either way, so above this the icons cost nothing and the
     common iPhone widths (375, 390) keep their glyph rhythm. Labels are never
     touched at any width. */
  .v2x.atd .atd-tab-ic{ display:none; }
  .v2x.atd .v2-tabs a{ padding:9px 13px; }
}

@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-tabsbar,.v2x.atd .atd-tabsbar::after,
  .v2x.atd .v2-tabs a,.v2x.atd .v2-tabs a::before,
  .v2x.atd .atd-tab-ic,.v2x.atd .atd-tabs-arrow{ transition:none !important; }
  .v2x.atd .v2-tabs a:not(.active):hover,
  .v2x.atd .atd-tabs-arrow:hover{ transform:none !important; }
  .v2x.atd .v2-tabs a:not(.active):hover .atd-tab-ic,
  .v2x.atd .v2-tabs a.active:hover .atd-tab-ic{ transform:none !important; }
}

/* ==========================================================================
   4a) About — 6-up capability icon strip
   ========================================================================== */
.v2x.atd .atd-caps{ display:grid; grid-template-columns:repeat(6,1fr); gap:14px; margin-top:24px; }
.v2x.atd .atd-cap{ display:flex; flex-direction:column; align-items:center; gap:10px; text-align:center; padding:6px 2px; }
.v2x.atd .atd-cap .ic{
  width:52px; height:52px; border-radius:var(--r-card);
  background:var(--accent-soft); color:var(--accent);
  display:flex; align-items:center; justify-content:center;
  font-size:1.15rem; transition:transform 150ms ease;
}
.v2x.atd .atd-cap:hover .ic{ transform:translateY(-3px); }
.v2x.atd .atd-cap .lb{ font-family:var(--font); font-size:.82rem; font-weight:600; color:#39414d; line-height:1.35; }

/* ==========================================================================
   4b) Key features — 2-col rows
   ========================================================================== */
.v2x.atd .atd-feats{ display:grid; grid-template-columns:1fr 1fr; gap:8px 24px; }
.v2x.atd .atd-feat{
  display:flex; gap:14px; align-items:flex-start; padding:14px; border-radius:var(--r-card);
  transition:background 150ms ease,transform 150ms ease,box-shadow 150ms ease;
}
.v2x.atd .atd-feat:hover{ background:var(--accent-soft2); transform:translateY(-2px); box-shadow:var(--sh-md); }
.v2x.atd .atd-feat .ic{
  width:46px; height:46px; border-radius:var(--r-card); flex-shrink:0;
  background:var(--accent-soft); color:var(--accent);
  display:flex; align-items:center; justify-content:center; font-size:1.05rem;
}
.v2x.atd .atd-feat .ic.is-check{ background:rgba(34,197,94,.12); color:#16a34a; }   /* mockup: green checks for Key Features */
.v2x.atd .atd-feat .nm{ font-family:var(--font); font-weight:700; font-size:1.05rem; color:var(--ink); margin:0 0 3px; }
.v2x.atd .atd-feat .ds{ font-size:.9rem; color:var(--muted); margin:0; line-height:1.55; }

/* Use-case cards (shared .v2-feature) */
.v2x.atd .v2-feature{
  display:flex; gap:14px; align-items:flex-start; padding:18px;
  background:#fff; border:1px solid var(--line); border-radius:var(--r-card);
  transition:transform 150ms ease,box-shadow 150ms ease,border-color 150ms ease;
}
.v2x.atd .v2-feature:hover{ transform:translateY(-3px); box-shadow:var(--sh-lg); border-color:#dbe8fd; }
.v2x.atd .v2-feature .ic{
  width:44px; height:44px; border-radius:var(--r-card); flex-shrink:0;
  background:linear-gradient(135deg,#eef4fe,#f6f9ff); color:var(--accent);
  display:flex; align-items:center; justify-content:center; font-size:1.05rem;
}
.v2x.atd .v2-feature .fw-semibold{ font-family:var(--font); font-weight:700; font-size:1rem; color:var(--ink); }
.v2x.atd .v2-chip.gray{ background:var(--accent-soft); color:var(--accent-dark); border-radius:var(--r-pill); font-family:var(--mono); }

/* ==========================================================================
   4c) Pricing cards
   ========================================================================== */
.v2x.atd .atd-plan{
  position:relative; background:#fff; border:1px solid var(--line); border-radius:var(--r-card);
  padding:24px 22px; height:100%; display:flex; flex-direction:column;
  transition:transform 150ms ease,box-shadow 150ms ease,border-color 150ms ease;
}
.v2x.atd .atd-plan:hover{ transform:translateY(-3px); box-shadow:var(--sh-lg); }
.v2x.atd .atd-plan.is-popular{ border-color:var(--accent); box-shadow:0 0 0 3px rgba(54,128,237,.30),var(--sh-lg); }
.v2x.atd .atd-plan-pop{
  position:absolute; top:-12px; left:50%; transform:translateX(-50%);
  background:var(--grad-brand); color:#fff;
  font-family:var(--font); font-size:.7rem; font-weight:600; letter-spacing:.04em; text-transform:uppercase;
  border-radius:var(--r-pill); padding:5px 13px; box-shadow:var(--sh-brand); white-space:nowrap;
}
.v2x.atd .atd-plan-name{ font-family:var(--font); font-size:1.25rem; font-weight:700; color:var(--ink); margin:0 0 8px; }
.v2x.atd .atd-plan-price{ display:flex; align-items:baseline; gap:5px; margin-bottom:14px; }
.v2x.atd .atd-plan-price .amt{ font-family:var(--font); font-size:2.25rem; font-weight:800; letter-spacing:-.03em; color:var(--ink); line-height:1; }
.v2x.atd .atd-plan-price .per{ font-size:.82rem; color:var(--muted2); font-weight:500; }
.v2x.atd .atd-plan-list{ list-style:none; margin:0 0 22px; padding:0; flex:1; }
.v2x.atd .atd-plan-list li{ display:flex; gap:9px; align-items:flex-start; font-size:.9rem; color:var(--muted); padding:5px 0; }
.v2x.atd .atd-plan-list li i{ color:var(--green); font-size:.82rem; margin-top:4px; }
.v2x.atd .atd-plan-list li.off{ color:#a6aeba; text-decoration:line-through; }
.v2x.atd .atd-plan-list li.off i{ color:#c5ccd6; }
.v2x.atd .atd-plan .v2-btn,
.v2x.atd .atd-plan .atd-btn{ width:100%; white-space:nowrap; padding-inline:12px; }

/* Plan grid. This card sits in the 8-column main area, so a fixed 4-up row
   squeezed every plan to ~230px and stranded a lone card whenever a tool had
   five. auto-fit sizes to the plan count instead, and the mid band drops to a
   clean 2-up so four plans read as 2+2 rather than 3+1. */
.v2x.atd .atd-plans{
  display:grid; gap:16px; align-items:stretch;
  grid-template-columns:repeat(auto-fit,minmax(min(100%,215px),1fr));
}
/* 5+ plans: a wider floor caps the row at three, giving 3+2 instead of 4+1. */
.v2x.atd .atd-plans[data-count="5"],
.v2x.atd .atd-plans[data-count="6"]{ grid-template-columns:repeat(auto-fit,minmax(min(100%,270px),1fr)); }
@media (min-width:992px) and (max-width:1399.98px){
  .v2x.atd .atd-plans,
  .v2x.atd .atd-plans[data-count="5"],
  .v2x.atd .atd-plans[data-count="6"]{ grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (max-width:479.98px){
  .v2x.atd .atd-plans,
  .v2x.atd .atd-plans[data-count="5"],
  .v2x.atd .atd-plans[data-count="6"]{ grid-template-columns:minmax(0,1fr); }
}
/* "Custom" / "Pay as you go" are words, not figures — never set them at 2.25rem. */
.v2x.atd .atd-plan-price .amt{ overflow-wrap:anywhere; }
.v2x.atd .atd-plan-price .amt.is-word{ font-size:1.5rem; }
.v2x.atd .atd-plan-price:has(.amt.is-word){ align-items:center; }
/* x-lucide renders <svg>, so the original `li i` rule never matched. */
.v2x.atd .atd-plan-list li svg{ color:var(--green); flex:0 0 auto; margin-top:3px; }
.v2x.atd .atd-plan-list li.off svg{ color:#c5ccd6; }
.v2x.atd .atd-plan-list li > span{ flex:1 1 auto; min-width:0; }

/* Section footer link / toggle (pricing "view full details", features "show more") */
.v2x.atd .atd-sec-more{ display:flex; justify-content:center; margin-top:20px; }
.v2x.atd .atd-sec-more .atd-link{ font-weight:600; }
.v2x.atd .atd-feats-toggle{
  background:none; border:0; cursor:pointer; font-family:var(--font);
  display:inline-flex; align-items:center; gap:8px; padding:8px 4px;
}
.v2x.atd .atd-feats-toggle .chev{ transition:transform 160ms ease; }
.v2x.atd .atd-feats-toggle.is-open .chev{ transform:rotate(180deg); }
.v2x.atd .atd-feats-more{ margin-top:0; }
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-feats-toggle .chev{ transition:none; }
}
body.theme-dark .v2x.atd .atd-plan-list li.off svg{ color:#4b5361; }

/* ==========================================================================
   4d) Reviews (shared partial re-skin: amber bars, verified card look)
   ========================================================================== */
.v2x.atd .v2-bar{ display:block; height:8px; border-radius:999px; background:#eef1f6; overflow:hidden; }
.v2x.atd .v2-bar>span{ display:block; height:100%; border-radius:999px; background:var(--amber); }
.v2x.atd .v2-toolcard{ border-radius:var(--r-card); background:#fff; }
.v2x.atd .v2-toolcard:hover{ border-color:#dbe8fd; box-shadow:var(--sh-md); }

/* ==========================================================================
   4e) FAQ (shared accordion re-skin: separated rounded items, + → ×)
   ========================================================================== */
.v2x.atd .v2-accordion{ border:0; border-radius:0; overflow:visible; }
.v2x.atd .v2-accordion details{
  border:1px solid var(--line); border-radius:var(--r-card); margin-bottom:12px;
  background:#fff; overflow:hidden; transition:box-shadow 150ms ease,border-color 150ms ease;
}
.v2x.atd .v2-accordion details[open]{ border-color:#dbe8fd; box-shadow:var(--sh-sm); }
.v2x.atd .v2-accordion details:last-child{ border-bottom:1px solid var(--line); }
.v2x.atd .v2-accordion summary{ padding:16px 20px; font-family:var(--font); font-weight:700; font-size:1.1rem; color:var(--ink); }
.v2x.atd .v2-accordion summary:hover{ background:transparent; }
.v2x.atd .v2-accordion summary .pm{ color:var(--accent); font-size:.9rem; transition:transform 200ms ease,color 150ms ease; }
.v2x.atd .v2-accordion details[open] summary{ color:var(--ink); }
.v2x.atd .v2-accordion details[open] summary .pm{ transform:rotate(45deg); color:var(--accent); }
.v2x.atd .v2-accordion .bd{ padding:0 20px 18px; font-size:1rem; color:var(--muted); line-height:1.75; }

/* ==========================================================================
   Two bootstrap-utility rules that USED to belong to the Pros & Cons partial.
   That partial no longer uses either class — it is a dedicated kit now, see
   §PROSCONS at the end of this file. These stay because `usecases`, `hero`
   and `share` also render `.small` / `.fw-bold` inside a `.v2-section`, and
   deleting them on the assumption that "the proscons rules" were dead would
   have restyled three other partials as a side effect.
   ========================================================================== */
.v2x.atd .v2-section .fw-bold{ font-family:var(--font); font-size:1.05rem; }
.v2x.atd .v2-section .small{ font-size:.95rem; line-height:1.55; color:var(--muted); }

/* ==========================================================================
   5) Sidebar
   ========================================================================== */
/* ══════════════════════════════════════════════════════════════════════════
   §SIDEBAR) One card system for the whole rail, matched to the HOMEPAGE.

   Values are lifted from the live homepage, not approximated — geometry from
   `.hpx-card` (radius --hpx-r 20px, 1px --hpx-line, --hpx-sh-soft at rest,
   --hpx-sh-lift + --tone-line on hover, easing --hpx-a-ease, icon
   scale(1.07) rotate(-3deg)) and the tone ramps from the rendered
   `--hpx-t-*-{bg,ink,line}` custom properties, light AND dark.

   ⚠️ The homepage card ALSO has a 3px `::before` accent bar that wipes in on
   hover. It is deliberately NOT copied here: a thin bar on a rounded card has
   been rejected twice in this codebase ("ugly" / "not looking good") — see
   [[generate-cta-and-focus-trap]]. The tone still reads through the icon
   chip, the count badge, the hover border and the hover glow.

   Also no `overflow:hidden` on the card (the homepage has it): the chips and
   links inside ring their focus state with a box-shadow, and clipping would
   cut those rings off at the card edge.
   ══════════════════════════════════════════════════════════════════════════ */
.v2x.atd .atd-sidebar{
  position:static; display:flex; flex-direction:column; gap:0;
  --hp-e:cubic-bezier(.22,.61,.36,1);
  --hp-sh:0 1px 2px rgba(16,24,40,.04), 0 6px 20px rgba(16,24,40,.05);
  --hp-sh-lift:0 2px 6px rgba(16,24,40,.06), 0 18px 44px rgba(16,24,40,.10);
}
/* Tone ramp — light (mirrors the homepage exactly) */
.v2x.atd .atd-sidebar [data-tone="blue"]   { --tone-bg:#EAF2FD; --tone-ink:#1B5BB5; --tone-line:#CFE0FA; --tone-1:#4C8DF2; --tone-2:#2060C0; }
.v2x.atd .atd-sidebar [data-tone="violet"] { --tone-bg:#F0EBFE; --tone-ink:#5B33C4; --tone-line:#DED2FB; --tone-1:#8B5CF6; --tone-2:#5B33C4; }
.v2x.atd .atd-sidebar [data-tone="emerald"]{ --tone-bg:#E6F8F1; --tone-ink:#08795A; --tone-line:#C6EEDF; --tone-1:#10B981; --tone-2:#08795A; }
.v2x.atd .atd-sidebar [data-tone="amber"]  { --tone-bg:#FEF4E4; --tone-ink:#A85B08; --tone-line:#FBE3C0; --tone-1:#F59E0B; --tone-2:#A85B08; }
.v2x.atd .atd-sidebar [data-tone="rose"]   { --tone-bg:#FEECEF; --tone-ink:#B31D3C; --tone-line:#FBD2DA; --tone-1:#F43F5E; --tone-2:#B31D3C; }
.v2x.atd .atd-sidebar [data-tone="cyan"]   { --tone-bg:#E4F6FB; --tone-ink:#0A6E88; --tone-line:#C2E9F4; --tone-1:#22B8D9; --tone-2:#0A6E88; }
.v2x.atd .atd-sidebar [data-tone="indigo"] { --tone-bg:#EBEEFE; --tone-ink:#3540B0; --tone-line:#D3D9FB; --tone-1:#6366F1; --tone-2:#3540B0; }
.v2x.atd .atd-sidebar [data-tone="teal"]   { --tone-bg:#E3F6F5; --tone-ink:#0B6E68; --tone-line:#C1EAE7; --tone-1:#14B8A6; --tone-2:#0B6E68; }

/* Card geometry + hover, per .hpx-card */
.v2x.atd .atd-sidebar > .v2-card{
  position:relative;
  border-radius:20px; border:1px solid var(--line);
  box-shadow:var(--hp-sh);
  transition:transform .22s var(--hp-e), box-shadow .24s ease, border-color .2s ease;
}
.v2x.atd .atd-sidebar > .v2-card.v2-section{ margin-bottom:16px; }
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-sidebar > .v2-card:hover{
    transform:translateY(-3px);
    border-color:var(--tone-line, var(--line));
    box-shadow:var(--hp-sh-lift);
  }
  .v2x.atd .atd-sidebar > .v2-card:hover .atd-side-ic{ transform:scale(1.07) rotate(-3deg); }
}
/* Tone drives the header chip and the count badge. */
.v2x.atd .atd-sidebar [data-tone] .atd-side-ic{
  background:linear-gradient(135deg, var(--tone-1,#4C8DF2), var(--tone-2,#2060C0));
  box-shadow:0 4px 12px color-mix(in srgb, var(--tone-2,#2060C0) 34%, transparent);
}
@supports not (color: color-mix(in srgb, red 50%, transparent)){
  .v2x.atd .atd-sidebar [data-tone] .atd-side-ic{ box-shadow:0 4px 12px rgba(16,24,40,.20); }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-sidebar > .v2-card{ transition:none !important; }
  .v2x.atd .atd-sidebar > .v2-card:hover{ transform:none; }
  .v2x.atd .atd-sidebar > .v2-card:hover .atd-side-ic{ transform:none; }
}
/* Tone ramp — dark (also the homepage's own, not an invention) */
body.theme-dark .v2x.atd .atd-sidebar [data-tone="blue"]   { --tone-bg:rgba(54,128,237,.18); --tone-ink:#8CBEFA; --tone-line:rgba(96,164,245,.28); }
body.theme-dark .v2x.atd .atd-sidebar [data-tone="violet"] { --tone-bg:rgba(124,77,240,.20); --tone-ink:#BFA6FB; --tone-line:rgba(160,120,250,.32); }
body.theme-dark .v2x.atd .atd-sidebar [data-tone="emerald"]{ --tone-bg:rgba(16,185,129,.18); --tone-ink:#6EE7BE; --tone-line:rgba(52,211,153,.30); }
body.theme-dark .v2x.atd .atd-sidebar [data-tone="amber"]  { --tone-bg:rgba(245,158,11,.20); --tone-ink:#FBC97A; --tone-line:rgba(251,191,36,.32); }
body.theme-dark .v2x.atd .atd-sidebar [data-tone="rose"]   { --tone-bg:rgba(244,63,94,.18);  --tone-ink:#FB9BB0; --tone-line:rgba(251,113,133,.30); }
body.theme-dark .v2x.atd .atd-sidebar [data-tone="cyan"]   { --tone-bg:rgba(6,182,212,.18);  --tone-ink:#7CD9EE; --tone-line:rgba(34,211,238,.30); }
body.theme-dark .v2x.atd .atd-sidebar [data-tone="indigo"] { --tone-bg:rgba(79,70,229,.20);  --tone-ink:#A9B2FB; --tone-line:rgba(129,140,248,.32); }
body.theme-dark .v2x.atd .atd-sidebar [data-tone="teal"]   { --tone-bg:rgba(20,184,166,.18); --tone-ink:#79DDD5; --tone-line:rgba(45,212,191,.30); }
body.theme-dark .v2x.atd .atd-sidebar{
  --hp-sh:0 1px 2px rgba(0,0,0,.40), 0 6px 20px rgba(0,0,0,.35);
  --hp-sh-lift:0 2px 6px rgba(0,0,0,.50), 0 18px 44px rgba(0,0,0,.45);
}
.v2x.atd .atd-side-title{
  font-family:var(--font); font-size:1.1rem; font-weight:700; color:var(--ink); margin:0 0 16px;
  display:flex; align-items:center; justify-content:space-between; gap:10px;
}
.v2x.atd .atd-side-title .atd-link{ font-size:.84rem; }

/* Card header row — heading + "View all". The link used to live INSIDE the
   <h2>, which swallowed "View all" into the accessible heading name; it is now
   a sibling and this wrapper carries the flex the title used to provide. */
.v2x.atd .atd-side-head{
  display:flex; align-items:center; justify-content:space-between; gap:10px; margin:0 0 16px;
}
/* ⚠️ EVERY head row that puts .atd-side-title beside an icon must be in this
   selector list. The title carries `margin:0 0 16px` for standalone use, and a
   flex row with `align-items:center` centres the MARGIN box — so an uncancelled
   bottom margin lifts the text half its value (8px, or 7px at the mobile step)
   above the icon tile it is supposed to sit level with. It reads as a wonky
   heading, not as a margin, which is why it survived this long.
   `.cmp-profile-head` (company hero) and `.amd-spec-head` (ai-model hero) —
   both the "At a Glance" card — plus `.sbd-panel-head`, the
   status board's Live Health panel — were doing exactly that; `.atd-side-head`
   and `.atd-side-ihead`/`.atd-side-ititle` already cancelled it. Added here
   rather than in cmp-styles/amd-styles so there is one list to extend, and
   because these hero cards are the same surface as the sidebar cards.
   Specificity: (0,3,0) and (0,4,0) both beat the (0,2,0) mobile rule that
   re-states margin-bottom at 14px, so the cancel holds at every width. */
.v2x.atd .atd-side-head .atd-side-title,
.v2x.atd .atd-side-ihead .atd-side-title,
.v2x.atd .atd-claim-head .atd-side-title,
.v2x.atd.cmp .cmp-profile-head .atd-side-title,
.v2x.atd.amd .amd-spec-head .atd-side-title,
.v2x.atd.sbd .sbd-panel-head .atd-side-title{ margin:0; flex:1 1 auto; min-width:0; }
.v2x.atd .atd-side-head .atd-link{ font-size:.84rem; flex:0 0 auto; white-space:nowrap; }

/* ==========================================================================
   §INFO) Tool Information spec card — header chip, glyphed rows, value pills
   ========================================================================== */
.v2x.atd .atd-side-ihead{ display:flex; align-items:center; gap:11px; margin:0 0 14px; }
.v2x.atd .atd-side-ic{
  flex:0 0 auto; width:34px; height:34px; border-radius:10px;
  display:flex; align-items:center; justify-content:center;
  background:linear-gradient(135deg,#4C8DF2,#2060C0); color:#fff; font-size:.85rem;
  box-shadow:0 4px 12px rgba(32,96,192,.30);
  transition:transform 380ms cubic-bezier(.16,1,.3,1);
}
/* Same story as .atd-claim-title: correct at (0,2,0) on desktop, beaten
   under 768px by the later `.atd-side-title{ margin-bottom:14px }` mobile
   step. The (0,3,0) head-row list above is what actually holds it now. */
.v2x.atd .atd-side-ititle{ margin:0; }
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-info:hover .atd-side-ic{ transform:scale(1.06) rotate(-4deg); }
}

/* Fact rows.
   `flex-wrap:wrap` + `min-width:0` is what stops a long value ("AI Chatbots &
   Assistants", "16+ Languages") from crushing its label — it drops to its own
   line instead. Nothing here truncates. */
.v2x.atd .atd-facts{ list-style:none; margin:0; padding:0; }
.v2x.atd .atd-facts li{
  position:relative;
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between;
  gap:8px 12px; font-size:.9rem;
  margin-inline:-12px; padding:10px 12px;
  border-bottom:1px solid var(--line); border-radius:9px;
  transition:background-color 220ms ease;
}
.v2x.atd .atd-facts li:last-child{ border-bottom:0; }
.v2x.atd .atd-facts .k{
  display:inline-flex; align-items:center; gap:9px; min-width:0;
  color:var(--muted2); transition:color 220ms ease;
}
.v2x.atd .atd-facts .k > i{
  flex:0 0 auto; width:15px; text-align:center; font-size:.78rem;
  color:var(--muted2); opacity:.75; transition:color 220ms ease, opacity 220ms ease, transform 320ms cubic-bezier(.16,1,.3,1);
}
.v2x.atd .atd-facts .v{
  color:var(--ink); font-weight:600; text-align:end; min-width:0;
  margin-inline-start:auto;
  display:inline-flex; align-items:center; justify-content:flex-end; gap:7px; flex-wrap:wrap;
}
.v2x.atd .atd-facts .v.mono{ font-family:var(--mono); font-size:.82rem; }
.v2x.atd .atd-facts .v .cat-ic{ color:var(--accent); font-size:.82rem; }
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-facts li:hover{ background:var(--accent-soft2); }
  .v2x.atd .atd-facts li:hover .k{ color:var(--muted); }
  .v2x.atd .atd-facts li:hover .k > i{ color:var(--accent); opacity:1; transform:scale(1.12); }
}

/* Value pills — Yes/No and the pricing model. A bare "Yes" reads identically
   to a data value like "2022"; a pill gives it semantic weight. */
.v2x.atd .atd-fpill{
  display:inline-flex; align-items:center; gap:5px;
  padding:3px 10px; border-radius:var(--r-pill);
  font-family:var(--font); font-size:.76rem; font-weight:700; letter-spacing:.01em;
  border:1px solid transparent; white-space:nowrap;
}
.v2x.atd .atd-fpill i{ font-size:.6rem; }
.v2x.atd .atd-fpill.is-yes{ background:#e8faf0; color:#0E7A55; border-color:#bdecd4; }
.v2x.atd .atd-fpill.is-no{ background:#f3f4f7; color:#6B7280; border-color:#e3e6ec; }
.v2x.atd .atd-fpill.is-green{ background:#e8faf0; color:#0E7A55; border-color:#bdecd4; }
.v2x.atd .atd-fpill.is-violet{ background:#f3eefe; color:#6d28d9; border-color:#e2d6fb; }
.v2x.atd .atd-fpill.is-blue{ background:var(--accent-soft); color:var(--accent-dark); border-color:#d6e4fc; }
.v2x.atd .atd-fpill.is-amber{ background:#fff7e6; color:#a4560a; border-color:#fde9c8; }
.v2x.atd .atd-fpill.is-slate{ background:#f3f4f7; color:#4A4A5A; border-color:#e3e6ec; }

/* Mobile-app OS marks — real chips instead of two bare glyphs. */
.v2x.atd .atd-fos{
  width:24px; height:24px; border-radius:7px;
  display:inline-flex; align-items:center; justify-content:center;
  background:#f3f4f7; border:1px solid #e3e6ec; color:#0F0F12; font-size:.76rem;
  transition:transform 300ms cubic-bezier(.16,1,.3,1), background-color 220ms ease;
}
.v2x.atd .atd-fos.is-android{ color:#0d8f4f; }
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-facts li:hover .atd-fos{ transform:translateY(-1px); }
}

/* Links in the value column. `.card a:hover` is declared sitewide in an inline
   <style> at (0,2,0) and wins ties on source order, so the hover colour is
   pinned at (0,4,1) here rather than left to inherit. */
.v2x.atd .atd-facts .v a,
.v2x.atd .atd-facts .v .atd-flink{
  color:var(--accent); display:inline-flex; align-items:center; gap:6px;
  text-decoration:none; border-bottom:1px solid transparent;
  transition:color 200ms ease, border-color 200ms ease;
}
.v2x.atd .atd-facts .v a:hover,
.v2x.atd .atd-facts .v .atd-flink:hover{
  color:var(--accent-dark); text-decoration:none; border-bottom-color:currentColor;
}
.v2x.atd .atd-flink.is-ext svg{ opacity:.6; transition:transform 300ms cubic-bezier(.16,1,.3,1), opacity 200ms ease; }
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-flink.is-ext:hover svg{ opacity:1; transform:translate(2px,-2px); }
}

/* Live status — dot breathes so "Active" reads as a live signal. */
.v2x.atd .atd-status-on{
  display:inline-flex; align-items:center; gap:7px;
  padding:3px 10px 3px 8px; border-radius:var(--r-pill);
  background:#e8faf0; border:1px solid #bdecd4;
  color:#0E7A55; font-weight:700; font-size:.76rem; white-space:nowrap;
}
.v2x.atd .atd-status-on .dot{
  width:7px; height:7px; border-radius:50%; background:var(--green); flex:0 0 auto;
  animation:atdLive 2.4s ease-out infinite;
}
@keyframes atdLive{
  0%{ box-shadow:0 0 0 0 rgba(34,197,94,.55); }
  70%{ box-shadow:0 0 0 6px rgba(34,197,94,0); }
  100%{ box-shadow:0 0 0 0 rgba(34,197,94,0); }
}

@media (max-width:400px){
  /* Very narrow: stack label over value so neither ever competes for width. */
  .v2x.atd .atd-facts li{ gap:4px; }
  .v2x.atd .atd-facts .v{ margin-inline-start:0; justify-content:flex-start; text-align:start; width:100%; }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-facts li,.v2x.atd .atd-facts .k,.v2x.atd .atd-facts .k > i,
  .v2x.atd .atd-fos,.v2x.atd .atd-side-ic,.v2x.atd .atd-flink.is-ext svg{ transition:none !important; }
  .v2x.atd .atd-status-on .dot{ animation:none; }
  .v2x.atd .atd-facts li:hover .k > i,.v2x.atd .atd-info:hover .atd-side-ic{ transform:none; }
}

/* Dark twins */
body.theme-dark .v2x.atd .atd-facts li:hover{ background:rgba(54,128,237,.10); }
body.theme-dark .v2x.atd .atd-fpill.is-yes,
body.theme-dark .v2x.atd .atd-fpill.is-green{ background:rgba(34,197,94,.16); color:#6EE7B7; border-color:rgba(34,197,94,.32); }
body.theme-dark .v2x.atd .atd-fpill.is-no,
body.theme-dark .v2x.atd .atd-fpill.is-slate{ background:rgba(255,255,255,.07); color:#A8AEBF; border-color:var(--dk-line-strong,rgba(255,255,255,.16)); }
body.theme-dark .v2x.atd .atd-fpill.is-violet{ background:rgba(139,92,246,.18); color:#C4B5FD; border-color:rgba(139,92,246,.34); }
body.theme-dark .v2x.atd .atd-fpill.is-blue{ background:rgba(54,128,237,.18); color:#9CC5F9; border-color:rgba(54,128,237,.34); }
body.theme-dark .v2x.atd .atd-fpill.is-amber{ background:rgba(245,158,11,.18); color:#F4C160; border-color:rgba(245,158,11,.34); }
body.theme-dark .v2x.atd .atd-fos{ background:rgba(255,255,255,.07); border-color:var(--dk-line-strong,rgba(255,255,255,.16)); color:var(--dk-text,#F4F5F7); }
body.theme-dark .v2x.atd .atd-fos.is-android{ color:#3ddc84; }
body.theme-dark .v2x.atd .atd-status-on{ background:rgba(34,197,94,.16); border-color:rgba(34,197,94,.32); color:#6EE7B7; }
body.theme-dark .v2x.atd .atd-facts .v a,
body.theme-dark .v2x.atd .atd-facts .v .atd-flink{ color:#7FB4F7; }
body.theme-dark .v2x.atd .atd-facts .v a:hover,
body.theme-dark .v2x.atd .atd-facts .v .atd-flink:hover{ color:#9CC5F9; }

/* Best For chips — brand-tinted per design.md */

/* ==========================================================================
   §CHIPS) ONE geometry, TWO behaviours.

   `.is-static` (Best For) DESCRIBES the tool — not a link, so it gets no lift
   and no pointer. `.is-links` (Tags) navigates to /ai-directory/tag/{slug}, so
   it is outlined at rest and fills solid on hover. Before this the two shared
   a single class and were pixel-identical, which advertised a hover
   affordance on chips that do nothing.

   Tone is carried by --t / --t-bg / --t-bd (set by .c0–.c5 further down), so
   one rule set drives both variants and adding a tone is three values.
   ========================================================================== */
.v2x.atd .atd-tags{ display:flex; flex-wrap:wrap; gap:8px; }
.v2x.atd .atd-tag{
  display:inline-flex; align-items:center; gap:7px;
  font-family:var(--font); font-size:.8rem; font-weight:600; line-height:1.3;
  border-radius:var(--r-pill); padding:6px 13px;
  border:1px solid transparent; text-decoration:none;
  transition:background-color 200ms ease, color 200ms ease, border-color 200ms ease,
             transform 300ms cubic-bezier(.16,1,.3,1), box-shadow 300ms ease;
}

.v2x.atd .atd-tags.is-static .atd-tag{
  background:var(--t-bg); color:var(--t); border-color:var(--t-bd); cursor:default;
}
.v2x.atd .atd-tags.is-links .atd-tag{
  background:transparent; color:var(--t); border-color:var(--t-bd);
}
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-tags.is-links .atd-tag:hover{
    background:var(--t); color:#fff; border-color:var(--t);
    transform:translateY(-2px); text-decoration:none;
    box-shadow:0 6px 14px color-mix(in srgb, var(--t) 34%, transparent);
  }
}
@supports not (color: color-mix(in srgb, red 50%, transparent)){
  @media (hover:hover) and (pointer:fine){
    .v2x.atd .atd-tags.is-links .atd-tag:hover{ box-shadow:0 6px 14px rgba(15,23,42,.20); }
  }
}
body:not(.admin-shell) .v2x.atd .atd-tags.is-links .atd-tag:focus-visible{
  outline:none; border-radius:var(--r-pill);
  box-shadow:0 0 0 3px rgba(54,128,237,.85), 0 0 0 6px rgba(54,128,237,.22);
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-tag{ transition:none !important; }
  .v2x.atd .atd-tags.is-links .atd-tag:hover{ transform:none; }
}

/* ==========================================================================
   §ALT) Alternative rows.

   ⚠️ `.nm` and `.sub` used to carry `white-space:nowrap` + `text-overflow:
   ellipsis`, so any tool name longer than the column was silently CLIPPED.
   They wrap now — nothing in this card truncates.
   ========================================================================== */
.v2x.atd .atd-alt{
  position:relative;
  display:flex; align-items:center; gap:12px;
  padding:10px; margin-inline:-2px; border-radius:12px;
  border:1px solid transparent; color:inherit; text-decoration:none;
  transition:background-color 220ms ease, border-color 220ms ease,
             transform 300ms cubic-bezier(.16,1,.3,1), box-shadow 300ms ease;
}
.v2x.atd .atd-alt .lg,
.v2x.atd .atd-alt img{
  width:40px; height:40px; border-radius:11px; flex-shrink:0; object-fit:contain;
  display:flex; align-items:center; justify-content:center;
  background:var(--accent-soft); color:var(--accent-dark);
  font-family:var(--font); font-weight:700; border:1px solid var(--line);
  transition:transform 340ms cubic-bezier(.16,1,.3,1), box-shadow 300ms ease;
}
.v2x.atd .atd-alt .inf{ flex:1 1 auto; min-width:0; }
.v2x.atd .atd-alt .nm{
  display:block; font-family:var(--font); font-weight:700; font-size:.92rem;
  color:var(--ink); line-height:1.3; overflow-wrap:anywhere;
  transition:color 200ms ease;
}
.v2x.atd .atd-alt .sub{
  display:block; font-size:.78rem; color:var(--muted2); line-height:1.4;
  margin-top:1px; overflow-wrap:anywhere;
}
.v2x.atd .atd-alt .rt{ display:inline-flex; align-items:center; gap:8px; flex:0 0 auto; }
/* Rating as an amber pill. The old `.rt .fa-star{color:var(--amber)}` matched
   nothing once the markup moved to the x-lucide component, so the star
   rendered in currentColor — i.e. black.
   (Angle brackets omitted on purpose: Blade compiles an x- tag even inside a
   CSS comment. See the note at the top of §CLAIM.) */
.v2x.atd .atd-rate{
  display:inline-flex; align-items:center; gap:5px;
  padding:3px 9px; border-radius:var(--r-pill);
  background:#fff7e6; border:1px solid #fde0b4; color:#a4560a;
  font-family:var(--font); font-size:.78rem; font-weight:700;
  font-variant-numeric:tabular-nums; white-space:nowrap;
}
.v2x.atd .atd-rate .fa-star{ color:var(--gold); font-size:.68rem; }
.v2x.atd .atd-alt .go{
  color:#aeb6c2; font-size:.68rem; flex:0 0 auto;
  transition:transform 320ms cubic-bezier(.16,1,.3,1), color 200ms ease;
}
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-alt:hover{
    background:var(--accent-soft2); border-color:#d9e6fb;
    transform:translateY(-2px); box-shadow:0 8px 18px rgba(54,128,237,.14);
    text-decoration:none;
  }
  .v2x.atd .atd-alt:hover .nm{ color:var(--accent-dark); }
  .v2x.atd .atd-alt:hover .lg,
  .v2x.atd .atd-alt:hover img{ transform:scale(1.06); box-shadow:0 5px 12px rgba(32,96,192,.20); }
  .v2x.atd .atd-alt:hover .go{ transform:translateX(3px); color:var(--accent); }
}
body:not(.admin-shell) .v2x.atd .atd-alt:focus-visible{
  outline:none; border-radius:12px;
  box-shadow:0 0 0 3px rgba(54,128,237,.85), 0 0 0 6px rgba(54,128,237,.22);
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-alt,.v2x.atd .atd-alt .lg,.v2x.atd .atd-alt img,.v2x.atd .atd-alt .go{ transition:none !important; }
  .v2x.atd .atd-alt:hover{ transform:none; }
  .v2x.atd .atd-alt:hover .lg,.v2x.atd .atd-alt:hover img,.v2x.atd .atd-alt:hover .go{ transform:none; }
}
body.theme-dark .v2x.atd .atd-rate{ background:rgba(245,158,11,.16); border-color:rgba(245,158,11,.34); color:#F4C160; }
@media (hover:hover) and (pointer:fine){
  body.theme-dark .v2x.atd .atd-alt:hover{ background:rgba(54,128,237,.10); border-color:rgba(54,128,237,.34); box-shadow:0 8px 20px rgba(0,0,0,.45); }
  body.theme-dark .v2x.atd .atd-alt:hover .nm{ color:#9CC5F9; }
}

/* Popular comparisons */
.v2x.atd .atd-comp{
  display:flex; align-items:center; gap:12px; padding:11px 8px; border-radius:var(--r-card);
  font-size:.9rem; color:var(--ink); transition:background 150ms ease,transform 150ms ease;
}
.v2x.atd .atd-comp:hover{ background:var(--accent-soft2); transform:translateX(2px); color:var(--accent); text-decoration:none; }
.v2x.atd .atd-comp .lg{
  width:30px; height:30px; border-radius:8px; flex-shrink:0; object-fit:contain;
  display:flex; align-items:center; justify-content:center;
  background:var(--accent-soft); color:var(--accent); font-size:.8rem;
}
.v2x.atd .atd-comp .vs{ color:var(--muted2); font-size:.78rem; font-weight:500; margin-inline:2px; }
.v2x.atd .atd-comp b{ font-weight:600; }
.v2x.atd .atd-comp .fa-chevron-right{ margin-left:auto; color:#aeb6c2; font-size:.68rem; }

/* Share — round brand-coloured buttons */
/* ── Share buttons. Each carries its platform colour in --soc, which also
      drives the hover glow and the halo ring, so one rule set covers all five
      and adding a network is a single line. --- */
.v2x.atd .atd-share-sub{ font-size:.88rem; color:var(--muted); margin:0 0 14px; line-height:1.55; }
.v2x.atd .atd-socials{ display:flex; gap:10px; flex-wrap:wrap; }
.v2x.atd .atd-soc{
  position:relative; isolation:isolate;
  width:44px; height:44px; border-radius:50%;
  display:inline-flex; align-items:center; justify-content:center;
  background:var(--soc,var(--accent)); color:#fff; font-size:.95rem;
  border:0; cursor:pointer; text-decoration:none;
  box-shadow:0 2px 6px rgba(15,23,42,.12);
  transition:transform 320ms cubic-bezier(.16,1,.3,1), box-shadow 320ms ease, filter 220ms ease;
}
.v2x.atd .atd-soc > *{ position:relative; z-index:1; }
.v2x.atd .atd-soc svg{ width:17px; height:17px; }
/* Halo — expands and fades on hover, same motion language as the gallery play
   control so the page reads as one system. */
.v2x.atd .atd-soc::after{
  content:''; position:absolute; inset:-4px; z-index:0; border-radius:50%;
  border:2px solid var(--soc,var(--accent)); opacity:0; transform:scale(.86);
  transition:transform 420ms cubic-bezier(.16,1,.3,1), opacity 320ms ease;
}
.v2x.atd .atd-soc-fb{ --soc:#1877F2; }
.v2x.atd .atd-soc-tw{ --soc:#0F0F12; }
.v2x.atd .atd-soc-li{ --soc:#0A66C2; }
.v2x.atd .atd-soc-wa{ --soc:#25D366; }
.v2x.atd .atd-soc-ln{ --soc:#3680ED; }
/* Copy confirmed — green, because --red/--danger are remapped to brand blue in
   this theme and a blue tick would be indistinguishable from the resting pill. */
.v2x.atd .atd-soc.is-copied{ --soc:#12A66F; transform:none; }
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-soc:hover{
    transform:translateY(-3px) scale(1.04); color:#fff; text-decoration:none;
    filter:saturate(1.08);
    box-shadow:0 10px 22px color-mix(in srgb, var(--soc,#3680ED) 42%, transparent);
  }
  .v2x.atd .atd-soc:hover::after{ opacity:.42; transform:scale(1); }
}
@supports not (color: color-mix(in srgb, red 50%, transparent)){
  @media (hover:hover) and (pointer:fine){
    .v2x.atd .atd-soc:hover{ box-shadow:0 10px 22px rgba(15,23,42,.28); }
  }
}
body:not(.admin-shell) .v2x.atd .atd-soc:focus-visible{
  outline:none; border-radius:50%;
  box-shadow:0 0 0 3px rgba(54,128,237,.85), 0 0 0 6px rgba(54,128,237,.24);
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-soc,.v2x.atd .atd-soc::after{ transition:none !important; }
  .v2x.atd .atd-soc:hover{ transform:none; }
}
/* Dark: the near-black X mark would disappear against the panel. */
body.theme-dark .v2x.atd .atd-soc{ box-shadow:none; }
body.theme-dark .v2x.atd .atd-soc-tw{ --soc:#3A3F4D; }
@media (hover:hover) and (pointer:fine){
  body.theme-dark .v2x.atd .atd-soc:hover{ box-shadow:0 10px 24px rgba(0,0,0,.55); }
}

/* Affiliate disclosure (if present) */
.v2x.atd .atd-disclosure{ background:var(--bg); border:1px dashed var(--line-strong); border-radius:var(--r-card); padding:16px; font-size:.8rem; color:var(--muted2); line-height:1.6; }


/* ==========================================================================
   Motion preferences — disable decorative motion entirely
   ========================================================================== */
@media (prefers-reduced-motion:reduce){
  .v2x.atd *,.v2x.atd *::before,.v2x.atd *::after{
    animation-duration:.01ms !important; animation-iteration-count:1 !important;
    transition-duration:.01ms !important; scroll-behavior:auto !important;
  }
}

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width:1199.98px){
  .v2x.atd .atd-caps{ grid-template-columns:repeat(3,1fr); gap:18px 12px; }
}
@media (max-width:991.98px){
  .v2x.atd .atd-sidebar{ position:static; top:auto; }
  .v2x.atd .atd-feats{ grid-template-columns:1fr; }
}
@media (max-width:767.98px){
  /* `flex-direction` on .atd-hero-head went with the block above: §HERO-X
     makes that element a GRID, where the property has no effect at all. */
  .v2x.atd .atd-caps{ grid-template-columns:repeat(2,1fr); }
}
@media (max-width:575.98px){
  /* The 84px phone tile that used to be set here is also §HERO-X's now
     (--atd-logo, in the responsive ramp at the end of that section). */
  .v2x.atd .atd-hero{ padding:18px; }
  /* The 1.7rem H1 that sat here is §HERO-X's too (1.5rem at this breakpoint,
     1.34rem under 400px) — it was overridden and never painted. */
  .v2x.atd .atd-cta-row,.v2x.atd .atd-cta-col{ width:100%; }
  .v2x.atd .atd-cta-row .v2-btn,
  .v2x.atd .atd-cta-row .atd-btn{ width:100%; }
  .v2x.atd .v2-card.pad{ padding:18px; }
  /* Phone: the two actions split the row evenly instead of hugging the left
     edge with dead space beside them. flex-basis:0 makes the split even
     regardless of label length, so "Add to favorites" cannot starve "Share".
     Both keep their full label — nothing is truncated or icon-only. */
  .v2x.atd .atd-topbar-actions{ width:100%; justify-content:stretch; gap:8px; flex-wrap:nowrap; }
  .v2x.atd .atd-pillbtn{ flex:1 1 0; min-width:0; padding:0 12px; font-size:.83rem; gap:7px; }
  .v2x.atd .atd-pillbtn span{ overflow:hidden; text-overflow:ellipsis; }
}

/* ════════════════ FEEDBACK PASS — premium additions ════════════════ */
.v2x.atd .atd-chip{ align-items:center; }
.v2x.atd .atd-chip .lcd,.v2x.atd .atd-chip svg{ flex:none; }

/* Premium breadcrumbs — soft pill trail */
body.v2-host .seo-breadcrumbs .breadcrumb,body:has(.v2x) .seo-breadcrumbs .breadcrumb{ display:flex; flex-wrap:wrap; gap:6px; align-items:center; padding:0; margin:0; background:transparent; }
body.v2-host .seo-breadcrumbs .breadcrumb-item,body:has(.v2x) .seo-breadcrumbs .breadcrumb-item{ display:inline-flex; align-items:center; }
body.v2-host .seo-breadcrumbs .breadcrumb-item a,body:has(.v2x) .seo-breadcrumbs .breadcrumb-item a{ display:inline-flex; align-items:center; gap:5px; padding:5px 12px; border-radius:999px; background:#fff; border:1px solid #e7eaf1; color:#4A4A5A; font-weight:500; font-size:.82rem; transition:all .15s ease; text-decoration:none; }
body.v2-host .seo-breadcrumbs .breadcrumb-item a:hover,body:has(.v2x) .seo-breadcrumbs .breadcrumb-item a:hover{ border-color:#3680ED; color:#3680ED; background:#eef4fe; transform:translateY(-1px); }
body.v2-host .seo-breadcrumbs .breadcrumb-item.active,body:has(.v2x) .seo-breadcrumbs .breadcrumb-item.active{ padding:5px 12px; border-radius:999px; background:#eef4fe; color:#2060C0; font-weight:700; font-size:.82rem; }
body.v2-host .seo-breadcrumbs .breadcrumb-item+.breadcrumb-item::before,body:has(.v2x) .seo-breadcrumbs .breadcrumb-item+.breadcrumb-item::before{ content:"\203A"; color:#c2c8d4; padding:0 1px; }

/* Best For — multi-colour pills */
/* Tone ramp — ink / soft fill / border. The solid `--t` doubles as the hover
   fill for link chips, so each was checked against WHITE ink: 6.5 · 4.9 · 7.4
   · 6.0 · 4.9 · 4.9 — all clear AA for text (4.5:1). */
.v2x.atd .atd-tag.c0{ --t:#2060C0; --t-bg:#e7f1ff; --t-bd:#cbdefb; }
.v2x.atd .atd-tag.c1{ --t:#15803d; --t-bg:#e9f9ef; --t-bd:#c4ecd5; }
.v2x.atd .atd-tag.c2{ --t:#6d28d9; --t-bg:#f3edff; --t-bd:#ddcdfb; }
.v2x.atd .atd-tag.c3{ --t:#be185d; --t-bg:#fdeaf3; --t-bd:#f8cede; }
.v2x.atd .atd-tag.c4{ --t:#b45309; --t-bg:#fff2dd; --t-bd:#fbdfb4; }
.v2x.atd .atd-tag.c5{ --t:#0e7490; --t-bg:#e6fbfa; --t-bd:#bdeeeb; }

/* Platforms / integrations / languages / changelog */
/* ── Platform cards. The glyph moves into a tinted chip that fills with the
      brand gradient on hover, so the whole tile reads as one control rather
      than an icon sitting next to some text. --- */
.v2x.atd .atd-plats{ display:flex; flex-wrap:wrap; gap:9px; }
.v2x.atd .atd-plat{
  position:relative;
  display:inline-flex; align-items:center; gap:9px;
  padding:8px 13px 8px 8px; border:1px solid var(--line); border-radius:12px;
  background:#fff; font-size:.86rem; font-weight:600; color:var(--ink);
  text-decoration:none; min-width:0;
  transition:border-color 220ms ease, color 220ms ease, box-shadow 300ms ease,
             transform 300ms cubic-bezier(.16,1,.3,1);
}
.v2x.atd .atd-plat-ic{
  flex:0 0 auto; width:28px; height:28px; border-radius:8px;
  display:inline-flex; align-items:center; justify-content:center;
  background:var(--accent-soft); color:var(--accent-dark); font-size:.88rem;
  transition:background 260ms ease, color 220ms ease, transform 340ms cubic-bezier(.16,1,.3,1);
}
.v2x.atd .atd-plat-l{ min-width:0; }        /* labels wrap, never truncate */
.v2x.atd .atd-plat i{ font-size:1em; line-height:1; }
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-plat:hover{
    border-color:rgba(54,128,237,.55); color:var(--accent-dark);
    transform:translateY(-2px); box-shadow:0 8px 18px rgba(54,128,237,.18); text-decoration:none;
  }
  .v2x.atd .atd-plat:hover .atd-plat-ic{
    background:linear-gradient(135deg,#4C8DF2,#2060C0); color:#fff; transform:scale(1.06);
  }
}
body:not(.admin-shell) .v2x.atd .atd-plat.is-link:focus-visible{
  outline:none; border-radius:12px;
  box-shadow:0 0 0 3px rgba(54,128,237,.85), 0 0 0 6px rgba(54,128,237,.22);
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-plat,.v2x.atd .atd-plat-ic{ transition:none !important; }
  .v2x.atd .atd-plat:hover{ transform:none; }
  .v2x.atd .atd-plat:hover .atd-plat-ic{ transform:none; }
}
/* Integrations: rebuilt as §INTEG at the end of this file. The five rules
   that stood here were not merely restyled -- `.nm` clipped its own text
   with an ellipsis and `.lg` / `.atd-integ img` sized a plate the new
   markup no longer has, so leaving them would have re-truncated the names
   this pass exists to un-truncate. */
/* ── Language pills. Static (not links), so no lift — just a quiet brand
      response so the flag row doesn't read as dead weight. --- */
.v2x.atd .atd-langs{ display:flex; flex-wrap:wrap; gap:8px; }
.v2x.atd .atd-langpill{
  display:inline-flex; align-items:center; gap:7px;
  padding:6px 13px 6px 8px; border:1px solid var(--line); border-radius:var(--r-pill);
  background:#fff; font-size:.82rem; font-weight:600; color:var(--ink);
  line-height:1.35; cursor:default;
  transition:background-color 220ms ease, border-color 220ms ease;
}
.v2x.atd .atd-langpill .lcd{ color:var(--accent); }
.v2x.atd .atd-langpill img,
.v2x.atd .atd-langpill svg{ flex:0 0 auto; border-radius:3px; }
.v2x.atd .atd-langpill-l{ min-width:0; }   /* long names wrap, never clip */
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-langpill:hover{ background:var(--accent-soft2); border-color:#cbdefb; }
}
@media (prefers-reduced-motion:reduce){ .v2x.atd .atd-langpill{ transition:none !important; } }
/* What's New: rebuilt as §CHLOG at the end of this file. `.atd-changelog` /
   `.atd-chlog` are gone from the markup, so these nine rules matched
   nothing after the rebuild. `.atd-utype` below is still live -- the new
   timeline keeps the pill and its five measured tone pairs. */
.v2x.atd .atd-utype{ font-size:.64rem; font-weight:700; text-transform:uppercase; letter-spacing:.04em; padding:2px 8px; border-radius:999px; }
.v2x.atd .atd-utype.feature{ background:#e9f9ef; color:#15803d; }
.v2x.atd .atd-utype.fix{ background:#e7f1ff; color:#2060C0; }
.v2x.atd .atd-utype.pricing{ background:#fff2dd; color:#b45309; }
.v2x.atd .atd-utype.announcement{ background:#f3edff; color:#6d28d9; }
.v2x.atd .atd-utype.other{ background:#eef1f6; color:#475061; }

/* Premium review card */
.v2x.atd .atd-reviews-grid{ display:grid; grid-template-columns:1fr 1fr; gap:14px; }
@media (max-width:680px){ .v2x.atd .atd-reviews-grid{ grid-template-columns:1fr; } }
.v2x.atd .atd-review{ border:1px solid var(--line); border-radius:14px; padding:18px; background:#fff; height:100%; transition:box-shadow .2s ease,transform .2s ease,border-color .2s; display:flex; flex-direction:column; gap:10px; }
.v2x.atd .atd-review:hover{ box-shadow:var(--sh-md); transform:translateY(-2px); border-color:rgba(54,128,237,.3); }
.v2x.atd .atd-review .rv-head{ display:flex; align-items:center; gap:11px; }
.v2x.atd .atd-review .rv-av{ width:42px; height:42px; border-radius:50%; flex:none; display:flex; align-items:center; justify-content:center; font-weight:800; color:#fff; font-size:1rem; }
.v2x.atd .atd-review .rv-nm{ font-weight:700; font-size:.92rem; display:flex; align-items:center; gap:5px; }
.v2x.atd .atd-review .rv-dt{ font-size:.74rem; color:var(--muted2); }
.v2x.atd .atd-review .rv-body{ font-size:.9rem; color:var(--muted); line-height:1.6; margin:0; flex:1; }
.v2x.atd .atd-review .rv-foot{ display:flex; align-items:center; gap:14px; font-size:.82rem; padding-top:8px; border-top:1px solid var(--line); }
.v2x.atd .atd-review .rv-act{ display:inline-flex; align-items:center; gap:6px; color:var(--muted); cursor:pointer; background:none; border:0; padding:0; text-decoration:none; }
.v2x.atd .atd-review .rv-act:hover{ color:var(--accent); }
.v2x.atd .atd-review .rv-act.on{ color:var(--accent); font-weight:700; }
.v2x.atd .atd-rsummary{ display:flex; align-items:center; gap:24px; flex-wrap:wrap; padding:6px 0 4px; }
.v2x.atd .atd-rsummary .big{ font-size:3.2rem; font-weight:800; line-height:1; letter-spacing:-.02em; background:linear-gradient(120deg,var(--accent-dark),var(--accent) 60%,var(--accent-light)); -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent; }
.v2x.atd .atd-rbar{ display:flex; align-items:center; gap:9px; margin-bottom:5px; }
.v2x.atd .atd-rbar .lab{ font-size:.78rem; color:var(--muted); width:44px; display:inline-flex; align-items:center; gap:3px; }
.v2x.atd .atd-rbar .track{ flex:1; height:8px; border-radius:999px; background:#eef1f6; overflow:hidden; }
.v2x.atd .atd-rbar .fill{ height:100%; border-radius:999px; background:linear-gradient(90deg,var(--amber),#fbbf24); }
.v2x.atd .atd-rbar .pct{ font-size:.78rem; color:var(--muted); width:40px; text-align:right; }

/* Upvote — social-style pill; green gradient + pop when voted */
/* ⚠️ SUPERSEDED by §UPVOTE at the end of this file, which restates every
   declaration below at equal-or-higher specificity and later in source order,
   and which the three-slot icon track in `tool/hero.blade.php` depends on.
   This block is what a grep for `atd-upvote` finds FIRST; a change here will
   look correct and paint nothing. Only `@keyframes atd-up-pop` / `atd-up-sheen`
   and the `.just-voted` pop still land from here. Edit §UPVOTE. */
.v2x.atd .atd-upvote{
  position:relative; display:inline-flex; align-items:center; gap:9px;
  padding:10px 14px 10px 20px; border:1.5px solid var(--line-strong); border-radius:var(--r-btn);
  background:#fff; color:var(--ink); font-weight:700; font-size:.97rem; line-height:1.2;
  cursor:pointer; overflow:hidden; -webkit-tap-highlight-color:transparent;
  transition:border-color .2s ease, color .2s ease, background .2s ease, transform .2s ease, box-shadow .2s ease;
}
.v2x.atd .atd-upvote .lcd,
.v2x.atd .atd-upvote svg{ transition:transform .25s cubic-bezier(.34,1.56,.64,1); }
.v2x.atd .atd-upvote .lbl{ letter-spacing:.01em; }
/* count badge */
.v2x.atd .atd-upvote .cnt{
  display:inline-flex; align-items:center; justify-content:center; min-width:26px; height:26px;
  padding:0 8px; border-radius:999px; background:var(--accent-soft); color:var(--accent);
  font-size:.82rem; font-weight:800; transition:background .2s ease, color .2s ease, transform .25s cubic-bezier(.34,1.56,.64,1);
}
/* hover (not yet voted) */
.v2x.atd .atd-upvote:not(.voted):hover{
  border-color:var(--accent); color:var(--accent); background:var(--accent-soft);
  transform:translateY(-2px); box-shadow:0 8px 18px rgba(54,128,237,.18);
}
.v2x.atd .atd-upvote:not(.voted):hover svg,
.v2x.atd .atd-upvote:not(.voted):hover .lcd{ transform:translateY(-3px); }
.v2x.atd .atd-upvote:not(.voted):hover .cnt{ background:#fff; }
.v2x.atd .atd-upvote:active{ transform:translateY(0) scale(.97); }
/* VOTED — green gradient, glow, pop + sheen sweep */
.v2x.atd .atd-upvote.voted{
  border-color:transparent; color:#fff; cursor:default;
  background:linear-gradient(135deg,#15a34a,#22c55e 55%,#4ade80);
  box-shadow:0 8px 22px rgba(34,197,94,.42), inset 0 1px 0 rgba(255,255,255,.25);
}
.v2x.atd .atd-upvote.voted svg,
.v2x.atd .atd-upvote.voted .lcd{ color:#fff; transform:translateY(-2px); }
.v2x.atd .atd-upvote.voted .cnt{ background:rgba(255,255,255,.22); color:#fff; }
/* pop + sheen fire ONLY on the real click (atdUpvote adds .just-voted), never on reload */
.v2x.atd .atd-upvote.just-voted{ animation:atd-up-pop .42s cubic-bezier(.34,1.56,.64,1); }
.v2x.atd .atd-upvote.just-voted::after{
  content:""; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
  background:linear-gradient(120deg,transparent 20%,rgba(255,255,255,.45) 50%,transparent 80%);
  transform:translateX(-120%); animation:atd-up-sheen .7s ease .05s 1;
}
@keyframes atd-up-pop{ 0%{transform:scale(.9)} 45%{transform:scale(1.08)} 100%{transform:scale(1)} }
@keyframes atd-up-sheen{ to{ transform:translateX(120%) } }
@media (prefers-reduced-motion: reduce){
  .v2x.atd .atd-upvote, .v2x.atd .atd-upvote svg, .v2x.atd .atd-upvote .lcd, .v2x.atd .atd-upvote .cnt{ transition:none; }
  .v2x.atd .atd-upvote.just-voted{ animation:none; }
  .v2x.atd .atd-upvote.just-voted::after{ display:none; }
}


/* ════════════════ Breadcrumbs — clean minimal trail (Inter), no pills ════════════════ */
body.v2-host .seo-breadcrumbs,body:has(.v2x) .seo-breadcrumbs{ font-family:'Inter',system-ui,-apple-system,'Segoe UI',Roboto,Arial,sans-serif !important; margin-bottom:18px; }
body.v2-host .seo-breadcrumbs .breadcrumb,body:has(.v2x) .seo-breadcrumbs .breadcrumb{ --bs-breadcrumb-divider:''; display:flex; flex-wrap:wrap; align-items:center; gap:0; margin:0; padding:0; background:transparent; font-size:.84rem; line-height:1.5; }
body.v2-host .seo-breadcrumbs .breadcrumb-item,body:has(.v2x) .seo-breadcrumbs .breadcrumb-item{ display:inline-flex; align-items:center; font-family:inherit !important; }
/* neutralise the Bootstrap/Tabler default divider */
body.v2-host .seo-breadcrumbs .breadcrumb-item::before,body:has(.v2x) .seo-breadcrumbs .breadcrumb-item::before{ display:none !important; content:none !important; }
body.v2-host .seo-breadcrumbs .breadcrumb-item+.breadcrumb-item,body:has(.v2x) .seo-breadcrumbs .breadcrumb-item+.breadcrumb-item{ padding-left:0 !important; }
/* simple chevron separator */
body.v2-host .seo-breadcrumbs .breadcrumb-item+.breadcrumb-item::before,body:has(.v2x) .seo-breadcrumbs .breadcrumb-item+.breadcrumb-item::before{ display:inline-block !important; content:"\203A" !important; color:#b9c0cc; font-weight:500; padding:0 9px !important; margin:0 !important; border:0 !important; width:auto !important; height:auto !important; transform:none !important; float:none; }
/* links: plain muted text, no box/pill */
body.v2-host .seo-breadcrumbs .breadcrumb-item a,body:has(.v2x) .seo-breadcrumbs .breadcrumb-item a{ display:inline-flex; align-items:center; gap:5px; padding:0 !important; background:transparent !important; border:0 !important; border-radius:0 !important; box-shadow:none !important; color:#6b7280; font-weight:500; text-decoration:none; transition:color .15s ease; }
body.v2-host .seo-breadcrumbs .breadcrumb-item a:hover,body:has(.v2x) .seo-breadcrumbs .breadcrumb-item a:hover{ color:#3680ED; background:transparent !important; border-color:transparent !important; transform:none !important; }
/* current page: solid dark text, no gradient pill */
body.v2-host .seo-breadcrumbs .breadcrumb-item.active,body:has(.v2x) .seo-breadcrumbs .breadcrumb-item.active{ padding:0 !important; background:none !important; color:#0F0F12 !important; font-weight:600; box-shadow:none !important; border-radius:0 !important; }

/* Hero chips → gradient colourful badge pills */
.v2x.atd .atd-chip{ color:#fff !important; border:0 !important; font-weight:700; padding:7px 13px; box-shadow:0 3px 9px rgba(15,15,18,.10); transition:transform .15s ease; }
.v2x.atd .atd-chip:hover{ transform:translateY(-2px); }
.v2x.atd .atd-chip .lcd,.v2x.atd .atd-chip i,.v2x.atd .atd-chip svg{ color:#fff !important; }
.v2x.atd .atd-chip-green { background:linear-gradient(135deg,#16a34a,#34d058) !important; box-shadow:0 3px 9px rgba(34,197,94,.32) !important; }
.v2x.atd .atd-chip-blue  { background:linear-gradient(135deg,#2563eb,#3680ED) !important; box-shadow:0 3px 9px rgba(54,128,237,.32) !important; }
.v2x.atd .atd-chip-violet{ background:linear-gradient(135deg,#7c3aed,#a855f7) !important; box-shadow:0 3px 9px rgba(139,92,246,.32) !important; }
.v2x.atd .atd-chip-amber { background:linear-gradient(135deg,#ea580c,#f59e0b) !important; box-shadow:0 3px 9px rgba(245,158,11,.32) !important; }

/* ════════════════ Gallery video slides (videos shown first) ════════════════
   The slide itself owns the 16:9 window (see §GAL), so the embed just fills
   it absolutely — it no longer carries its own clamp() height, which used to
   give videos a different ratio from the screenshots beside them. */
.v2x.atd .atd-vid-slide{ display:block; padding:0; }
.v2x.atd .atd-vid-embed{ position:absolute; inset:0; background:#000; }
.v2x.atd .atd-vid-embed iframe,.v2x.atd .atd-vid-embed video{ position:absolute; inset:0; width:100%; height:100%; border:0; display:block; }
.v2x.atd .atd-gal-thumbs .atd-thumb-vid .atd-thumb-fill{ position:absolute; inset:0; background:linear-gradient(135deg,#1a1d27,#2a2f3e); display:block; }
.v2x.atd .atd-thumb-play{ position:absolute; inset:0; z-index:2; display:flex; align-items:center; justify-content:center; pointer-events:none; }
.v2x.atd .atd-thumb-play i{
  width:26px; height:26px; display:flex; align-items:center; justify-content:center;
  padding-left:2px; font-size:.66rem; color:#fff;
  background:linear-gradient(135deg,#4C8DF2,#2060C0);
  border:1.5px solid rgba(255,255,255,.85); border-radius:50%;
  box-shadow:0 3px 10px rgba(8,12,22,.42);
  transition:transform 280ms cubic-bezier(.16,1,.3,1);
}
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-gal-thumbs .swiper-slide:hover .atd-thumb-play i{ transform:scale(1.12); }
}

/* ════════════════ Platform pills as links (task: per-platform UTM link) ════════════════ */
.v2x.atd .atd-plat.is-link{ text-decoration:none; }
/* The trailing external-link chevron ONLY. This was written at `svg` when the
   chip held a Font Awesome <i>; now the platform mark is itself an inline SVG
   inside .atd-plat-ic, and the descendant selector dimmed the whole logo to
   45%. The chevron is a direct child, the mark is a grandchild. */
.v2x.atd .atd-plat.is-link > svg{ opacity:.45; margin-left:1px; }
.v2x.atd .atd-plat.is-link:hover > svg{ opacity:.9; }

/* ════════════════ Tool sidebar social accounts (end of Tool Information) ════════════════ */
.v2x.atd .atd-side-social-wrap{ margin-top:16px; padding-top:14px; border-top:1px solid var(--line); }
.v2x.atd .atd-side-social-label{ display:block; font-size:.72rem; font-weight:700; text-transform:uppercase; letter-spacing:.05em; color:var(--muted); margin-bottom:10px; }
.v2x.atd .atd-side-socials{ display:flex; flex-wrap:wrap; gap:8px; }

/* Each button adopts its PLATFORM's colour on hover via --soc, set per class
   below. One rule set drives all nine — adding a network is one line. Ink is
   white on every fill; the darkest measured pair is Reddit at 3.2:1, which
   clears the 3:1 floor for non-text content (WCAG 1.4.11). */
.v2x.atd .atd-side-soc{
  position:relative; overflow:hidden;
  width:40px; height:40px; border-radius:11px;
  border:1px solid var(--line); background:#fff; color:var(--ink);
  display:inline-flex; align-items:center; justify-content:center;
  transition:transform 300ms cubic-bezier(.16,1,.3,1), border-color 220ms ease,
             color 220ms ease, box-shadow 300ms ease;
}
.v2x.atd .atd-side-soc > *{ position:relative; z-index:1; }
.v2x.atd .atd-side-soc::before{
  content:''; position:absolute; inset:0; z-index:0; border-radius:inherit;
  background:var(--soc,var(--accent)); opacity:0; transform:scale(.7);
  transition:opacity 240ms ease, transform 340ms cubic-bezier(.16,1,.3,1);
}
.v2x.atd .atd-side-soc i{ font-size:1rem; line-height:1; }
.v2x.atd .atd-side-soc svg{ width:15px; height:15px; }

.v2x.atd .atd-side-soc-x{ --soc:#0F0F12; }
.v2x.atd .atd-side-soc-linkedin{ --soc:#0A66C2; }
.v2x.atd .atd-side-soc-youtube{ --soc:#FF0000; }
.v2x.atd .atd-side-soc-github{ --soc:#24292F; }
.v2x.atd .atd-side-soc-instagram{ --soc:#DD2A7B; }
.v2x.atd .atd-side-soc-facebook{ --soc:#1877F2; }
.v2x.atd .atd-side-soc-tiktok{ --soc:#0F0F12; }
.v2x.atd .atd-side-soc-discord{ --soc:#5865F2; }
.v2x.atd .atd-side-soc-reddit{ --soc:#FF4500; }
/* Instagram is a gradient, not a flat hue — override the fill layer only. */
.v2x.atd .atd-side-soc-instagram::before{
  background:linear-gradient(135deg,#F58529 0%,#DD2A7B 52%,#8134AF 100%);
}

@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-side-soc:hover{
    transform:translateY(-3px); color:#fff; text-decoration:none;
    border-color:var(--soc,var(--accent));
    box-shadow:0 8px 18px color-mix(in srgb, var(--soc,#3680ED) 34%, transparent);
  }
  .v2x.atd .atd-side-soc:hover::before{ opacity:1; transform:scale(1); }
}
/* color-mix() is recent — fall back to a neutral lift where it is unsupported
   so the hover never loses its depth cue entirely. */
@supports not (color: color-mix(in srgb, red 50%, transparent)){
  @media (hover:hover) and (pointer:fine){
    .v2x.atd .atd-side-soc:hover{ box-shadow:0 8px 18px rgba(15,23,42,.22); }
  }
}
body:not(.admin-shell) .v2x.atd .atd-side-soc:focus-visible{
  outline:none; border-radius:11px;
  box-shadow:0 0 0 3px rgba(54,128,237,.85), 0 0 0 6px rgba(54,128,237,.24);
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-side-soc,.v2x.atd .atd-side-soc::before{ transition:none !important; }
  .v2x.atd .atd-side-soc:hover{ transform:none; }
}
/* Dark: the two near-black marks would vanish on a dark panel — lift them. */
body.theme-dark .v2x.atd .atd-side-soc{ background:var(--dk-surface-3,#1D1D22); border-color:var(--line); color:var(--dk-text,#F4F5F7); }
body.theme-dark .v2x.atd .atd-side-soc-x{ --soc:#3A3F4D; }
body.theme-dark .v2x.atd .atd-side-soc-tiktok{ --soc:#3A3F4D; }
body.theme-dark .v2x.atd .atd-side-soc-github{ --soc:#3A3F4D; }
.v2x.atd .atd-side-soc svg{ width:15px; height:15px; }

/* ==========================================================================
   DARK MODE — tool page follows the site-wide `body.theme-dark` switch.
   The isolation layer above forces a LIGHT canvas with !important; here we
   override it (higher specificity + !important) so the canvas, navbar and
   footer go dark too, then re-map the .v2x.atd tokens and flip every
   hardcoded #fff surface / light tint. Light mode is untouched.
   ========================================================================== */
/* 1 · Dark canvas + chrome (beats the forced-light isolation rules) */
body.theme-dark:has(.v2x){ background:var(--dk-bg,#0E0E11) !important; color:var(--dk-text,#F4F5F7) !important; }
body.theme-dark.v2-host{ background:var(--dk-bg,#0E0E11) !important; color:var(--dk-text,#F4F5F7) !important; }
body.theme-dark:has(.v2x) .navbar,
body.theme-dark.v2-host .navbar{ background:var(--dk-surface-2,#17171B) !important; border-bottom:1px solid var(--dk-line-solid,#2C2C31) !important; }
body.theme-dark:has(.v2x) .navbar .nav-link,
body.theme-dark:has(.v2x) .navbar .navbar-brand,
body.theme-dark.v2-host .navbar .nav-link,
body.theme-dark.v2-host .navbar .navbar-brand{ color:var(--dk-text,#F4F5F7) !important; }
body.theme-dark:has(.v2x) .footer,
body.theme-dark.v2-host .footer{ background:var(--dk-surface-2,#17171B) !important; border-top:1px solid var(--dk-line-solid,#2C2C31) !important; }
/* breadcrumb trail */
body.theme-dark:has(.v2x) .seo-breadcrumbs .breadcrumb-item a,
body.theme-dark.v2-host .seo-breadcrumbs .breadcrumb-item a{ color:var(--dk-text-3,#9AA0AB); }
body.theme-dark:has(.v2x) .seo-breadcrumbs .breadcrumb-item a:hover,
body.theme-dark.v2-host .seo-breadcrumbs .breadcrumb-item a:hover{ color:var(--dk-accent,#60A4F5); }
body.theme-dark:has(.v2x) .seo-breadcrumbs .breadcrumb-item.active,
body.theme-dark.v2-host .seo-breadcrumbs .breadcrumb-item.active{ color:var(--dk-text,#F4F5F7) !important; }
body.theme-dark:has(.v2x) .seo-breadcrumbs .breadcrumb-item+.breadcrumb-item::before,
body.theme-dark.v2-host .seo-breadcrumbs .breadcrumb-item+.breadcrumb-item::before{ color:var(--dk-text-4,#71767F); }

/* 2 · Token remap for the tool design system */
body.theme-dark .v2x.atd{
  /* --muted2 lifted #7E8499 -> #8E94A8. It measured 4.71:1 on a FLAT dark
     panel, which the wash added by §SPINE-WASH / §CARD-WASH takes to 4.22:1 on an
     amber sidebar card and 3.86:1 in a washed section — a regression the
     wash caused, so the wash pays for it. #8E94A8 measures 4.76-5.80:1
     across every washed ground and is still plainly fainter than --muted.
     Its LIGHT twin (#8a8a9a) is a separate, pre-existing failure: 3.40:1
     on a flat white card, i.e. under 4.5:1 before any of this. Left alone
     deliberately rather than re-toned as a side effect. */
  --ink:var(--dk-text,#F4F5F7); --muted:var(--dk-text-3,#9AA0AB); --muted2:#8E94A8;
  --line:var(--dk-line-solid,#2C2C31); --line-strong:var(--dk-line-solid-2,#3A3A42); --bg:var(--dk-surface,#131317);
  --accent-soft:rgba(54,128,237,.20); --accent-soft2:rgba(54,128,237,.10);
  --atd-surface:var(--dk-surface-2,#17171B);
  --sh-sm:0 1px 3px rgba(0,0,0,.55),0 1px 2px rgba(0,0,0,.45);
  --sh-md:0 4px 12px rgba(0,0,0,.55),0 2px 6px rgba(0,0,0,.40);
  --sh-lg:0 12px 26px rgba(0,0,0,.60),0 4px 10px rgba(0,0,0,.45);
  color:var(--ink);
}

/* 3 · Surfaces that hardcode #fff → dark panel */
body.theme-dark .v2x.atd .v2-card,
body.theme-dark .v2x.atd .v2-btn-outline,
body.theme-dark .v2x.atd .atd-btn-ghost,
body.theme-dark .v2x.atd .atd-pillbtn,
body.theme-dark .v2x.atd .atd-hero,
body.theme-dark .v2x.atd .atd-logo-tile,
body.theme-dark .v2x.atd .atd-gal-main,
body.theme-dark .v2x.atd .atd-gal-thumbs .swiper-slide,
body.theme-dark .v2x.atd .v2-feature,
body.theme-dark .v2x.atd .atd-plan,
body.theme-dark .v2x.atd .v2-toolcard,
body.theme-dark .v2x.atd .v2-accordion details,
body.theme-dark .v2x.atd .atd-plat,
body.theme-dark .v2x.atd .atd-review,
body.theme-dark .v2x.atd .atd-upvote,
body.theme-dark .v2x.atd .atd-side-soc{ background:var(--dk-surface-2,#17171B); }
/* Tab scroller, dark. This must NOT simply be deleted: the shared V2 kit ships
   `body.theme-dark .v2x .v2-tabs{background:rgba(23,25,34,.92)}` at (0,3,1),
   which out-specifies the `background:none` on `.v2x.atd .v2-tabs` (0,3,0) and
   paints a second translucent surface inside the .atd-tabsbar card. Removing
   the local rule handed the page straight back to the kit's; it takes an
   explicit (0,4,1) override to actually clear it. */
body.theme-dark .v2x.atd .v2-tabs{ background:none; -webkit-backdrop-filter:none; backdrop-filter:none; }

/* 4 · Light tints, gradients & faint text */
body.theme-dark .v2x.atd .v2-rich{ color:#C2C6D4; }
body.theme-dark .v2x.atd .atd-cap .lb{ color:#C2C6D4; }
body.theme-dark .v2x.atd .v2-feature .ic{ background:linear-gradient(135deg,rgba(54,128,237,.22),rgba(54,128,237,.08)); }
body.theme-dark .v2x.atd .v2-bar,
body.theme-dark .v2x.atd .atd-rbar .track{ background:rgba(255,255,255,.10); }
body.theme-dark .v2x.atd .atd-noshot{ border-color:rgba(54,128,237,.28); }
body.theme-dark .v2x.atd .v2-feature:hover,
body.theme-dark .v2x.atd .v2-toolcard:hover,
body.theme-dark .v2x.atd .v2-accordion details[open]{ border-color:rgba(54,128,237,.40); }
body.theme-dark .v2x.atd .atd-badge-verified{ background:rgba(54,128,237,.18); border-color:rgba(54,128,237,.34); color:#7fb4f4; }
body.theme-dark .v2x.atd .atd-badge-featured{ background:linear-gradient(135deg,rgba(245,158,11,.22),rgba(245,158,11,.10)); border-color:rgba(245,158,11,.40); color:#f4c160; }
body.theme-dark .v2x.atd .atd-upvote:not(.voted):hover .cnt{ background:var(--dk-surface-2,#17171B); }

/* Best-For tags — translucent hue tints */
/* Dark tone ramp. Redefines the TOKENS, not background/color — declaring the
   properties directly here (as this block used to) would out-specify the
   .is-static / .is-links variants and collapse both back into one look.
   --t is INK on dark, so it must be the LIGHT end of each hue; the link
   chips therefore fill with a darker --t-fill and keep light ink rather than
   flipping to white, which is the --accent-light-as-a-fill inversion that
   [[dark-mode-contrast-layer]] exists to prevent. */
body.theme-dark .v2x.atd .atd-tag.c0{ --t:#9DC0F6; --t-bg:rgba(54,128,237,.16);  --t-bd:rgba(54,128,237,.34);  --t-fill:rgba(54,128,237,.34); }
body.theme-dark .v2x.atd .atd-tag.c1{ --t:#5FDD97; --t-bg:rgba(34,197,94,.16);   --t-bd:rgba(34,197,94,.34);   --t-fill:rgba(34,197,94,.30); }
body.theme-dark .v2x.atd .atd-tag.c2{ --t:#C4ABFB; --t-bg:rgba(139,92,246,.18);  --t-bd:rgba(139,92,246,.36);  --t-fill:rgba(139,92,246,.34); }
body.theme-dark .v2x.atd .atd-tag.c3{ --t:#F49AC8; --t-bg:rgba(236,72,153,.16);  --t-bd:rgba(236,72,153,.34);  --t-fill:rgba(236,72,153,.30); }
body.theme-dark .v2x.atd .atd-tag.c4{ --t:#F4BE60; --t-bg:rgba(245,158,11,.16);  --t-bd:rgba(245,158,11,.34);  --t-fill:rgba(245,158,11,.28); }
body.theme-dark .v2x.atd .atd-tag.c5{ --t:#67D6E4; --t-bg:rgba(14,165,180,.16);  --t-bd:rgba(14,165,180,.34);  --t-fill:rgba(14,165,180,.30); }
@media (hover:hover) and (pointer:fine){
  body.theme-dark .v2x.atd .atd-tags.is-links .atd-tag:hover{
    background:var(--t-fill); color:var(--t); border-color:var(--t);
    box-shadow:0 6px 16px rgba(0,0,0,.45);
  }
}
body.theme-dark .v2x.atd .atd-plat-ic{ background:rgba(54,128,237,.18); color:#9CC5F9; }
/* .atd-langpill is NOT in the shared dark-surface list further up; it used to
   inherit an adaptive token (--accent-soft2) and now carries a literal #fff,
   so it needs its own dark panel or the flags sit on white in dark mode. */
body.theme-dark .v2x.atd .atd-langpill{ background:var(--dk-surface-2,#17171B); border-color:var(--line); color:var(--ink); }
@media (hover:hover) and (pointer:fine){
  body.theme-dark .v2x.atd .atd-plat:hover{ color:#9CC5F9; box-shadow:0 8px 20px rgba(0,0,0,.5); }
  body.theme-dark .v2x.atd .atd-langpill:hover{ background:rgba(54,128,237,.12); border-color:rgba(54,128,237,.36); }
}

/* Changelog type badges — translucent */
body.theme-dark .v2x.atd .atd-utype.feature{ background:rgba(34,197,94,.16); color:#5fdd97; }
body.theme-dark .v2x.atd .atd-utype.fix{ background:rgba(54,128,237,.16); color:#9DC0F6; }
body.theme-dark .v2x.atd .atd-utype.pricing{ background:rgba(245,158,11,.16); color:#f4be60; }
body.theme-dark .v2x.atd .atd-utype.announcement{ background:rgba(139,92,246,.18); color:#c4abfb; }
body.theme-dark .v2x.atd .atd-utype.other{ background:rgba(255,255,255,.08); color:#C2C6D4; }

/* ==========================================================================
   §HERO-PRO) HERO — premium rebuild (identity · meta · chips · stats · CTAs)

   Appended deliberately: every rule here has to out-cascade both the original
   §2 HERO block and the `body.theme-dark` surface list further up, so it must
   come last. The GALLERY (§GAL, right column) is untouched by design.

   Three things drove the rebuild:
   · LAYOUT — the head was a flex row, so the pitch, chips and buttons were all
     trapped in a column narrowed by a 112px logo. It is now a 3-area grid:
     logo + identity share row 1, everything else spans the FULL width beneath.
     The same grid is the mobile layout; there is no separate stacked variant.
   · CONTRAST — the old chips were solid gradients with white ink (measured:
     white on #3680ED 3.84:1, on #a855f7 3.96:1, on #f59e0b 2.15:1, on #34d058
     2.04:1 — all fail AA at 13px), the verified badge was #1d9bf0 on #eaf4ff
     (2.70:1) and the voted upvote ran white over a #4ade80 stop (1.74:1).
     All 51 ink/ground pairs in this block were re-measured; every colour was
     measured: soft tint + DARK hue ink at rest, DARK hue fill + white ink on
     hover. Dark mode keeps light hue ink on a translucent fill instead of
     flipping to white — the ink-token-used-as-a-fill inversion.
   · STATE — every interactive element now has a real rest → hover → active
     progression, all of it behind (hover:hover) so a touch device never gets
     a stuck hover, and all of it off under prefers-reduced-motion.
   ========================================================================== */

/* ── Shell ─────────────────────────────────────────────────────────────── */
.v2x.atd .atd-hero{
  --atd-cta-h:52px;
  --atd-logo:112px;
  position:relative; isolation:isolate;
  padding:clamp(20px,2.6vw,34px);
  border:1px solid var(--line); border-radius:20px;
  background:
    radial-gradient(115% 95% at 0% 0%, rgba(54,128,237,.075) 0%, rgba(54,128,237,0) 55%),
    #fff;
  box-shadow:0 1px 2px rgba(15,23,42,.05), 0 16px 38px -18px rgba(15,23,42,.16);
}
/* The brand hairline along the very top edge used to live on ::before. It is
   now the first BACKGROUND LAYER of .atd-hero (see §HERO-SHINE at the end of
   this file): backgrounds clip to the rounded border box for free, so it
   needs no radius of its own and no breakpoint twin — and ::before is freed
   for the orbit ring. */
body.theme-dark .v2x.atd .atd-hero{
  border-color:var(--dk-line-solid,#2C2C31);
  background:
    radial-gradient(115% 95% at 0% 0%, rgba(54,128,237,.17) 0%, rgba(54,128,237,0) 55%),
    var(--dk-surface-2,#17171B);
  box-shadow:0 1px 2px rgba(0,0,0,.5), 0 22px 46px -22px rgba(0,0,0,.85);
}

/* ── Head grid ─────────────────────────────────────────────────────────── */
.v2x.atd .atd-hero-head{
  display:grid;
  grid-template-columns:auto minmax(0,1fr);
  grid-template-areas:"logo ident" "body body";
  column-gap:22px; row-gap:20px; align-items:start;
}
.v2x.atd .atd-logo-plate{ grid-area:logo; position:relative; align-self:start; }
.v2x.atd .atd-hero-ident{ grid-area:ident; min-width:0; align-self:center; }
.v2x.atd .atd-hero-body { grid-area:body;  min-width:0; }

/* ── Logo plate ────────────────────────────────────────────────────────── */
/* Everything in this block is expressed as a RATIO of --atd-logo, so the plate
   keeps its proportions down the whole ramp instead of needing a hand-tuned
   twin per breakpoint. The ratios are the values the 112px desktop tile
   already used (-16/112, 30/112, 12/112), so desktop renders byte-identical;
   what changes is that a 80px phone tile now gets a 11px halo and 8.6px of
   padding rather than desktop's 16 and 12, which at that size were a bloom
   wider than the gap to the title and a frame eating a quarter of the mark. */
.v2x.atd .atd-logo-halo{
  position:absolute; inset:calc(var(--atd-logo) * -.143); z-index:0;
  border-radius:calc(var(--atd-logo) * .268); pointer-events:none;
  background:radial-gradient(58% 58% at 50% 45%, rgba(54,128,237,.34), rgba(54,128,237,0) 72%);
  filter:blur(12px); opacity:.7;
  transition:opacity .45s ease, transform .55s cubic-bezier(.16,1,.3,1);
}
/* The tile stays a LIGHT plate in dark mode too. Brand logos are overwhelmingly
   drawn for a light ground, and the previous dark twin painted #171922 behind
   them — a near-black mark on a near-black tile. */
.v2x.atd .atd-logo-tile,
.v2x.atd .atd-logo-letter{
  position:relative; z-index:1;
  width:var(--atd-logo); height:var(--atd-logo);
  border-radius:24px; flex:none;
  transition:transform .45s cubic-bezier(.16,1,.3,1), box-shadow .4s ease;
}
.v2x.atd .atd-logo-tile{
  object-fit:contain; padding:calc(var(--atd-logo) * .107); background:#fff;
  border:1px solid var(--line);
  box-shadow:0 1px 2px rgba(15,23,42,.06), 0 14px 28px -14px rgba(15,23,42,.32), inset 0 1px 0 #fff;
}
.v2x.atd .atd-logo-letter{
  display:flex; align-items:center; justify-content:center;
  background:linear-gradient(140deg,#2060C0,#3680ED 52%,#60A4F5);
  color:#fff; font-size:calc(var(--atd-logo) * .38); font-weight:800; line-height:1;
  border:0; box-shadow:0 12px 28px -12px rgba(32,96,192,.85), inset 0 1px 0 rgba(255,255,255,.35);
}

/* Paired marks — the compare hero, where one plate cannot represent two tools.
   Every value is a RATIO of --atd-logo like the rest of this block, so the pair
   rides the same responsive ramp instead of needing a hand-tuned twin per
   breakpoint. The tiles sit at 72% and overlap by 16%, keeping the group inside
   roughly the single-plate footprint. Selectors are (0,3,0) so they outrank the
   breakpoint rules further down that re-set border-radius on the base classes. */
.v2x.atd .atd-logo-duo{
  position:relative; z-index:1;
  display:flex; align-items:center;
}
.v2x.atd .atd-logo-duo .atd-logo-tile,
.v2x.atd .atd-logo-duo .atd-logo-letter{
  width:calc(var(--atd-logo) * .72); height:calc(var(--atd-logo) * .72);
  border-radius:calc(var(--atd-logo) * .16);
}
/* Full fit. `.atd-logo-tile` carries a real 1px border drawn outside the
   content box, so the inset was only costing size — the same reason
   `.atd-ctax-logo` fills. Scoped to the duo: a SINGLE hero keeps its padding,
   which is a deliberate choice on those pages and not mine to change here.
   overflow:hidden clips a square mark to the radius instead of squaring it. */
.v2x.atd .atd-logo-duo .atd-logo-tile{ padding:0; overflow:hidden; }
/* The base letter rule sizes its glyph off the FULL --atd-logo, which would
   overflow a 72% tile — .38 x .72. */
.v2x.atd .atd-logo-duo .atd-logo-letter{ font-size:calc(var(--atd-logo) * .274); }
.v2x.atd .atd-logo-duo > * + *{ margin-left:calc(var(--atd-logo) * -.16); }
.v2x.atd .atd-logo-duo > *:last-child{ z-index:2; }
/* The shared halo is ONE glow spanning the whole plate, which reads as a single
   object behind two marks. It goes; each tile answers its own hover instead.
   The plate-level lift and glow are scoped off a pair by :not(.is-duo) up in
   the base block, so nothing has to be un-set here and the dark-mode resting
   shadow still applies untouched. */
.v2x.atd .atd-logo-plate.is-duo .atd-logo-halo{ display:none; }
.v2x.atd .atd-logo-duo > *{ transition:transform .45s cubic-bezier(.16,1,.3,1), box-shadow .4s ease; }
/* z-index lifts the hovered mark over its neighbour, or the overlap clips it. */
.v2x.atd .atd-logo-duo > *:hover{ transform:translateY(-2px) scale(1.015); z-index:3; }
.v2x.atd .atd-logo-duo .atd-logo-tile:hover{ box-shadow:0 1px 2px rgba(15,23,42,.06), 0 10px 20px -12px rgba(32,96,192,.28); }
.v2x.atd .atd-logo-duo .atd-logo-letter:hover{ box-shadow:0 10px 20px -10px rgba(32,96,192,.55), inset 0 1px 0 rgba(255,255,255,.35); }
body.theme-dark .v2x.atd .atd-logo-duo .atd-logo-tile:hover{ box-shadow:0 1px 2px rgba(0,0,0,.4), 0 10px 20px -12px rgba(0,0,0,.7); }
body.theme-dark .v2x.atd .atd-logo-tile{
  background:#fff; border-color:var(--dk-line-strong,rgba(255,255,255,.16));
  box-shadow:0 1px 2px rgba(0,0,0,.5), 0 16px 32px -16px rgba(0,0,0,.9);
}
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-logo-plate:not(.is-duo):hover .atd-logo-tile,
  .v2x.atd .atd-logo-plate:not(.is-duo):hover .atd-logo-letter{ transform:translateY(-4px) scale(1.025); }
  .v2x.atd .atd-logo-plate:not(.is-duo):hover .atd-logo-tile{ box-shadow:0 1px 2px rgba(15,23,42,.06), 0 22px 40px -16px rgba(32,96,192,.45); }
  .v2x.atd .atd-logo-plate:not(.is-duo):hover .atd-logo-halo{ opacity:1; transform:scale(1.1); }
}

/* ── Title row + status badges ─────────────────────────────────────────── */
.v2x.atd .atd-title-row{
  display:flex; align-items:center; flex-wrap:wrap; gap:8px 13px; margin:0 0 11px;
}
.v2x.atd .atd-h1{
  font-size:clamp(1.9rem,1.15rem+2.3vw,2.85rem) !important;
  font-weight:800; letter-spacing:-.032em; line-height:1.06;
  color:var(--ink); margin:0; overflow-wrap:anywhere;
}
.v2x.atd .atd-badges{ display:inline-flex; align-items:center; flex-wrap:wrap; gap:8px; }
.v2x.atd .atd-badge-featured,
.v2x.atd .atd-badge-trending,
.v2x.atd .atd-badge-certificate,
.v2x.atd .atd-badge-editors,
.v2x.atd .atd-badge-live,
.v2x.atd .atd-badge-verified{
  display:inline-flex; align-items:center; gap:6px;
  padding:5px 12px 5px 10px; border-radius:999px;
  font-size:.76rem; font-weight:700; line-height:1.35; letter-spacing:.005em;
  white-space:nowrap;
  transition:transform .28s cubic-bezier(.16,1,.3,1), box-shadow .28s ease, filter .2s ease;
}
.v2x.atd .atd-badge-featured{
  background:linear-gradient(135deg,#FFF7E2,#FFE7A8);
  border:1px solid rgba(180,83,9,.34); color:#8A5206;
  box-shadow:0 2px 6px rgba(245,158,11,.20), inset 0 1px 0 rgba(255,255,255,.75);
}
.v2x.atd .atd-badge-featured .lcd,.v2x.atd .atd-badge-featured i{ color:#B45309; }
/* ── Trending, the third kind (2026-09-02) ────────────────────────────────
   Featured and Trending were BOTH rendered as `atd-badge-featured`, so a
   hero carrying the two drew the same amber star pill twice and the pair
   carried no information. Rose is not a new colour on the site: it is what
   the listing cards already paint trending with (`.acx-flag.is-fire`,
   #FFE4E6 / #9F1239), so a course reads the same on the grid and on its own
   page. Ink #9F1239 on the #FFE4E6 end of the ramp is 6.68:1 — AA at any
   weight, unlike the tint-on-tint pairs that failed the 2026-08 audit. */
.v2x.atd .atd-badge-trending{
  background:linear-gradient(135deg,#FFF1F3,#FFE4E6);
  border:1px solid rgba(190,18,60,.30); color:#9F1239;
  box-shadow:0 2px 6px rgba(244,63,94,.20), inset 0 1px 0 rgba(255,255,255,.75);
}
.v2x.atd .atd-badge-trending .lcd,.v2x.atd .atd-badge-trending i{ color:#E11D48; }
/* ── Certificate, the fourth kind (2026-09-02) ────────────────────────────
   It used to be passed as kind 'verified', so a course attribute wore the
   site's TRUST MARK and a course with both ticked drew two identical blue
   pills. Emerald is not a new colour: `.acx-fig.is-cert` on the listing
   cards already paints this exact claim #047857 on #ECFDF5, measured there
   at 5.21:1. The gradient's DARK stop is that same #ECFDF5, so the worst
   point of this pill is the figure the cards already pass on. */
.v2x.atd .atd-badge-certificate{
  background:linear-gradient(135deg,#F4FEF9,#ECFDF5);
  border:1px solid rgba(4,120,87,.28); color:#047857;
  box-shadow:0 2px 6px rgba(16,185,129,.18), inset 0 1px 0 rgba(255,255,255,.75);
}
.v2x.atd .atd-badge-certificate .lcd,.v2x.atd .atd-badge-certificate i{ color:#059669; }
/* STROKED, not filled. Lucide `award` is a ribbon path plus a plain circle,
   so the fill+stroke:0 treatment the star and the flame use would collapse
   it into a solid blob. 13px because a stroked glyph needs more room than a
   silhouette; the other two sit at 12. */
.v2x.atd .atd-badge-certificate svg{ width:13px; height:13px; flex:0 0 auto; }
/* §EDITORS — the FIFTH kind, added 2026-09-03. Editor's Pick (cheat sheets)
   and Editor's Choice (browser extensions) were both passed as kind
   'featured', so a hero carrying Featured as well drew the SAME amber star
   pill twice — the reported bug, and the same defect Trending and
   Certificate each had before they got a kind.

   Violet is not a new palette: it is exactly what the listing cards already
   give this claim (.nwsp-badge.is-pick, and the news card's
   data-tone="violet" — both --aits-violet-soft #EEE6FF on
   --aits-violet-ink #4C2FBE), so a card and its detail page agree. As with
   certificate, the gradient's DARK stop IS the card colour, so the pill's
   worst point is the pair the cards already stand behind: 7.08:1, AAA. */
.v2x.atd .atd-badge-editors{
  background:linear-gradient(135deg,#F7F3FF,#EEE6FF);
  border:1px solid rgba(112,72,232,.28); color:#4C2FBE;
  box-shadow:0 2px 6px rgba(112,72,232,.16), inset 0 1px 0 rgba(255,255,255,.75);
}
.v2x.atd .atd-badge-editors .lcd,.v2x.atd .atd-badge-editors i{ color:#7048E8; }
/* §LIVE — the SIXTH kind, added 2026-09-03. /events/{slug} passed BOTH
   Featured and "Live now" as kind 'featured', so an event that was both drew
   the amber star pill twice — the same defect cheat sheets and extensions had.

   The pair is lifted VERBATIM from the event card's own live plate
   (.evx-plate.has-live #FEECEF, .evx-dp.is-live #B3122B), so a card and its
   detail page agree. 6.08:1 — AA at any weight.

   ⚠️ This sits in the SAME ROSE FAMILY as `trending` (#FFE4E6 / #9F1239) and
   is only a shade deeper. That is tolerable ONLY because no page passes both:
   /events never emits a Trending badge. If one is ever added there, these two
   need pulling apart — do not assume the shade difference carries it.

   The glyph is a PULSING DOT, not a Lucide icon: it is what the card uses to
   mean live, and it is the one differentiator that survives at pill size when
   the hue does not. The animation is switched off with the rest of the kit
   under prefers-reduced-motion. */
.v2x.atd .atd-badge-live{
  background:linear-gradient(135deg,#FFF5F7,#FEECEF);
  border:1px solid rgba(179,18,43,.26); color:#B3122B;
  box-shadow:0 2px 6px rgba(244,63,94,.16), inset 0 1px 0 rgba(255,255,255,.75);
}
.v2x.atd .atd-badge-live .atd-live-dot{
  width:7px; height:7px; border-radius:50%; flex:0 0 auto;
  background:currentColor; position:relative;
  animation:atd-live-pulse 1.8s ease-out infinite;
}
@keyframes atd-live-pulse{
  0%,100%{ box-shadow:0 0 0 0 rgba(244,63,94,.55); }
  70%    { box-shadow:0 0 0 5px rgba(244,63,94,0); }
}
.v2x.atd .atd-badge-verified{
  background:linear-gradient(135deg,#EDF5FF,#DBEAFF);
  border:1px solid rgba(32,96,192,.30); color:#1A5FC8;
  box-shadow:0 2px 6px rgba(54,128,237,.16), inset 0 1px 0 rgba(255,255,255,.75);
}
.v2x.atd .atd-badge-verified svg{ width:14px; height:14px; display:inline-block; vertical-align:-2px; }
body.theme-dark .v2x.atd .atd-badge-featured{
  background:linear-gradient(135deg,rgba(245,158,11,.24),rgba(245,158,11,.11));
  border-color:rgba(245,158,11,.44); color:#F6C86A; box-shadow:none;
}
body.theme-dark .v2x.atd .atd-badge-featured .lcd,
body.theme-dark .v2x.atd .atd-badge-featured i{ color:#F6C86A; }
body.theme-dark .v2x.atd .atd-badge-verified{
  background:linear-gradient(135deg,rgba(54,128,237,.26),rgba(54,128,237,.12));
  border-color:rgba(54,128,237,.46); color:#9DC0F6; box-shadow:none;
}
body.theme-dark .v2x.atd .atd-badge-trending{
  background:linear-gradient(135deg,rgba(244,63,94,.26),rgba(244,63,94,.12));
  border-color:rgba(244,63,94,.46); color:#FDA4AF; box-shadow:none;
}
body.theme-dark .v2x.atd .atd-badge-trending .lcd,
body.theme-dark .v2x.atd .atd-badge-trending i{ color:#FDA4AF; }
body.theme-dark .v2x.atd .atd-badge-certificate{
  background:linear-gradient(135deg,rgba(16,185,129,.26),rgba(16,185,129,.12));
  border-color:rgba(16,185,129,.46); color:#6EE7B7; box-shadow:none;
}
body.theme-dark .v2x.atd .atd-badge-certificate .lcd,
body.theme-dark .v2x.atd .atd-badge-certificate i{ color:#6EE7B7; }
body.theme-dark .v2x.atd .atd-badge-editors{
  background:linear-gradient(135deg,rgba(112,72,232,.30),rgba(112,72,232,.14));
  border-color:rgba(139,105,240,.48); color:#C4B1FF; box-shadow:none;
}
body.theme-dark .v2x.atd .atd-badge-editors .lcd,
body.theme-dark .v2x.atd .atd-badge-editors i{ color:#C4B1FF; }
body.theme-dark .v2x.atd .atd-badge-live{
  background:linear-gradient(135deg,rgba(244,63,94,.26),rgba(244,63,94,.12));
  border-color:rgba(251,113,133,.44); color:#FB9BB0; box-shadow:none;
}
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-badge-featured:hover{ transform:translateY(-2px); box-shadow:0 8px 18px -6px rgba(180,83,9,.45); }
  .v2x.atd .atd-badge-verified:hover{ transform:translateY(-2px); box-shadow:0 8px 18px -6px rgba(32,96,192,.45); }
  .v2x.atd .atd-badge-trending:hover{ transform:translateY(-2px); box-shadow:0 8px 18px -6px rgba(190,18,60,.45); }
  .v2x.atd .atd-badge-certificate:hover{ transform:translateY(-2px); box-shadow:0 8px 18px -6px rgba(4,120,87,.45); }
  .v2x.atd .atd-badge-editors:hover{ transform:translateY(-2px); box-shadow:0 8px 18px -6px rgba(76,47,190,.45); }
  .v2x.atd .atd-badge-live:hover{ transform:translateY(-2px); box-shadow:0 8px 18px -6px rgba(179,18,43,.45); }
  body.theme-dark .v2x.atd .atd-badge-featured:hover,
  body.theme-dark .v2x.atd .atd-badge-trending:hover,
  body.theme-dark .v2x.atd .atd-badge-certificate:hover,
  body.theme-dark .v2x.atd .atd-badge-editors:hover,
  body.theme-dark .v2x.atd .atd-badge-live:hover,
  body.theme-dark .v2x.atd .atd-badge-verified:hover{ box-shadow:0 8px 18px -6px rgba(0,0,0,.7); filter:brightness(1.12); }
}

/* ── Meta strip: owner ─────────────────────────────────────────────────────
   The category pill and its icon plate were removed with the markup on
   2026-08-12 (the breadcrumb carries the category instead), and the trust
   badges went the same way earlier that day. The row is kept as a flex
   container so it still wraps cleanly if anything is added back beside the
   owner. */
.v2x.atd .atd-meta-row{
  display:flex; align-items:center; flex-wrap:wrap; gap:9px 11px; margin:0;
}
.v2x.atd .atd-by-line{ font-size:.88rem; font-weight:500; color:var(--muted); }
.v2x.atd .atd-by-link{
  color:#1B54A8; font-weight:700; text-decoration:none;
  background-image:linear-gradient(currentColor,currentColor);
  background-size:0 1.5px; background-position:0 100%; background-repeat:no-repeat;
  transition:background-size .28s cubic-bezier(.16,1,.3,1), color .2s ease;
}
body.theme-dark .v2x.atd .atd-by-link{ color:#9DC0F6; }
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-by-link:hover{ background-size:100% 1.5px; color:#164896; text-decoration:none; }
  body.theme-dark .v2x.atd .atd-by-link:hover{ color:#CFE2FE; }
}

/* The .atd-trust / .aitt-badge overrides that sat here went with the "AI Directory"
   + "Verified Company" pair when it was removed from the meta strip (2026-08-12).
   Nothing on this page renders the tool-type component any more, so tool-type.css
   no longer loads here at all — do not re-add these rules without the markup. */

/* ── Pitch ─────────────────────────────────────────────────────────────── */
.v2x.atd .atd-desc{
  color:var(--muted); max-width:68ch; margin:0 0 18px;
  font-size:1.06rem; line-height:1.7; font-weight:400;
}

/* ── Capability chips — soft tint at rest, hue fill on hover ───────────── */
.v2x.atd .atd-chips{ display:flex; flex-wrap:wrap; gap:9px; margin:0 0 20px; }
.v2x.atd .atd-chip{
  display:inline-flex !important; align-items:center; gap:8px;
  padding:6px 14px 6px 6px !important; border-radius:999px !important;
  border:1px solid var(--c-bd) !important; background:var(--c-bg) !important; color:var(--c-ink) !important;
  font-size:.83rem !important; font-weight:700 !important; line-height:1.4;
  box-shadow:none !important; text-decoration:none; max-width:100%;
  transition:transform .3s cubic-bezier(.16,1,.3,1), box-shadow .3s ease,
             background .26s ease, border-color .26s ease, color .2s ease !important;
}
.v2x.atd .atd-chip-lbl{ min-width:0; }
.v2x.atd .atd-chip-ic{
  flex:none; width:24px; height:24px; border-radius:999px;
  display:inline-flex; align-items:center; justify-content:center;
  background:#fff; color:var(--c-ink) !important;
  box-shadow:0 1px 2px rgba(15,23,42,.12);
  transition:background .26s ease, color .2s ease, transform .4s cubic-bezier(.16,1,.3,1);
}
/* Deliberately (0,5,0): the FEEDBACK-PASS block above paints every glyph inside
   a chip `color:#fff !important` at (0,4,0). A (0,3,0) rule here loses to it and
   the icons go white on the soft tint — invisible. Do not shorten this selector. */
.v2x.atd .atd-chip .atd-chip-ic .lcd,
.v2x.atd .atd-chip .atd-chip-ic svg,
.v2x.atd .atd-chip .atd-chip-ic i{ display:block; color:inherit !important; }
/* Hue ramp. Both states were MEASURED at 13px/700, not eyeballed —
   ink-on-tint / white-on-the-LIGHTEST-fill-stop:
   green 4.56 / 5.02 · blue 6.47 / 6.01 · violet 6.78 / 7.10 · amber 5.65 / 5.02.
   Green is the thinnest margin of the four: #15803D is the shared --green-ink
   token, kept for consistency, so DEEPEN the tint before touching that ink.
   The fills are the DARK end of each hue for exactly that reason: the design
   this replaced filled with the LIGHT end and put white on top — white on
   #34d058 is 2.2:1, and on #3680ED it is 3.6:1. Both failed AA at this size. */
.v2x.atd .atd-chip-green { --c-ink:#147136; --c-bg:#E8F8EE; --c-bd:rgba(21,128,61,.26);  --c-fill:linear-gradient(135deg,#166534,#15803D); --c-glow:rgba(21,128,61,.55); }
.v2x.atd .atd-chip-blue  { --c-ink:#1B54A8; --c-bg:#EAF2FE; --c-bd:rgba(32,96,192,.26);  --c-fill:linear-gradient(135deg,#1B4FA0,#2060C0); --c-glow:rgba(32,96,192,.55); }
.v2x.atd .atd-chip-violet{ --c-ink:#6429C7; --c-bg:#F2ECFE; --c-bd:rgba(109,40,217,.26); --c-fill:linear-gradient(135deg,#5B21B6,#6D28D9); --c-glow:rgba(109,40,217,.55); }
.v2x.atd .atd-chip-amber { --c-ink:#9A4A08; --c-bg:#FDF2E0; --c-bd:rgba(154,74,8,.28);   --c-fill:linear-gradient(135deg,#92400E,#B45309); --c-glow:rgba(154,74,8,.55); }
body.theme-dark .v2x.atd .atd-chip-green { --c-ink:#5FDD97; --c-bg:rgba(34,197,94,.14);  --c-bd:rgba(34,197,94,.32);  --c-fill:linear-gradient(135deg,rgba(34,197,94,.34),rgba(34,197,94,.20)); --c-glow:rgba(0,0,0,.6); }
body.theme-dark .v2x.atd .atd-chip-blue  { --c-ink:#9DC0F6; --c-bg:rgba(54,128,237,.16); --c-bd:rgba(54,128,237,.34); --c-fill:linear-gradient(135deg,rgba(54,128,237,.36),rgba(54,128,237,.20)); --c-glow:rgba(0,0,0,.6); }
body.theme-dark .v2x.atd .atd-chip-violet{ --c-ink:#C4ABFB; --c-bg:rgba(139,92,246,.16); --c-bd:rgba(139,92,246,.34); --c-fill:linear-gradient(135deg,rgba(139,92,246,.36),rgba(139,92,246,.20)); --c-glow:rgba(0,0,0,.6); }
body.theme-dark .v2x.atd .atd-chip-amber { --c-ink:#F4BE60; --c-bg:rgba(245,158,11,.15); --c-bd:rgba(245,158,11,.32); --c-fill:linear-gradient(135deg,rgba(245,158,11,.32),rgba(245,158,11,.18)); --c-glow:rgba(0,0,0,.6); }
body.theme-dark .v2x.atd .atd-chip-ic{ background:rgba(255,255,255,.10); box-shadow:none; }
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-chip:hover{
    background:var(--c-fill) !important; color:#fff !important; border-color:transparent !important;
    transform:translateY(-3px); box-shadow:0 12px 22px -10px var(--c-glow) !important;
  }
  .v2x.atd .atd-chip:hover .atd-chip-ic{ background:rgba(255,255,255,.24); color:#fff !important; transform:rotate(-8deg) scale(1.06); box-shadow:none; }
  /* Dark: keep the LIGHT hue ink on a translucent fill. Flipping to white ink
     over a light-hue colour is the inversion the contrast layer exists to
     prevent, so the ink token stays put and only the fill deepens. */
  body.theme-dark .v2x.atd .atd-chip:hover{ color:var(--c-ink) !important; border-color:var(--c-bd) !important; }
  body.theme-dark .v2x.atd .atd-chip:hover .atd-chip-ic{ background:rgba(255,255,255,.18); color:var(--c-ink) !important; }
}

/* ── Stat rail ─────────────────────────────────────────────────────────── */
/* ⚠️ SUPERSEDED by §SPECRAIL at the end of this file, which restates every
   declaration below at equal-or-higher specificity and later in source order.
   This block is what a grep for `atd-statrail` finds FIRST, so a change made
   here will look correct and paint nothing. Edit §SPECRAIL.
   What still lands from here: only the properties §SPECRAIL leaves alone. */
.v2x.atd .atd-statrail{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(136px,1fr));
  gap:10px; margin:0 0 22px;
}
/* One or two figures do not earn the full column width — without these the
   single-stat listings render one card stretched edge to edge. */
.v2x.atd .atd-statrail.is-1{ grid-template-columns:minmax(136px,208px); }
.v2x.atd .atd-statrail.is-2{ grid-template-columns:repeat(2,minmax(136px,1fr)); max-width:460px; }
.v2x.atd .atd-stat{
  position:relative; overflow:hidden;
  display:flex; flex-direction:column; gap:7px;
  padding:12px 15px; border-radius:14px;
  border:1px solid var(--line);
  background:linear-gradient(180deg,#FBFCFE,#F3F7FD);
  transition:transform .32s cubic-bezier(.16,1,.3,1), box-shadow .32s ease, border-color .26s ease;
}
.v2x.atd .atd-stat::after{
  content:""; position:absolute; inset:0; pointer-events:none; opacity:0;
  background:radial-gradient(90% 120% at 0% 0%, rgba(54,128,237,.16), rgba(54,128,237,0) 70%);
  transition:opacity .32s ease;
}
.v2x.atd .atd-stat-top{ display:flex; align-items:center; gap:9px; flex-wrap:wrap; min-height:26px; }
.v2x.atd .atd-stat-val{
  font-size:1.5rem; font-weight:800; letter-spacing:-.025em; line-height:1; color:var(--ink);
}
.v2x.atd .atd-stat .v2-stars{ font-size:.68rem; letter-spacing:1.5px; line-height:1; color:var(--gold); }
.v2x.atd .atd-stat-lbl{
  display:inline-flex; align-items:center; gap:6px;
  font-size:.72rem; font-weight:700; letter-spacing:.07em; text-transform:uppercase;
  color:var(--muted);
}
.v2x.atd .atd-stat-lbl .lcd{ color:var(--accent); flex:none; }
body.theme-dark .v2x.atd .atd-stat{
  border-color:var(--line);
  background:linear-gradient(180deg,var(--dk-surface-3,#1D1D22),var(--dk-surface-2,#17171B));
}
body.theme-dark .v2x.atd .atd-stat-lbl .lcd{ color:#7FB4F4; }
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-stat:hover{
    transform:translateY(-3px); border-color:rgba(54,128,237,.38);
    box-shadow:0 14px 26px -14px rgba(32,96,192,.5);
  }
  .v2x.atd .atd-stat:hover::after{ opacity:1; }
  body.theme-dark .v2x.atd .atd-stat:hover{ border-color:rgba(54,128,237,.5); box-shadow:0 14px 26px -14px rgba(0,0,0,.85); }
}

/* ── CTA row ───────────────────────────────────────────────────────────── */
.v2x.atd .atd-cta-row{ display:flex; flex-wrap:wrap; align-items:stretch; gap:12px; margin:0; }
.v2x.atd .atd-cta-row .atd-btn,
.v2x.atd .atd-cta-row .atd-upvote{
  height:var(--atd-cta-h); border-radius:13px;
  font-size:.96rem; font-weight:700; letter-spacing:-.005em; white-space:nowrap;
}
.v2x.atd .atd-cta-row .atd-btn{ padding:0 24px !important; gap:10px; }
.v2x.atd .atd-btn-ic{ display:inline-flex; align-items:center; transition:transform .35s cubic-bezier(.16,1,.3,1); }

/* Primary — brand gradient. The lightest stop is #2F72DA, the lightest blue
   that still clears 4.5:1 against white ink at this size (4.62:1). */
.v2x.atd .atd-cta-row .atd-btn-primary{
  position:relative; overflow:hidden; border-color:transparent; color:#fff;
  background:linear-gradient(135deg,#2F72DA 0%,#2261C4 55%,#1A4FA6 100%);
  box-shadow:0 1px 2px rgba(15,23,42,.12), 0 14px 26px -14px rgba(32,96,192,.9);
  transition:transform .3s cubic-bezier(.16,1,.3,1), box-shadow .3s ease, background .26s ease;
}
.v2x.atd .atd-cta-row .atd-btn-primary::after{
  content:""; position:absolute; inset:0; pointer-events:none; border-radius:inherit;
  background:linear-gradient(115deg,transparent 22%,rgba(255,255,255,.38) 50%,transparent 78%);
  transform:translateX(-130%);
}
.v2x.atd .atd-cta-row .atd-btn-primary > *{ position:relative; z-index:1; }

/* Secondary — quiet surface at rest, brand tint on hover. */
.v2x.atd .atd-cta-row .atd-btn-outline{
  background:#fff; color:#1B54A8; border:1.5px solid #CFE0FA;
  box-shadow:0 1px 2px rgba(15,23,42,.05);
  transition:transform .3s cubic-bezier(.16,1,.3,1), box-shadow .3s ease,
             background .26s ease, border-color .26s ease, color .2s ease;
}
body.theme-dark .v2x.atd .atd-cta-row .atd-btn-outline{
  background:var(--dk-surface-3,#1D1D22); color:#9DC0F6; border-color:rgba(54,128,237,.38); box-shadow:none;
}
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-cta-row .atd-btn-primary:hover{
    background:linear-gradient(135deg,#2A6BD2 0%,#1D59B8 55%,#164896 100%); color:#fff;
    transform:translateY(-3px); box-shadow:0 2px 4px rgba(15,23,42,.12), 0 20px 34px -14px rgba(32,96,192,1);
  }
  .v2x.atd .atd-cta-row .atd-btn-primary:hover::after{ animation:atd-cta-sheen .75s cubic-bezier(.16,1,.3,1) 1; }
  .v2x.atd .atd-cta-row .atd-btn-primary:hover .atd-btn-ic{ transform:translate(2px,-2px); }
  .v2x.atd .atd-cta-row .atd-btn-outline:hover{
    background:linear-gradient(180deg,#F3F8FF,#E8F1FD); border-color:#3680ED; color:#164896;
    transform:translateY(-3px); box-shadow:0 14px 26px -14px rgba(32,96,192,.55);
  }
  .v2x.atd .atd-cta-row .atd-btn-outline:hover .atd-btn-ic{ transform:scale(1.1); }
  body.theme-dark .v2x.atd .atd-cta-row .atd-btn-outline:hover{
    background:rgba(54,128,237,.16); border-color:rgba(54,128,237,.7); color:#D6E6FE;
    box-shadow:0 14px 26px -14px rgba(0,0,0,.9);
  }
}
.v2x.atd .atd-cta-row .atd-btn:active{ transform:translateY(-1px) scale(.985); }
@keyframes atd-cta-sheen{ from{ transform:translateX(-130%) } to{ transform:translateX(130%) } }

/* ⚠️ SUPERSEDED by §UPVOTE at the end of this file — see the note on the base
   block above. The contrast measurements in this comment are still the live
   ones: §UPVOTE reuses this exact emerald ramp for the voted state. */
/* Upvote — matched to the buttons beside it (height, radius, weight). The
   voted fill is a deeper emerald than before: white on the old #4ade80 stop
   measured 1.74:1. The count pill is now white-on-green rather than the
   reverse — translucent white over the green measured 3.18:1 and failed. */
.v2x.atd .atd-cta-row .atd-upvote{
  padding:0 14px 0 20px; gap:9px; border-width:1.5px; border-color:var(--line-strong);
  background:#fff; color:var(--ink);
}
.v2x.atd .atd-cta-row .atd-upvote .cnt{ background:var(--accent-soft); color:#1B54A8; }
.v2x.atd .atd-cta-row .atd-upvote.voted{
  background:linear-gradient(135deg,#0E7A45,#12874C 55%,#0F7F58); color:#fff; border-color:transparent;
  box-shadow:0 1px 2px rgba(15,23,42,.12), 0 14px 26px -14px rgba(14,122,69,.95), inset 0 1px 0 rgba(255,255,255,.22);
}
.v2x.atd .atd-cta-row .atd-upvote.voted .cnt{ background:rgba(255,255,255,.95); color:#0E7A45; }
body.theme-dark .v2x.atd .atd-cta-row .atd-upvote{ background:var(--dk-surface-3,#1D1D22); border-color:var(--line-strong); color:var(--ink); }
body.theme-dark .v2x.atd .atd-cta-row .atd-upvote .cnt{ background:rgba(54,128,237,.20); color:#9DC0F6; }
@media (hover:hover) and (pointer:fine){
  /* colour is restated, not inherited: the §upvote block above still supplies
     `color:var(--accent)` on this hover, and #3680ED on the soft tint is 3.5:1. */
  .v2x.atd .atd-cta-row .atd-upvote:not(.voted):hover{
    background:var(--accent-soft); border-color:var(--accent); color:#1B54A8;
    transform:translateY(-3px); box-shadow:0 14px 26px -14px rgba(32,96,192,.6);
  }
  .v2x.atd .atd-cta-row .atd-upvote:not(.voted):hover .lcd{ color:#1B54A8; }
  .v2x.atd .atd-cta-row .atd-upvote:not(.voted):hover .cnt{ background:#fff; color:#1B54A8; }
  body.theme-dark .v2x.atd .atd-cta-row .atd-upvote:not(.voted):hover{
    background:rgba(54,128,237,.16); border-color:rgba(54,128,237,.7); color:#D6E6FE;
    box-shadow:0 14px 26px -14px rgba(0,0,0,.9);
  }
  body.theme-dark .v2x.atd .atd-cta-row .atd-upvote:not(.voted):hover .cnt{ background:rgba(255,255,255,.14); color:#D6E6FE; }
}

/* Keyboard parity — the hero's own controls get the same ring as the rest of
   the page, on the pill radius rather than the global 8px. */
.v2x.atd .atd-chip:focus-visible,
.v2x.atd .atd-cta-row .atd-btn:focus-visible,
.v2x.atd .atd-cta-row .atd-upvote:focus-visible{
  outline:none; border-radius:999px;
  box-shadow:0 0 0 3px rgba(54,128,237,.85), 0 0 0 6px rgba(54,128,237,.22);
}
.v2x.atd .atd-cta-row .atd-btn:focus-visible,
.v2x.atd .atd-cta-row .atd-upvote:focus-visible{ border-radius:13px; }

/* ── Responsive ────────────────────────────────────────────────────────── */
@media (max-width:1199.98px){
  .v2x.atd .atd-hero{ --atd-logo:104px; }
}
@media (max-width:991.98px){          /* tablet — hero stacks, gallery drops below */
  .v2x.atd .atd-hero{ --atd-logo:96px; }
  .v2x.atd .atd-hero-grid{ align-items:flex-start; }
  .v2x.atd .atd-hero-head{ column-gap:20px; row-gap:18px; }
  .v2x.atd .atd-desc{ max-width:none; }
}
@media (max-width:767.98px){
  .v2x.atd .atd-hero{ --atd-logo:92px; --atd-cta-h:50px; }
  .v2x.atd .atd-hero-head{ column-gap:16px; row-gap:16px; }
  .v2x.atd .atd-logo-tile,.v2x.atd .atd-logo-letter{ border-radius:20px; }
  /* No `padding:9px` here any more. It was the desktop 12px hand-scaled for
     one breakpoint and it would have OVERRIDDEN the ratio above (this block is
     later in the file at equal specificity), pinning every phone tile to a
     frame sized for an 84px plate. */
  .v2x.atd .atd-statrail{ grid-template-columns:repeat(auto-fit,minmax(108px,1fr)); gap:8px; }
  .v2x.atd .atd-stat{ padding:11px 12px; }
  .v2x.atd .atd-stat-val{ font-size:1.32rem; }
}
@media (max-width:575.98px){
  /* 68 -> 80px. The identity column is minmax(0,1fr) so it simply absorbs the
     12px: at the 360px worst case the title still gets 204px, and .atd-h1 wraps
     rather than clipping. Radius stays 17px, which at 80px is 21% — the same
     proportion the 112px desktop tile has, where at 68px it read rounder. */
  .v2x.atd .atd-hero{ --atd-logo:80px; --atd-cta-h:50px; padding:18px 16px; border-radius:16px; }
  .v2x.atd .atd-logo-tile,.v2x.atd .atd-logo-letter{ border-radius:17px; }
  /* 1.62 -> 1.5rem. The logo plate went 68 -> 80px in the same pass, so the
     title column is 12px narrower; a 26px H1 beside it pushed common names
     onto a third line. */
  .v2x.atd .atd-h1{ font-size:1.5rem !important; }
  .v2x.atd .atd-title-row{ gap:7px 10px; margin-bottom:9px; }
  .v2x.atd .atd-desc{ font-size:1rem; line-height:1.65; margin-bottom:16px; }
  .v2x.atd .atd-chips{ gap:8px; margin-bottom:18px; }
  .v2x.atd .atd-chip{ font-size:.79rem !important; padding:5px 12px 5px 5px !important; }
  .v2x.atd .atd-chip-ic{ width:22px; height:22px; }
  /* Every action goes full width and keeps its complete label — a two-up grid
     clipped "Visit Company Page" at 360px, and truncated button text is worse
     than a taller stack. */
  .v2x.atd .atd-cta-row{ gap:10px; }
  .v2x.atd .atd-cta-row .atd-btn,
  .v2x.atd .atd-cta-row .atd-upvote{ width:100%; justify-content:center; }
  .v2x.atd .atd-cta-row .atd-upvote{ padding:0 16px; }
}
@media (max-width:340px){
  /* Last resort, and deliberately far down the ramp: the icons are
     decorative (aria-hidden) and dropping them buys ~23px a tab, but the
     common phone widths are 360 / 375 / 390 / 393 — cutting at 400px
     stripped the glyphs on nearly every real handset to buy horizontal
     room the rail already scrolls for. Only the 320px class of device
     sheds them now. Labels are never touched at any width. */
  .v2x.atd .atd-tab-ic{ display:none; }
  .v2x.atd .v2-tabs a{ padding:9px 12px; }
}
@media (max-width:399.98px){
  /* 320-399px. 60px was smaller than the 64px tap target the CTA buttons use
     and read as a favicon beside a 1.46rem H1. */
  .v2x.atd .atd-hero{ --atd-logo:68px; }
  .v2x.atd .atd-h1{ font-size:1.34rem !important; }
  .v2x.atd .atd-statrail{ grid-template-columns:1fr 1fr; }
}

/* ── Motion preferences ────────────────────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-logo-tile,.v2x.atd .atd-logo-letter,.v2x.atd .atd-logo-halo,
  .v2x.atd .atd-chip,.v2x.atd .atd-chip-ic,
  .v2x.atd .atd-stat,.v2x.atd .atd-stat::after,.v2x.atd .atd-badge-featured,
  .v2x.atd .atd-badge-trending,.v2x.atd .atd-badge-certificate,
  .v2x.atd .atd-badge-editors,.v2x.atd .atd-badge-live,
  .v2x.atd .atd-badge-verified,.v2x.atd .atd-btn-ic,
  .v2x.atd .atd-cta-row .atd-btn,.v2x.atd .atd-cta-row .atd-upvote{ transition:none !important; }
  .v2x.atd .atd-logo-plate:hover .atd-logo-tile,
  .v2x.atd .atd-logo-duo > *:hover,
  .v2x.atd .atd-logo-plate:hover .atd-logo-letter,
  .v2x.atd .atd-chip:hover,.v2x.atd .atd-stat:hover,
  .v2x.atd .atd-badge-featured:hover,.v2x.atd .atd-badge-trending:hover,
  .v2x.atd .atd-badge-certificate:hover,.v2x.atd .atd-badge-editors:hover,
  .v2x.atd .atd-badge-live:hover,
  .v2x.atd .atd-badge-verified:hover,
  .v2x.atd .atd-cta-row .atd-btn:hover,.v2x.atd .atd-cta-row .atd-upvote:hover{ transform:none !important; }
  .v2x.atd .atd-badge-live .atd-live-dot{ animation:none !important; }
  .v2x.atd .atd-cta-row .atd-btn-primary:hover::after{ animation:none !important; }
  .v2x.atd .atd-chip:hover .atd-chip-ic{ transform:none !important; }
}

/* ══════════════════════════════════════════════════════════════════════════
   §SIDEBAR-ORBIT) The rail's rotating light, carried into the sidebar.

   Appended at the END of the file on purpose: it has to out-cascade the
   §SIDEBAR block, the tone ramps and the `body.theme-dark` surface list, so
   it must come last. Same reasoning as §HERO-PRO.

   ONE recipe, driven entirely by custom properties, used at six scales:

     card            7.5s   the slow ambient sweep — "this card is alive"
     alternative /   3.1s   a row you can actually click
       comparison
     tag chip        2.6s   fastest, because it is the smallest target
     platform pill   2.9s   links only (see the defect note below)
     share button    2.4s
     claim button    3.4s   slowest of the controls: it is the page's one
                            commitment, and haste is the wrong register

   THE HUE IS NOT FIXED. Every card already carries a `--tone-*` set (blue,
   violet, emerald, amber, rose, cyan, indigo, teal), and the orbit reads it,
   so Tags orbits indigo, Languages emerald, Alternatives amber, Share rose.
   Tag chips go further and orbit their OWN per-chip `.c0`–`.c5` tone. That is
   the difference between a effect pasted onto eight cards and a system: the
   light belongs to the card it is lighting.

   Because the gradient is written once, dark mode is not a second copy of a
   15-stop conic — it is two alpha numbers (`--orb-a1` / `--orb-a2`), lifted
   because a 55%-alpha tail that reads clearly over #fff disappears over
   #171922.

   `rgba(var(--orb-rgb), …)` rather than a hex plus `transparent`: a conic
   fading a colour to the `transparent` KEYWORD interpolates through
   transparent BLACK in sRGB and leaves a grey, dirty fringe on every tail.
   Fading to `rgba(same-rgb, 0)` keeps the hue all the way out.

   The card's own orbit DIMS to 30% whenever a control inside it is hovered,
   so the thing under the pointer always wins — identical choreography to the
   section rail, which is what makes the two read as one page.
   ══════════════════════════════════════════════════════════════════════════ */

/* Each tone's RGB triplet. A separate declaration rather than an edit to the
   ramp above, so the homepage-matched values stay byte-identical and this
   block remains removable in one piece. */
.v2x.atd .atd-sidebar [data-tone="blue"]   { --tone-rgb:76,141,242; }
.v2x.atd .atd-sidebar [data-tone="violet"] { --tone-rgb:139,92,246; }
.v2x.atd .atd-sidebar [data-tone="emerald"]{ --tone-rgb:16,185,129; }
.v2x.atd .atd-sidebar [data-tone="amber"]  { --tone-rgb:245,158,11; }
.v2x.atd .atd-sidebar [data-tone="rose"]   { --tone-rgb:244,63,94; }
.v2x.atd .atd-sidebar [data-tone="cyan"]   { --tone-rgb:34,184,217; }
.v2x.atd .atd-sidebar [data-tone="indigo"] { --tone-rgb:99,102,241; }
.v2x.atd .atd-sidebar [data-tone="teal"]   { --tone-rgb:20,184,166; }

.v2x.atd .atd-sidebar{
  --orb-rgb:54,128,237;      /* fallback hue for anything outside a toned card */
  --orb-hot:255,255,255;     /* the specular core of the comet */
  --orb-a1:.55;              /* leading tail */
  --orb-a2:.92;              /* trailing tail */
  --orb-a3:1;                /* core */
}
/* Over near-black the tails have to work harder or the comet reads as a
   single white dash with nothing attached to it. */
body.theme-dark .v2x.atd .atd-sidebar{ --orb-a1:.68; --orb-a2:1; }

@supports ((-webkit-mask-composite:xor) or (mask-composite:exclude)){
  /* ── The recipe. Two full-box mask layers — one clipped to the content box,
     one to the border box — composited with xor, leaving exactly the padding
     band. mask-clip follows border-radius, so the inner cut is a rounded
     rect on a rounded rect and the corners stay true.

     The @supports gate is load-bearing, not defensive: without mask-composite
     the two layers UNION and the conic paints as a SOLID BLOCK over the card,
     covering every label in it. Where the mask is missing there is simply no
     ring, and the existing border/lift/shadow hover carries the state. ── */
  .v2x.atd .atd-sidebar > .v2-card::before,
  .v2x.atd .col-lg-8 > .v2-card::before,
  .v2x.atd .atd-hero::before,
  .v2x.atd .atd-alt::before,
  .v2x.atd .atd-comp::before,
  .v2x.atd .atd-tags.is-links .atd-tag::before,
  .v2x.atd .atd-plat.is-link::before,
  .v2x.atd .atd-soc::before,
  .v2x.atd .atd-claim-btn::before{
    content:""; position:absolute; pointer-events:none;
    inset:-1px; z-index:1; border-radius:inherit; padding:var(--orb-t,1.5px);
    --atd-spin:0deg;
    background:conic-gradient(from var(--atd-spin),
      rgba(var(--orb-rgb), 0)                0deg,
      rgba(var(--orb-rgb), var(--orb-a1))   30deg,
      rgba(var(--orb-hot), var(--orb-a3))   52deg,
      rgba(var(--orb-rgb), var(--orb-a2))   74deg,
      rgba(var(--orb-rgb), 0)              118deg,
      rgba(var(--orb-rgb), 0)              180deg,
      rgba(var(--orb-rgb), var(--orb-a1))  210deg,
      rgba(var(--orb-hot), var(--orb-a3))  232deg,
      rgba(var(--orb-rgb), var(--orb-a2))  254deg,
      rgba(var(--orb-rgb), 0)              298deg,
      rgba(var(--orb-rgb), 0)              360deg);
    -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite:xor;
            mask-composite:exclude;
    opacity:0; transition:opacity .32s ease;
    animation:atd-orbit var(--orb-sp,3s) linear infinite;
    animation-play-state:paused;   /* a paused animation does not tick, so
                                      idle cards and chips cost nothing, and
                                      re-entering RESUMES the orbit rather
                                      than snapping back to 0deg */
  }

  /* ── Per-host geometry. Radius is restated wherever `inherit` would be
     wrong: the ring sits at inset:-1px, i.e. 1px OUTSIDE the host box, so a
     square-cornered host needs its radius plus that pixel. ── */
  /* Main-column sections orbit in brand blue, at the card's pace. */
  /* The hero orbits in brand blue too, one step slower than a section:
     it is the largest surface on the page and haste reads as fussy. */
  .v2x.atd .atd-hero::before{
    --orb-rgb:54,128,237; --orb-sp:9s; --orb-t:1.5px;
    border-radius:21px;
  }
  .v2x.atd .col-lg-8 > .v2-card::before{
    --orb-rgb:54,128,237; --orb-sp:7.5s; --orb-t:1.5px;
    border-radius:21px;
  }
  .v2x.atd .atd-sidebar > .v2-card::before{
    --orb-rgb:var(--tone-rgb, 54,128,237); --orb-sp:7.5s; --orb-t:1.5px;
    border-radius:21px;                       /* card 20px + the 1px offset */
  }
  /* The claim card keeps `overflow:hidden` for its corner bloom, which would
     clip a ring hung outside the box — so this one sits ON the padding edge
     instead, at the card radius less its 1px border. */
  .v2x.atd .atd-sidebar > .v2-card.atd-claim::before{ inset:0; border-radius:19px; }

  .v2x.atd .atd-alt::before{  --orb-sp:3.1s; --orb-t:1.5px; border-radius:13px; }
  .v2x.atd .atd-comp::before{ --orb-sp:3.1s; --orb-t:1.5px; border-radius:13px; }
  /* Chips orbit their OWN tone, not the card's — six hues in one card, each
     chip lighting up in the colour it already wears. */
  .v2x.atd .atd-tags.is-links .atd-tag::before{
    --orb-rgb:var(--t-rgb, 54,128,237); --orb-sp:2.6s; --orb-t:1.4px;
  }
  .v2x.atd .atd-plat.is-link::before{ --orb-sp:2.9s; --orb-t:1.5px; border-radius:13px; }
  .v2x.atd .atd-soc::before{
    --orb-rgb:var(--soc-rgb, 54,128,237); --orb-sp:2.4s; --orb-t:1.6px;
    inset:-2px; border-radius:50%;
  }
  /* The claim button also clips (it carries a sheen), so inset:0 again. */
  .v2x.atd .atd-claim-btn::before{
    --orb-rgb:255,255,255; --orb-hot:255,255,255; --orb-a1:.42; --orb-a2:.85;
    --orb-sp:3.4s; --orb-t:1.6px; inset:0; border-radius:11px; z-index:2;
  }

  /* Per-chip tag hues, mirroring the .c0–.c5 --t ramp. */
  .v2x.atd .atd-tag.c0{ --t-rgb:32,96,192; }
  .v2x.atd .atd-tag.c1{ --t-rgb:21,128,61; }
  .v2x.atd .atd-tag.c2{ --t-rgb:109,40,217; }
  .v2x.atd .atd-tag.c3{ --t-rgb:190,24,93; }
  .v2x.atd .atd-tag.c4{ --t-rgb:180,83,9; }
  .v2x.atd .atd-tag.c5{ --t-rgb:14,116,144; }
  body.theme-dark .v2x.atd .atd-tag.c0{ --t-rgb:157,192,246; }
  body.theme-dark .v2x.atd .atd-tag.c1{ --t-rgb:95,221,151; }
  body.theme-dark .v2x.atd .atd-tag.c2{ --t-rgb:196,171,251; }
  body.theme-dark .v2x.atd .atd-tag.c3{ --t-rgb:244,154,200; }
  body.theme-dark .v2x.atd .atd-tag.c4{ --t-rgb:244,190,96; }
  body.theme-dark .v2x.atd .atd-tag.c5{ --t-rgb:103,214,228; }

  /* Share buttons orbit in their own network colour. */
  .v2x.atd .atd-soc-fb{ --soc-rgb:24,119,242; }
  .v2x.atd .atd-soc-tw{ --soc-rgb:15,15,18; }
  .v2x.atd .atd-soc-li{ --soc-rgb:10,102,194; }
  .v2x.atd .atd-soc-wa{ --soc-rgb:37,211,102; }
  .v2x.atd .atd-soc-ln{ --soc-rgb:54,128,237; }
  .v2x.atd .atd-soc.is-copied{ --soc-rgb:18,166,111; }
  /* A near-black comet is invisible on a near-black panel. */
  body.theme-dark .v2x.atd .atd-soc-tw{ --soc-rgb:154,163,184; }

  /* ── Reveal. Keyboard is deliberately OUTSIDE the hover query — a keyboard
     on a touch screen is a real combination, and focus deserves the same
     premium answer as the pointer. ── */
  .v2x.atd .atd-alt:focus-visible::before,
  .v2x.atd .atd-comp:focus-visible::before,
  .v2x.atd .atd-tags.is-links .atd-tag:focus-visible::before,
  .v2x.atd .atd-plat.is-link:focus-visible::before,
  .v2x.atd .atd-soc:focus-visible::before,
  .v2x.atd .atd-claim-btn:focus-visible::before{ opacity:1; animation-play-state:running; }

  @media (hover:hover) and (pointer:fine){
    .v2x.atd .atd-sidebar > .v2-card:hover::before,
    .v2x.atd .col-lg-8 > .v2-card:hover::before,
    .v2x.atd .atd-hero:hover::before,
    .v2x.atd .atd-alt:hover::before,
    .v2x.atd .atd-comp:hover::before,
    .v2x.atd .atd-tags.is-links .atd-tag:hover::before,
    .v2x.atd .atd-plat.is-link:hover::before,
    .v2x.atd .atd-soc:hover::before,
    .v2x.atd .atd-claim-btn:hover::before{ opacity:1; animation-play-state:running; }

    /* The card steps back the moment a control inside it claims the pointer.
       Without :has() the card simply stays lit — a degradation, not a break. */
    .v2x.atd .atd-sidebar > .v2-card:has(.atd-alt:hover)::before,
    .v2x.atd .atd-sidebar > .v2-card:has(.atd-comp:hover)::before,
    .v2x.atd .atd-sidebar > .v2-card:has(.atd-tag:hover)::before,
    .v2x.atd .atd-sidebar > .v2-card:has(.atd-plat:hover)::before,
    .v2x.atd .atd-sidebar > .v2-card:has(.atd-soc:hover)::before,
    .v2x.atd .atd-sidebar > .v2-card:has(.atd-side-soc:hover)::before,
    .v2x.atd .atd-sidebar > .v2-card:has(.atd-claim-btn:hover)::before,
    .v2x.atd .atd-sidebar > .v2-card:has(.atd-link:hover)::before,
    .v2x.atd .atd-sidebar > .v2-card:has(.atd-flink:hover)::before{ opacity:.3; }
  }
  /* Touch has no hover, so the press itself lights the control — for exactly
     as long as the finger is down, which is when the feedback is wanted. */
  @media (hover:none){
    .v2x.atd .atd-alt:active::before,
    .v2x.atd .atd-comp:active::before,
    .v2x.atd .atd-tags.is-links .atd-tag:active::before,
    .v2x.atd .atd-plat.is-link:active::before,
    .v2x.atd .atd-soc:active::before,
    .v2x.atd .atd-claim-btn:active::before{ opacity:1; animation-play-state:running; }
  }
  /* Reduced motion keeps the LIGHT and drops the TRAVEL: the ring freezes at
     135deg, which reads as a designed gradient edge rather than an arbitrary
     one, and the bloom goes with it — a static glow on one arc looks like a
     rendering fault. */
  @media (prefers-reduced-motion:reduce){
    .v2x.atd .atd-sidebar > .v2-card::before,
    .v2x.atd .col-lg-8 > .v2-card::before,
    .v2x.atd .atd-hero::before,
    .v2x.atd .atd-alt::before,
    .v2x.atd .atd-comp::before,
    .v2x.atd .atd-tags.is-links .atd-tag::before,
    .v2x.atd .atd-plat.is-link::before,
    .v2x.atd .atd-soc::before,
    .v2x.atd .atd-claim-btn::before{ --atd-spin:135deg; animation:none !important; }
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   §SIDEBAR-FIX) Three defects found while wiring the orbit, all pre-existing.
   ══════════════════════════════════════════════════════════════════════════ */

/* 1 · A DEAD HOVER ON A NON-LINK. A platform without a URL renders as
   `<span class="atd-plat">`, but the hover rule was written at `.atd-plat`
   with no `.is-link` — so a static span lifted, changed border and filled its
   icon chip under the pointer while doing nothing on click. The FOCUS rule
   beside it was already correctly scoped, which is what gave it away. The
   tags block had solved this exact problem (`is-static` deliberately has no
   lift, "so the sidebar never offers a hover affordance that does nothing")
   — this restores that rule to the platforms. */
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-plat:not(.is-link):hover{
    border-color:var(--line); color:var(--ink);
    transform:none; box-shadow:none;
  }
  .v2x.atd .atd-plat:not(.is-link):hover .atd-plat-ic{
    background:var(--accent-soft); color:var(--accent-dark); transform:none;
  }
  /* 2 · …and the ones that ARE links hard-coded brand blue for their hover,
     inside a CYAN card. Now they answer in the card's own tone, like every
     other control in the sidebar. */
  .v2x.atd .atd-plat.is-link:hover{
    border-color:rgba(var(--tone-rgb,54,128,237), .55);
    color:var(--tone-ink, var(--accent-dark));
    box-shadow:0 8px 18px rgba(var(--tone-rgb,54,128,237), .20);
  }
  .v2x.atd .atd-plat.is-link:hover .atd-plat-ic{
    background:linear-gradient(135deg, var(--tone-1,#4C8DF2), var(--tone-2,#2060C0));
  }
  body.theme-dark .v2x.atd .atd-plat.is-link:hover{
    box-shadow:0 8px 20px rgba(0,0,0,.45);
  }
}

/* 3 · THE COMPARISON ROW WAS TWO GRADES BELOW THE ROW ABOVE IT. `.atd-comp`
   sat on a 150ms background swap and a 2px nudge while `.atd-alt` — the same
   kind of control, in the next card — had a lift, a shadow, a logo scale, an
   arrow slide, a focus ring, a dark twin and a reduced-motion answer.
   Worse, its hover ink was `var(--accent)` (#3680ED) on `--accent-soft2`
   (#f6f9ff), which measures 3.63:1 — under the 4.5:1 body-text bar — and it
   had no dark twin at all, so dark mode painted #3680ED on a dark panel.
   Brought onto the same footing, with --accent-dark (5.94:1). */
.v2x.atd .atd-comp{
  position:relative;
  border:1px solid transparent; margin-inline:-2px;
  transition:background-color 220ms ease, border-color 220ms ease, color 200ms ease,
             transform 300ms cubic-bezier(.16,1,.3,1), box-shadow 300ms ease;
}
.v2x.atd .atd-comp .lg{ transition:transform 320ms cubic-bezier(.16,1,.3,1), box-shadow 300ms ease; }
.v2x.atd .atd-comp .fa-chevron-right{ transition:transform 320ms cubic-bezier(.16,1,.3,1), color 200ms ease; }
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-comp:hover{
    background:rgba(var(--tone-rgb,54,128,237), .07);
    border-color:rgba(var(--tone-rgb,54,128,237), .28);
    color:var(--accent-dark); text-decoration:none;
    transform:translateY(-2px);
    box-shadow:0 8px 18px rgba(var(--tone-rgb,54,128,237), .16);
  }
  .v2x.atd .atd-comp:hover .lg{ transform:scale(1.06); box-shadow:0 5px 12px rgba(32,96,192,.20); }
  .v2x.atd .atd-comp:hover .fa-chevron-right{ transform:translateX(3px); color:var(--accent); }
  body.theme-dark .v2x.atd .atd-comp:hover{
    background:rgba(var(--tone-rgb,54,128,237), .12);
    border-color:rgba(var(--tone-rgb,54,128,237), .34);
    color:#9CC5F9; box-shadow:0 8px 20px rgba(0,0,0,.45);
  }
}
body:not(.admin-shell) .v2x.atd .atd-comp:focus-visible{
  outline:none; border-radius:var(--r-card);
  box-shadow:0 0 0 3px rgba(54,128,237,.85), 0 0 0 6px rgba(54,128,237,.22);
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-comp,.v2x.atd .atd-comp .lg,.v2x.atd .atd-comp .fa-chevron-right{ transition:none !important; }
  .v2x.atd .atd-comp:hover{ transform:none; }
  .v2x.atd .atd-comp:hover .lg,
  .v2x.atd .atd-comp:hover .fa-chevron-right{ transform:none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   §SIDEBAR-RESP) The sidebar is `col-lg-4`, so below 992px it stops being a
   rail and becomes a full-width stack — the cards get WIDER there, not
   narrower, and the real pressure is vertical: eight cards a reader now has
   to scroll past. So the ramp trims height (padding, gaps, header chip) and
   never touches a label. Nothing in these cards truncates at any width.
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width:991.98px){
  /* Full-width now, so chip rows can breathe wider before wrapping. */
  .v2x.atd .atd-sidebar > .v2-card.v2-section{ margin-bottom:14px; }
  .v2x.atd .atd-plats{ grid-template-columns:repeat(auto-fill,minmax(170px,1fr)); }
}
@media (max-width:767.98px){
  .v2x.atd .atd-side-title{ font-size:1.05rem; margin-bottom:14px; }
  .v2x.atd .atd-side-ihead{ gap:10px; margin-bottom:12px; }
  .v2x.atd .atd-alt{ padding:9px 8px; gap:10px; }
}
@media (max-width:575.98px){
  .v2x.atd .atd-sidebar > .v2-card{ border-radius:16px; }
  .v2x.atd .atd-sidebar > .v2-card.v2-section{ margin-bottom:12px; }
  .v2x.atd .atd-side-ic{ width:32px; height:32px; border-radius:9px; font-size:.8rem; }
  .v2x.atd .atd-side-title{ font-size:1rem; }
  .v2x.atd .atd-tag{ padding:7px 12px; }          /* taller, not wider: a finger */
  .v2x.atd .atd-plat{ padding:9px 12px 9px 9px; }
  .v2x.atd .atd-soc{ width:42px; height:42px; }
  .v2x.atd .atd-socials{ gap:10px; }
  .v2x.atd .atd-alt .lg,.v2x.atd .atd-alt img{ width:38px; height:38px; border-radius:10px; }
}
/* The card radius shrinks at 576px, so the orbit that hangs 1px outside it
   has to follow or the ring corners bulge past the card's. */
@supports ((-webkit-mask-composite:xor) or (mask-composite:exclude)){
  @media (max-width:575.98px){
    .v2x.atd .atd-sidebar > .v2-card::before{ border-radius:17px; }
    .v2x.atd .atd-sidebar > .v2-card.atd-claim::before{ border-radius:15px; }
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   §CARD-WASH) The claim card's gradient, generalised to every sidebar card.

   The claim card was the only one with any depth to it: a 150deg diagonal
   wash (#f7faff → #fff → #f4f8ff), a 210px radial bloom hanging off the
   top-right corner, and a tinted border. Beside seven flat white cards it
   read as the one designed surface on the rail. This gives all eight the same
   treatment — but keyed to `--tone-rgb`, so the wash and the bloom arrive in
   the card's OWN hue rather than eight copies of blue.

   TWO MECHANISMS, chosen for two different reasons:

   · The WASH is a background LAYER on the card. Backgrounds clip to the
     rounded border box for free, so it needs no `overflow:hidden` — which
     matters, because §SIDEBAR deliberately withholds that: the chips and
     links inside ring their focus state with a box-shadow, and clipping
     would slice those rings off at the card edge.

   · The BLOOM is `::after`, because it has to ANIMATE on hover (opacity and
     a scale from the corner it hangs off) and background layers cannot
     cross-fade. `::before` is already the orbit ring — see §SIDEBAR-ORBIT.

   `isolation:isolate` on the card is what makes `z-index:-1` mean what it
   should. A card with `position:relative` and no z-index is NOT a stacking
   context, so a negative-z pseudo would escape to an ancestor's context and
   paint BEHIND the card's own background, i.e. vanish. Isolating it keeps the
   bloom exactly where it belongs: above the card's background, beneath every
   word on it — and no `z-index:1` on the children is needed, which is how the
   claim card had to solve the same problem.

   ⚠️ This SUPERSEDES the claim card's own wash. `.v2x.atd .atd-claim` is
   (0,3,0) and this is (0,4,0), and it comes later besides, so the shared rule
   wins for both the default (data-tone blue) and the owner-managed
   (data-tone emerald) variants — which is the point: one system, not two. The
   claim card keeps its bespoke `.atd-claim-glow` SPAN as its bloom, so the
   shared `::after` is suppressed there rather than stacking a second one.
   ══════════════════════════════════════════════════════════════════════════ */
.v2x.atd .atd-sidebar > .v2-card{
  isolation:isolate;
  /* Middle stop fades to the SAME hue at zero alpha, never the `transparent`
     keyword — that interpolates through transparent black in sRGB and dirties
     the fade. Same rule as the orbit's tails. */
  background:
    linear-gradient(150deg,
      rgba(var(--tone-rgb,54,128,237), .055) 0%,
      rgba(var(--tone-rgb,54,128,237), 0)   46%,
      rgba(var(--tone-rgb,54,128,237), .04) 100%) no-repeat,
    #fff;
  border-color:rgba(var(--tone-rgb,54,128,237), .17);
}
.v2x.atd .atd-sidebar > .v2-card::after{
  content:""; position:absolute; inset:0; z-index:-1; pointer-events:none;
  border-radius:inherit;
  /* The bloom's CENTRE sits outside the box on purpose — only its tail bleeds
     into the corner, which is what makes it read as light falling on the card
     rather than a circle drawn on it. */
  background:radial-gradient(210px 210px at calc(100% + 34px) -46px,
    rgba(var(--tone-rgb,54,128,237), .22) 0%,
    rgba(var(--tone-rgb,54,128,237), 0)  70%) no-repeat;
  opacity:.9; transform-origin:100% 0;
  transition:opacity 360ms ease, transform 520ms cubic-bezier(.16,1,.3,1);
}
/* One bloom per card: the claim card already ships a tuned span, including the
   green owner-managed variant the tone ramp does not model. */
.v2x.atd .atd-sidebar > .v2-card.atd-claim::after{ content:none; }

/* (0,5,1) — it has to out-rank `body.theme-dark .v2x.atd .v2-card` (0,4,1) in
   the shared surface list, which would otherwise hand the card a flat #171922
   back and drop the wash entirely. The same element-count flip that the
   section rail's active tab hits. */
body.theme-dark .v2x.atd .atd-sidebar > .v2-card{
  background:
    linear-gradient(150deg,
      rgba(var(--tone-rgb,54,128,237), .09) 0%,
      rgba(var(--tone-rgb,54,128,237), 0)  46%,
      rgba(var(--tone-rgb,54,128,237), .06) 100%) no-repeat,
    var(--dk-surface-2,#17171B);
  border-color:rgba(var(--tone-rgb,54,128,237), .26);
}
body.theme-dark .v2x.atd .atd-sidebar > .v2-card::after{
  background:radial-gradient(210px 210px at calc(100% + 34px) -46px,
    rgba(var(--tone-rgb,54,128,237), .18) 0%,
    rgba(var(--tone-rgb,54,128,237), 0)  70%) no-repeat;
}

@media (hover:hover) and (pointer:fine){
  /* The bloom swells from the corner it hangs off, so the light appears to
     move rather than simply brighten. Paired with the orbit on the same
     hover, that is the card's whole answer — it still does not lift beyond
     the 3px §SIDEBAR already gives it. */
  .v2x.atd .atd-sidebar > .v2-card:hover::after{ opacity:1; transform:scale(1.16); }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-sidebar > .v2-card::after{ transition:none !important; }
  .v2x.atd .atd-sidebar > .v2-card:hover::after{ transform:none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   §SPINE-BLUE) The Tool Information card's treatment, in brand blue, on the
   hero · the section rail · all thirteen main-column sections.

   THE REFERENCE IS THE SIDEBAR'S "Tool Information" CARD, not an invention:
   20px radius, a soft 150deg diagonal wash, a concentrated corner bloom, a
   hairline tinted edge, a gradient icon TILE beside the heading, and the
   orbit ring on hover. Everything here is that card's recipe with the tone
   pinned to brand blue instead of read from `--tone-rgb`.

   The sidebar is NOT touched by this block — it keeps its eight per-card
   tones. `.atd-sidebar > .v2-card` and `.col-lg-8 > .v2-card` are disjoint.

   ⚠️ TWO EARLIER ATTEMPTS FAILED AND BOTH LESSONS ARE LOAD-BEARING:

   1. A wash is invisible unless it departs from the GROUND. `--bg` is
      #f6f8fc, so blue at .05 puts a white card's corner at #f5f9fe — the
      page's own colour. Measure the composite against #f6f8fc, never #fff.

   2. Cranking ONE broad radial to .24 to compensate does not read as premium,
      it reads as a blue haze over half the card. What makes the reference
      card work is CONTRAST WITHIN THE CARD: a nearly-white field, a soft
      diagonal, and a small saturated bloom in one corner — plus the fully
      saturated gradient tile as the anchor. The blue lives in the ACCENTS,
      not in the field.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Card surface ─────────────────────────────────────────────────────────
   `> .v2-card` is a DIRECT child on purpose: reviews and the FAQ accordion
   nest their own cards, and those stay plain rather than putting a washed
   card inside a washed card. Verified against the real DOM — 13 of 13 direct
   children match, out of 14 `.v2-card` in the column. */
.v2x.atd .col-lg-8 > .v2-card{
  position:relative; isolation:isolate;
  border-radius:20px;
  background:
    linear-gradient(150deg,
      rgba(54,128,237,.055) 0%,
      rgba(54,128,237,0)   46%,
      rgba(54,128,237,.04) 100%) no-repeat,
    #fff;
  border:1px solid rgba(54,128,237,.17);
  box-shadow:
    0 1px 2px rgba(16,24,40,.04),
    0 6px 20px rgba(16,24,40,.05);
  transition:border-color .2s ease, box-shadow .24s ease;
}
/* Corner bloom. A background LAYER would clip for free, but this has to
   ANIMATE on hover and background layers cannot cross-fade — hence ::after,
   with ::before left to the orbit ring. `isolation:isolate` above is what
   makes z-index:-1 mean "over the card's own background, under every word on
   it": a card with position:relative and no z-index is NOT a stacking
   context, so the pseudo would escape to an ancestor's and paint behind the
   background entirely. */
.v2x.atd .col-lg-8 > .v2-card::after{
  content:""; position:absolute; inset:0; z-index:-1; pointer-events:none;
  border-radius:inherit;
  background:radial-gradient(280px 280px at calc(100% + 40px) -60px,
    rgba(54,128,237,.20) 0%, rgba(54,128,237,0) 70%) no-repeat;
  opacity:.9; transform-origin:100% 0;
  transition:opacity 360ms ease, transform 520ms cubic-bezier(.16,1,.3,1);
}
body.theme-dark .v2x.atd .col-lg-8 > .v2-card{
  background:
    linear-gradient(150deg,
      rgba(54,128,237,.10) 0%,
      rgba(54,128,237,0)  46%,
      rgba(54,128,237,.07) 100%) no-repeat,
    var(--dk-surface-2,#17171B);
  border-color:rgba(54,128,237,.26);
  box-shadow:0 1px 2px rgba(0,0,0,.40), 0 6px 20px rgba(0,0,0,.35);
}
body.theme-dark .v2x.atd .col-lg-8 > .v2-card::after{
  background:radial-gradient(280px 280px at calc(100% + 40px) -60px,
    rgba(54,128,237,.17) 0%, rgba(54,128,237,0) 70%) no-repeat;
}

/* ── The gradient icon tile — the reference card's single strongest cue ────
   Nine headings lead with an inline lucide `<svg>` and four with a FontAwesome
   `<i>`; both become the tile. The svg carries width/height ATTRIBUTES of 18,
   which CSS overrides — with `box-sizing:border-box` and 8px of padding the
   glyph draws at 18px inside a 34px plate, matching `.atd-side-ic` exactly.
   `color:#fff !important` is required, not lazy: three of the four `<i>`
   glyphs carry Bootstrap's `.text-muted`, which is itself `!important`. */
.v2x.atd .col-lg-8 > .v2-card .v2-section-title{
  gap:11px; align-items:center;
}
.v2x.atd .col-lg-8 > .v2-card .v2-section-title > svg:first-child,
.v2x.atd .col-lg-8 > .v2-card .v2-section-title > i:first-child{
  box-sizing:border-box; flex:0 0 auto;
  width:34px; height:34px; border-radius:10px;
  display:inline-flex; align-items:center; justify-content:center;
  background:linear-gradient(135deg,#4C8DF2,#2060C0);
  color:#fff !important;
  box-shadow:0 4px 12px rgba(32,96,192,.30);
  transition:transform 380ms cubic-bezier(.16,1,.3,1), box-shadow 300ms ease;
}
.v2x.atd .col-lg-8 > .v2-card .v2-section-title > svg:first-child{ padding:8px; }
.v2x.atd .col-lg-8 > .v2-card .v2-section-title > i:first-child{ font-size:.85rem; }

/* ── Hover ────────────────────────────────────────────────────────────────
   The orbit ring is wired in §SIDEBAR-ORBIT (one recipe, seven hosts). Here
   the card answers with LIGHT only — the bloom swells from the corner it
   hangs off, the edge brightens, the tile lifts. No translateY: the reference
   card lifts because it is a 300px block of links, and a 900px prose section
   sliding under the pointer as you read it is not the same gesture. */
@media (hover:hover) and (pointer:fine){
  .v2x.atd .col-lg-8 > .v2-card:hover{
    border-color:rgba(54,128,237,.34);
    box-shadow:
      0 2px 6px rgba(16,24,40,.06),
      0 18px 44px -14px rgba(32,96,192,.22);
  }
  .v2x.atd .col-lg-8 > .v2-card:hover::after{ opacity:1; transform:scale(1.16); }
  .v2x.atd .col-lg-8 > .v2-card:hover .v2-section-title > svg:first-child,
  .v2x.atd .col-lg-8 > .v2-card:hover .v2-section-title > i:first-child{
    transform:scale(1.07) rotate(-3deg);
    box-shadow:0 6px 16px rgba(32,96,192,.40);
  }
  body.theme-dark .v2x.atd .col-lg-8 > .v2-card:hover{
    border-color:rgba(54,128,237,.46);
    box-shadow:0 2px 6px rgba(0,0,0,.50), 0 18px 44px -14px rgba(0,0,0,.55);
  }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .col-lg-8 > .v2-card,
  .v2x.atd .col-lg-8 > .v2-card::after,
  .v2x.atd .col-lg-8 > .v2-card .v2-section-title > svg:first-child,
  .v2x.atd .col-lg-8 > .v2-card .v2-section-title > i:first-child{ transition:none !important; }
  .v2x.atd .col-lg-8 > .v2-card:hover::after{ transform:none; }
  .v2x.atd .col-lg-8 > .v2-card:hover .v2-section-title > svg:first-child,
  .v2x.atd .col-lg-8 > .v2-card:hover .v2-section-title > i:first-child{ transform:none; }
}
@media (max-width:575.98px){
  .v2x.atd .col-lg-8 > .v2-card{ border-radius:16px; }
  .v2x.atd .col-lg-8 > .v2-card .v2-section-title > svg:first-child,
  .v2x.atd .col-lg-8 > .v2-card .v2-section-title > i:first-child{ width:32px; height:32px; border-radius:9px; }
  .v2x.atd .col-lg-8 > .v2-card .v2-section-title > svg:first-child{ padding:7px; }
}
/* The orbit hangs 1px outside the card, so its radius has to follow. */
@supports ((-webkit-mask-composite:xor) or (mask-composite:exclude)){
  @media (max-width:575.98px){
    .v2x.atd .col-lg-8 > .v2-card::before{ border-radius:17px; }
  }
}

/* ── Hero ────────────────────────────────────────────────────────────────
   Defined once, in §HERO-BLUE at the END of this file. A copy used to live
   here too; both parsed, the later one won, and this one was invisible dead
   code waiting to swallow someone edit. Do not re-add it. ── */

/* ── The section rail ─────────────────────────────────────────────────────
   Both of its pseudos are spoken for — ::before is the orbit ring, ::after
   the shine bar — so the wash rides the background. It is only ~68px tall, so
   the diagonal gets a hard 150deg sweep and the bloom a small px radius;
   a percentage falloff would complete in 30px and read as a band. Every chip
   carries its own opaque fill, so the wash never sits behind rail text. */
.v2x.atd .atd-tabsbar{
  background:
    radial-gradient(190px 190px at 0% 0%, rgba(54,128,237,.16) 0%, rgba(54,128,237,0) 72%) no-repeat,
    linear-gradient(150deg, rgba(54,128,237,.05) 0%, rgba(54,128,237,0) 52%, rgba(54,128,237,.035) 100%) no-repeat,
    #fff;
}
body.theme-dark .v2x.atd .atd-tabsbar{
  background:
    radial-gradient(190px 190px at 0% 0%, rgba(54,128,237,.17) 0%, rgba(54,128,237,0) 72%) no-repeat,
    linear-gradient(150deg, rgba(54,128,237,.09) 0%, rgba(54,128,237,0) 52%, rgba(54,128,237,.06) 100%) no-repeat,
    var(--dk-surface-2,#17171B);
}

/* ── Light --muted2, forced by the wash ────────────────────────────────────
   #8a8a9a measured 3.40:1 on a flat white card — already under the 4.5:1
   body-text bar before any of this, and worse on the wash. #5F5F6B measures
   4.9-6.3:1 across every washed ground here and on the sidebar's tone-washed
   cards, and is still plainly fainter than --muted (#4A4A5A). It carries the
   dates, price periods and subtitles — grep var(--muted2) for the sites.
   NOTE: the base token block still declares #8a8a9a; this later (0,2,0) rule
   overrides it, so BOTH appear in the stylesheet text and a grep alone will
   mislead. Resolve the cascade. */
/* ══════════════════════════════════════════════════════════════════════════
   §GOLD) One gold for every star on all three detail pages

   Before this there were FIVE: --amber #F59E0B on `.v2-stars` and `.atd-rate`,
   #BC6E08 on the hero stat rail, --rvx-star #C96C05 in the reviews kit, a
   #C96C05->#92400E orange-brown gradient on the rating tiles, and --warning
   from the shared kit underneath. Two of them (the #F59E0B pair) measured
   2.15:1 on a white card — they were failing the 3:1 non-text bar as well as
   looking inconsistent.

   ⚠️ #F59E0B IS A DELIBERATE, INFORMED CHOICE — DO NOT "FIX" IT BACK.
   It measures 2.15:1 on a white card, 2.02 on the page ground and 2.09 on the
   form panel, i.e. under the 3:1 WCAG 1.4.11 bar for non-text content. That
   was raised, measured and shown before it was adopted; the brightest gold
   that DOES clear 3:1 everywhere is about #B8860B (3.25 / 3.06 / 3.17), and
   this section shipped on it for one revision. The owner chose the brighter
   brand amber for the look, with the ratios on the table. Two things make
   that defensible in practice, and both must survive any edit here:
     · every star is accompanied by its NUMERIC rating in adjacent text
       ("4.8", "5", "Not rated yet"), so no information lives in the glyph
       alone, and
     · --gold-deep is painted UNDER each glyph as a drop-shadow, which gives
       the shape a defined edge against a white card even where the fill does
       not carry it.
   If the bar is ever enforced, the one-line change is --gold back to #B8860B.

   THE TILE IS A SEPARATE PROBLEM. `.rvx-star.is-on` fills the tile and keeps a
   WHITE glyph, so the contrast that matters is white-against-tile: on flat
   #F59E0B that is 2.15:1 and the star nearly vanishes. The tile therefore runs
   a GRADIENT from --gold-tile to --gold-deep (#F59E0B -> #B45309, white = 2.15
   at the lightest corner but 5.02 across most of the tile), which is also what
   makes it read as metal rather than as a flat amber square. */
.v2x.atd{
  --gold:#F59E0B;        /* the star glyph — the brand amber, chosen 2026-08-13 */
  --gold-lift:#FCD34D;   /* metallic highlight, gradients only */
  --gold-deep:#B45309;   /* shadow end, glyph drop-shadow, gradient dark end */
  --gold-tile:#F59E0B;   /* light end of a filled tile under a white glyph */
}
body.theme-dark .v2x.atd{
  /* Same amber: 8.16:1 on the #171922 card, so dark needs no lift. Only the
     gradient ends move, to keep depth against a near-black surface. */
  --gold:#F59E0B; --gold-lift:#FDE68A; --gold-deep:#D97706; --gold-tile:#F59E0B;
}
/* The one shared star treatment. The drop-shadow is what makes a flat fill
   read as metal; it is a --gold-deep shadow, not a black one, so it deepens
   the gold instead of greying it. */
.v2x.atd .v2-stars,
.v2x.atd .atd-rate .fa-star{
  color:var(--gold);
  filter:drop-shadow(0 1px 0 rgba(180,83,9,.42));
}
body.theme-dark .v2x.atd .v2-stars,
body.theme-dark .v2x.atd .atd-rate .fa-star{ filter:drop-shadow(0 1px 0 rgba(0,0,0,.45)); }

.v2x.atd{ --muted2:#5F5F6B; }

/* ── Bottom CTA band is a saturated brand surface already and is left alone;
   washing a wash would only mud it. ────────────────────────────────────── */

/* ══════════════════════════════════════════════════════════════════════════
   §HERO-BLUE) The hero on the Tool Information card's recipe. Blue only.

   Identical language to §SPINE-BLUE and to the sidebar card it copies —
   150deg diagonal wash · corner bloom on ::after that swells on hover ·
   hairline blue edge · the orbit ring on ::before — one step deeper, because
   it is the hero.

   TWO THINGS WERE REMOVED FROM THE PREVIOUS PASS, both on request:

   · THE VIOLET. The hero used to carry a violet radial on the right and a
     violet stop in its top hairline, as a deliberate asymmetry marking it out
     from the sections. The page reads as one blue system now, so the violet
     is gone from both the wash and the hairline. `--violet` is untouched as a
     token — the tag chips and the sidebar's violet tone still use it.

   · THE SHINE SWEEP. A `background-position` glint on ::after crossed the
     card once per hover. It was a second motion competing with the orbit for
     the same gesture, and the orbit is the one that was asked for. ::after is
     back to what the reference card uses it for: the corner bloom.

   THE BRAND HAIRLINE stays a background LAYER rather than a pseudo — that is
   what freed ::before for the ring, and it is strictly better anyway:
   backgrounds clip to the rounded border box for free, so it needs neither a
   radius of its own nor the breakpoint twin that restated it at 16px.
   Multi-layer backgrounds must restate `background-size`/`-position` for
   EVERY layer in order, so this uses `background-image` + `background-color`
   rather than the shorthand.
   ══════════════════════════════════════════════════════════════════════════ */
.v2x.atd .atd-hero{
  background-image:
    /* 1 · brand hairline along the top edge — blue only now */
    linear-gradient(90deg,
      rgba(54,128,237,0)   0%,
      rgba(54,128,237,.55) 20%,
      rgba(96,164,245,.95) 50%,
      rgba(54,128,237,.55) 80%,
      rgba(54,128,237,0)  100%),
    /* 2 · the reference card's 150deg diagonal, one step deeper */
    linear-gradient(150deg,
      rgba(54,128,237,.085) 0%,
      rgba(54,128,237,0)   46%,
      rgba(54,128,237,.05) 100%);
  background-repeat:no-repeat;
  background-size:100% 2px, auto;
  background-position:0 0, 0 0;
  background-color:#fff;
  border-color:rgba(54,128,237,.22);
  transition:border-color .22s ease, box-shadow .26s ease;
}
body.theme-dark .v2x.atd .atd-hero{
  background-image:
    linear-gradient(90deg,
      rgba(54,128,237,0)    0%,
      rgba(96,164,245,.60) 20%,
      rgba(157,200,255,.95) 50%,
      rgba(96,164,245,.60) 80%,
      rgba(54,128,237,0)  100%),
    linear-gradient(150deg,
      rgba(54,128,237,.13) 0%,
      rgba(54,128,237,0)  46%,
      rgba(54,128,237,.08) 100%);
  background-repeat:no-repeat;
  background-size:100% 2px, auto;
  background-position:0 0, 0 0;
  background-color:var(--dk-surface-2,#17171B);
  border-color:rgba(54,128,237,.30);
}

/* Corner bloom — the same ::after the reference card uses, at the hero's
   scale. A background LAYER would clip for free, but this has to ANIMATE on
   hover and background layers cannot cross-fade. `isolation:isolate` (set in
   §HERO-PRO) is what makes z-index:-1 mean "over the hero's own background,
   under every word and control on it": an element with position:relative and
   no z-index is NOT a stacking context, so the pseudo would escape to an
   ancestor's and paint behind the background entirely. */
.v2x.atd .atd-hero::after{
  content:""; position:absolute; inset:0; z-index:-1; pointer-events:none;
  border-radius:inherit;
  background:radial-gradient(360px 360px at -50px -80px,
    rgba(54,128,237,.22) 0%, rgba(54,128,237,0) 70%) no-repeat;
  opacity:.9; transform-origin:0 0;
  transition:opacity 360ms ease, transform 520ms cubic-bezier(.16,1,.3,1);
}
body.theme-dark .v2x.atd .atd-hero::after{
  background:radial-gradient(360px 360px at -50px -80px,
    rgba(54,128,237,.18) 0%, rgba(54,128,237,0) 70%) no-repeat;
}

/* Hover — light only, and only the orbit moves. No translateY: the reference
   card lifts because it is a 300px block of links; the hero is the page's
   masthead and sliding it under the pointer is not the same gesture. */
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-hero:hover::after{ opacity:1; transform:scale(1.14); }
  .v2x.atd .atd-hero:hover{
    border-color:rgba(54,128,237,.38);
    box-shadow:0 2px 6px rgba(15,23,42,.06), 0 22px 52px -18px rgba(32,96,192,.24);
  }
  body.theme-dark .v2x.atd .atd-hero:hover{
    border-color:rgba(54,128,237,.50);
    box-shadow:0 2px 6px rgba(0,0,0,.5), 0 22px 52px -18px rgba(0,0,0,.6);
  }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-hero,.v2x.atd .atd-hero::after{ transition:none !important; }
  .v2x.atd .atd-hero:hover::after{ transform:none; }
}
/* The orbit hangs 1px outside the card, so its radius follows the hero's own
   16px at the phone step. */
@supports ((-webkit-mask-composite:xor) or (mask-composite:exclude)){
  @media (max-width:575.98px){
    .v2x.atd .atd-hero::before{ border-radius:17px; }
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   §PROSCONS) Pros & Cons — two toned panels on the sidebar-card recipe.

   THE REFERENCE IS THE SIDEBAR, not an invention. Each panel is a
   `.atd-sidebar > .v2-card` in miniature: 150deg diagonal wash · hairline
   tinted edge · corner bloom on ::after that swells on hover · orbit ring on
   ::before · gradient icon tile · count badge in the tone. The only thing
   that changes is which tone drives it — emerald for pros, rose for cons,
   both lifted straight out of the §SIDEBAR ramp so this section reads as
   part of the same system rather than a second one.

   WHAT THE OLD LAYOUT GOT WRONG. It was a bootstrap `row g-4` of two bare
   columns of `.small` text. Live data is 6-8 pros against 4-7 cons on every
   one of the 33 listings, so the right column always ran short and the
   leftover space read as a HOLE punched in the card rather than as padding.
   Panels fix that for free: whitespace inside a bordered, washed surface is
   breathing room. The lists flex so both panels stretch to a common height.

   ⚠️ NO HOVER AFFORDANCE THAT DOES NOTHING. Neither the rows nor the panels
   are links, so their hover is a READING HIGHLIGHT, not a control: no lift,
   no translate, no cursor change, no border switch — light and ink only.
   This is the rule §SIDEBAR-FIX had to restore to `.atd-plat` after a static
   span spent 27 pages pretending to be clickable. Do not "improve" it into a
   card lift.

   Appended at the END of the file, like §SIDEBAR-ORBIT and §HERO-PRO: the
   panels sit inside a `.col-lg-8 > .v2-card`, so they have to out-cascade
   §SPINE-BLUE's card rules and the dark-mode surface list above.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Tone. `--pc-rgb` is the hue everything translucent is built from (wash,
   bloom, orbit, shadows). The opaque values are separate because a hue that
   works as a 6%-alpha wash is not the same hue that can carry white on it —
   see the tile note below. ── */
.v2x.atd .atd-pc-col.is-pro,
.v2x.atd .atd-pc-tag.is-pro{
  --pc-rgb:16,185,129;
  --pc-tile-1:#0C9A6E; --pc-tile-2:#08795A;   /* header tile ramp */
  --pc-solid:#08795A;                          /* marker fill on hover, light */
  --pc-bg:#E6F8F1; --pc-ink:#08795A; --pc-line:#C6EEDF;
}
.v2x.atd .atd-pc-col.is-con,
.v2x.atd .atd-pc-tag.is-con{
  --pc-rgb:244,63,94;
  --pc-tile-1:#F43F5E; --pc-tile-2:#B31D3C;
  --pc-solid:#B31D3C;
  --pc-bg:#FEECEF; --pc-ink:#B31D3C; --pc-line:#FBD2DA;
}
/* Dark twins are the §SIDEBAR dark ramp's own emerald / rose entries. */
body.theme-dark .v2x.atd .atd-pc-col.is-pro,
body.theme-dark .v2x.atd .atd-pc-tag.is-pro{ --pc-bg:rgba(16,185,129,.18); --pc-ink:#6EE7BE; --pc-line:rgba(52,211,153,.30); }
body.theme-dark .v2x.atd .atd-pc-col.is-con,
body.theme-dark .v2x.atd .atd-pc-tag.is-con{ --pc-bg:rgba(244,63,94,.18);  --pc-ink:#FB9BB0; --pc-line:rgba(251,113,133,.30); }

/* ══ 1 · Balance strip ═══════════════════════════════════════════════════
   ONE segment per listed point, never a proportional score bar: a 60/40
   split of a tally is a fact, a 60/40 split drawn as one continuous bar
   invites the reader to see it as "60% good", which the data does not say.
   Counting ticks cannot be misread. Past 24 points the blade falls back to
   two proportional bars (data-mode="ratio") because thinner segments than
   their own gaps stop reading as countable at all.

   The strip is not a heading and not a control; it is aria-hidden in the
   blade, with the two flanking chips carrying the numbers for assistive tech.
   ══════════════════════════════════════════════════════════════════════ */
.v2x.atd .atd-pc-bal{
  display:grid; grid-template-columns:auto minmax(0,1fr) auto;
  align-items:center; gap:14px;
  margin:-2px 0 22px;
}
.v2x.atd .atd-pc-tag{
  display:inline-flex; align-items:center; gap:7px;
  padding:6px 13px; border-radius:var(--r-pill);
  background:var(--pc-bg); color:var(--pc-ink); border:1px solid var(--pc-line);
  font-family:var(--font); font-size:.83rem; font-weight:600; white-space:nowrap;
  transition:transform .26s cubic-bezier(.16,1,.3,1), box-shadow .26s ease;
}
.v2x.atd .atd-pc-tag b{ font-weight:800; font-size:.95rem; font-variant-numeric:tabular-nums; }
.v2x.atd .atd-pc-tag svg{ flex:0 0 auto; opacity:.9; }

.v2x.atd .atd-pc-bar{ display:flex; align-items:stretch; gap:4px; min-width:0; height:10px; }
.v2x.atd .atd-pc-bar .seg{
  flex:1 1 0; min-width:3px; border-radius:var(--r-pill);
  transition:transform .34s cubic-bezier(.16,1,.3,1), opacity .3s ease, box-shadow .3s ease;
}
/* Light mode wants the DARK end of each ramp — #10B981 on a white card is
   2.54:1, under the 3:1 floor for a graphic that carries meaning. #059669 is
   3.77:1. Dark mode inverts: the same #10B981 is 6.19:1 on the dark card,
   and #059669 would sink into it. Measured, not eyeballed. */
.v2x.atd .atd-pc-bar .seg.is-pro{ background:linear-gradient(180deg,#059669,#047857); }
.v2x.atd .atd-pc-bar .seg.is-con{ background:linear-gradient(180deg,#F43F5E,#E11D48); }
body.theme-dark .v2x.atd .atd-pc-bar .seg.is-pro{ background:linear-gradient(180deg,#10B981,#059669); }
body.theme-dark .v2x.atd .atd-pc-bar .seg.is-con{ background:linear-gradient(180deg,#FB7185,#F43F5E); }

/* ══ 2 · Grid ════════════════════════════════════════════════════════════
   One empty side collapses to a single full-width panel — an empty bordered
   box beside a full one is worse than no box at all.
   ══════════════════════════════════════════════════════════════════════ */
.v2x.atd .atd-pc-grid{
  display:grid; grid-template-columns:repeat(2,minmax(0,1fr));
  gap:18px; align-items:stretch;
}
.v2x.atd .atd-pc-grid[data-pc-side="pros"],
.v2x.atd .atd-pc-grid[data-pc-side="cons"]{ grid-template-columns:minmax(0,1fr); }

/* ══ 3 · Panel surface ═══════════════════════════════════════════════════
   Layer order matters and every layer must restate its size/position: a
   multi-layer `background` shorthand silently drops the layers it is not
   given values for. `background-image` + `background-color` instead, exactly
   as §HERO-BLUE does for the same reason.

   The hairline is a background LAYER rather than a pseudo because both
   pseudos are already spoken for (::before = orbit ring, ::after = bloom),
   and because backgrounds clip to the rounded border box for free — it needs
   no radius of its own and no breakpoint twin when the radius changes.
   ══════════════════════════════════════════════════════════════════════ */
.v2x.atd .atd-pc-col{
  position:relative; isolation:isolate;
  display:flex; flex-direction:column;
  padding:18px 18px 16px; border-radius:16px;
  background-image:
    /* 1 · tone hairline along the top edge */
    linear-gradient(90deg,
      rgba(var(--pc-rgb),0)   0%,
      rgba(var(--pc-rgb),.45) 22%,
      rgba(var(--pc-rgb),.85) 50%,
      rgba(var(--pc-rgb),.45) 78%,
      rgba(var(--pc-rgb),0)  100%),
    /* 2 · the reference card's 150deg diagonal */
    linear-gradient(150deg,
      rgba(var(--pc-rgb),.085) 0%,
      rgba(var(--pc-rgb),.015) 46%,
      rgba(var(--pc-rgb),.06) 100%);
  background-repeat:no-repeat;
  background-size:100% 2px, auto;
  background-position:0 0, 0 0;
  background-color:#fff;
  border:1px solid rgba(var(--pc-rgb),.22);
  box-shadow:0 1px 2px rgba(16,24,40,.04), 0 6px 20px rgba(16,24,40,.05);
  transition:border-color .2s ease, box-shadow .24s ease;
}
/* Corner bloom. Its CENTRE sits outside the box so only the tail bleeds in —
   that is what makes it read as light falling on the panel instead of a
   circle drawn on it. `isolation:isolate` above is what makes z-index:-1 mean
   "over the panel's own background, under every word on it"; without it the
   pseudo escapes to an ancestor's stacking context and paints behind the
   background entirely. */
.v2x.atd .atd-pc-col::after{
  content:""; position:absolute; inset:0; z-index:-1; pointer-events:none;
  border-radius:inherit;
  background:radial-gradient(230px 230px at calc(100% + 34px) -50px,
    rgba(var(--pc-rgb),.22) 0%, rgba(var(--pc-rgb),0) 70%) no-repeat;
  opacity:.9; transform-origin:100% 0;
  transition:opacity 360ms ease, transform 520ms cubic-bezier(.16,1,.3,1);
}
body.theme-dark .v2x.atd .atd-pc-col{
  background-image:
    linear-gradient(90deg,
      rgba(var(--pc-rgb),0)   0%,
      rgba(var(--pc-rgb),.50) 22%,
      rgba(var(--pc-rgb),.95) 50%,
      rgba(var(--pc-rgb),.50) 78%,
      rgba(var(--pc-rgb),0)  100%),
    linear-gradient(150deg,
      rgba(var(--pc-rgb),.14) 0%,
      rgba(var(--pc-rgb),.03) 46%,
      rgba(var(--pc-rgb),.09) 100%);
  background-repeat:no-repeat;
  background-size:100% 2px, auto;
  background-position:0 0, 0 0;
  /* One step lighter than the card's #171922 so the panel reads as a surface
     ON the card rather than a hole in it. */
  background-color:var(--dk-surface-3,#1D1D22);
  border-color:rgba(var(--pc-rgb),.30);
  box-shadow:0 1px 2px rgba(0,0,0,.40), 0 6px 20px rgba(0,0,0,.35);
}
/* .22 -> .15 in dark, and the reason is measured: at the hover-scaled bloom's
   reach the nearest text sits ~94px from the centre, where .18 composites the
   emerald panel to #18403B and takes --muted (#9CA2B3) to 4.49:1 — 0.01 under
   the bar. .15 lands it at 4.60:1. Light needs no such cut (7.29:1 at the same
   point) because the bloom there darkens the ground rather than lifting it. */
body.theme-dark .v2x.atd .atd-pc-col::after{
  background:radial-gradient(230px 230px at calc(100% + 34px) -50px,
    rgba(var(--pc-rgb),.15) 0%, rgba(var(--pc-rgb),0) 70%) no-repeat;
}

/* ══ 4 · Panel header ════════════════════════════════════════════════════ */
.v2x.atd .atd-pc-head{ display:flex; align-items:center; gap:11px; margin:0 0 14px; }
/* The tile is `.atd-side-ic`'s geometry to the pixel. The emerald RAMP is
   not: the sidebar's #10B981 top end carries white at 2.54:1, so a white
   thumbs-up on it washes out at exactly the size it is drawn. #0C9A6E starts
   the ramp at 3.58:1 and every point along it clears 3:1 (3.58 / 3.94 / 4.35
   / 4.86 / 5.39). Rose needed no change — #F43F5E is already 3.67:1. */
.v2x.atd .atd-pc-ic{
  flex:0 0 auto; width:34px; height:34px; border-radius:10px;
  display:flex; align-items:center; justify-content:center;
  background:linear-gradient(135deg,var(--pc-tile-1),var(--pc-tile-2));
  color:#fff;
  box-shadow:0 4px 12px rgba(var(--pc-rgb),.34);
  transition:transform 380ms cubic-bezier(.16,1,.3,1), box-shadow 300ms ease;
}
/* A real <h3>: the card's own title is the <h2>, so the two panels are its
   subheads and the main column keeps a complete outline. Bootstrap's reboot
   ships a margin-top and a font-size with the element — both neutralised
   here, so the swap from the old <div> is invisible. */
.v2x.atd .atd-pc-ttl{
  flex:1 1 auto; min-width:0; margin:0;
  font-family:var(--font); font-size:1.1rem; font-weight:700;
  letter-spacing:-.01em; line-height:1.25; color:var(--ink);
}
.v2x.atd .atd-pc-n{
  flex:0 0 auto; min-width:23px; height:23px; padding:0 7px;
  border-radius:var(--r-pill);
  display:inline-flex; align-items:center; justify-content:center;
  background:var(--pc-bg); color:var(--pc-ink); border:1px solid var(--pc-line);
  font-family:var(--font); font-size:.72rem; font-weight:700;
  font-variant-numeric:tabular-nums;
}

/* ══ 5 · Rows ════════════════════════════════════════════════════════════
   `flex:1` on the list is what lets both panels stretch to a common height
   without the shorter one's border stopping halfway down the row.
   ══════════════════════════════════════════════════════════════════════ */
.v2x.atd .atd-pc-list{
  list-style:none; margin:0; padding:0; flex:1 1 auto;
  display:flex; flex-direction:column; gap:2px;
}
.v2x.atd .atd-pc-item{
  position:relative; isolation:isolate;
  display:flex; align-items:flex-start; gap:11px;
  padding:9px 11px; border-radius:11px;
}
/* THE WASH — the "before" half of the hover. Sized by INSETS rather than a
   scaleX transform because `transform-origin` has no logical keyword: a
   scaleX wipe would run right-to-left in RTL, and this page is direction-
   agnostic everywhere else (grep inset-inline-start). Insets flip for free.
   The gradient is vertical for the same reason — a 90deg one would reverse. */
.v2x.atd .atd-pc-item::before{
  content:""; position:absolute; z-index:-1; pointer-events:none;
  top:0; bottom:0; inset-inline-start:0; inset-inline-end:100%;
  border-radius:inherit;
  background:linear-gradient(180deg, rgba(var(--pc-rgb),.14), rgba(var(--pc-rgb),.06));
  transition:inset-inline-end 420ms cubic-bezier(.16,1,.3,1);
}
/* THE SPINE — the "after" half. Reads as a text-selection marker, which is
   the register we want: emphasis, not a control. scaleY is direction-neutral,
   so this one can stay on the compositor. */
.v2x.atd .atd-pc-item::after{
  content:""; position:absolute; z-index:-1; pointer-events:none;
  inset-inline-start:0; top:7px; bottom:7px; width:3px;
  border-radius:var(--r-pill);
  background:linear-gradient(180deg,var(--pc-tile-1),var(--pc-tile-2));
  opacity:0; transform:scaleY(.25); transform-origin:50% 50%;
  transition:transform 380ms cubic-bezier(.16,1,.3,1), opacity 240ms ease;
}
.v2x.atd .atd-pc-mk{
  flex:0 0 auto; width:20px; height:20px; margin-top:1px;
  border-radius:7px;
  display:inline-flex; align-items:center; justify-content:center;
  background:var(--pc-bg); color:var(--pc-ink); border:1px solid var(--pc-line);
  transition:background 220ms ease, color 220ms ease, border-color 220ms ease,
             transform 380ms cubic-bezier(.16,1,.3,1), box-shadow 260ms ease;
}
.v2x.atd .atd-pc-tx{
  flex:1 1 auto; min-width:0;
  font-size:.95rem; line-height:1.6; color:var(--muted);
  transition:color 200ms ease;
}

/* ══ 6 · Hover ═══════════════════════════════════════════════════════════ */
@media (hover:hover) and (pointer:fine){
  /* Panel: light only — bloom swells from the corner it hangs off, the edge
     brightens, the tile lifts. No translateY (see the affordance note). */
  .v2x.atd .atd-pc-col:hover{
    border-color:rgba(var(--pc-rgb),.42);
    box-shadow:0 2px 6px rgba(16,24,40,.06), 0 18px 40px -14px rgba(var(--pc-rgb),.30);
  }
  .v2x.atd .atd-pc-col:hover::after{ opacity:1; transform:scale(1.16); }
  .v2x.atd .atd-pc-col:hover .atd-pc-ic{
    transform:scale(1.07) rotate(-3deg);
    box-shadow:0 6px 16px rgba(var(--pc-rgb),.45);
  }
  body.theme-dark .v2x.atd .atd-pc-col:hover{
    border-color:rgba(var(--pc-rgb),.52);
    box-shadow:0 2px 6px rgba(0,0,0,.50), 0 18px 40px -14px rgba(0,0,0,.55);
  }

  /* Row: wash wipes in, spine grows, marker fills, ink deepens to --ink. */
  .v2x.atd .atd-pc-item:hover::before{ inset-inline-end:0; }
  .v2x.atd .atd-pc-item:hover::after{ opacity:1; transform:scaleY(1); }
  .v2x.atd .atd-pc-item:hover .atd-pc-tx{ color:var(--ink); }
  .v2x.atd .atd-pc-item:hover .atd-pc-mk{
    background:var(--pc-solid); border-color:var(--pc-solid); color:#fff;
    transform:scale(1.08) rotate(-4deg);
    box-shadow:0 4px 12px rgba(var(--pc-rgb),.40);
  }
  /* Dark inverts the fill rather than dimming it. #08795A on a #1B1E28 panel
     is nearly the panel; the bright end is the only fill that reads — and a
     bright fill takes a DARK glyph, never white (#fff on #10B981 is 2.54:1,
     the exact ink-token-used-as-a-fill inversion the dark-mode contrast layer
     exists to prevent). #0B0D13 measures 7.66:1 emerald, 5.29:1 rose. */
  body.theme-dark .v2x.atd .atd-pc-col.is-pro .atd-pc-item:hover .atd-pc-mk{
    background:#10B981; border-color:#10B981; color:var(--dk-bg-deep,#0A0A0C);
  }
  body.theme-dark .v2x.atd .atd-pc-col.is-con .atd-pc-item:hover .atd-pc-mk{
    background:#F43F5E; border-color:#F43F5E; color:var(--dk-bg-deep,#0A0A0C);
  }

  /* Cross-link: hovering a panel plays its half of the strip back. The other
     half steps aside rather than disappearing, so the tally still reads.
     Without :has() nothing happens — a degradation, not a break. */
  .v2x.atd .atd-pc:has(.atd-pc-col.is-pro:hover) .atd-pc-bar .seg.is-pro,
  .v2x.atd .atd-pc:has(.atd-pc-col.is-con:hover) .atd-pc-bar .seg.is-con{
    transform:scaleY(1.5);
  }
  .v2x.atd .atd-pc:has(.atd-pc-col.is-pro:hover) .atd-pc-bar .seg.is-con,
  .v2x.atd .atd-pc:has(.atd-pc-col.is-con:hover) .atd-pc-bar .seg.is-pro{ opacity:.34; }
  .v2x.atd .atd-pc:has(.atd-pc-col.is-pro:hover) .atd-pc-tag.is-pro,
  .v2x.atd .atd-pc:has(.atd-pc-col.is-con:hover) .atd-pc-tag.is-con{
    transform:translateY(-1px);
    box-shadow:0 5px 14px rgba(var(--pc-rgb),.26);
  }
}

/* ══ 7 · The orbit ring ══════════════════════════════════════════════════
   §SIDEBAR-ORBIT's recipe, self-contained so this section stays removable in
   one piece: a conic the size of the box, masked to its padding band by two
   full-box mask layers composited xor/exclude. `--atd-spin` and the
   `atd-orbit` keyframes are registered once in §TABS and reused here — one
   registration, many hosts.

   The feature query is load-bearing, not defensive: without mask-composite
   the two layers UNION and the conic paints a SOLID BLOCK over the panel,
   covering every word in it. Where it is missing there is simply no ring and
   the border/bloom hover carries the state on its own.

   Panels orbit at 6.5s — between the section card's 7.5s and the sidebar
   row's 3.1s, which is where they sit in the page's hierarchy.
   ══════════════════════════════════════════════════════════════════════ */
@supports ((-webkit-mask-composite:xor) or (mask-composite:exclude)){
  .v2x.atd .atd-pc-col::before{
    content:""; position:absolute; pointer-events:none;
    inset:-1px; z-index:1; border-radius:17px;   /* panel 16px + the 1px offset */
    padding:1.5px;
    --atd-spin:0deg;
    /* Tails fade to rgba(same hue, 0), never the `transparent` KEYWORD — that
       interpolates through transparent black in sRGB and leaves a grey fringe
       on every tail. */
    background:conic-gradient(from var(--atd-spin),
      rgba(var(--pc-rgb), 0)               0deg,
      rgba(var(--pc-rgb), var(--pc-a1))   30deg,
      rgba(255,255,255, 1)                52deg,
      rgba(var(--pc-rgb), var(--pc-a2))   74deg,
      rgba(var(--pc-rgb), 0)             118deg,
      rgba(var(--pc-rgb), 0)             180deg,
      rgba(var(--pc-rgb), var(--pc-a1))  210deg,
      rgba(255,255,255, 1)               232deg,
      rgba(var(--pc-rgb), var(--pc-a2))  254deg,
      rgba(var(--pc-rgb), 0)             298deg,
      rgba(var(--pc-rgb), 0)             360deg);
    -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite:xor;
            mask-composite:exclude;
    opacity:0; transition:opacity .32s ease;
    animation:atd-orbit 6.5s linear infinite;
    animation-play-state:paused;   /* a paused animation does not tick, so an
                                      idle panel costs nothing and re-entering
                                      RESUMES rather than snapping to 0deg */
  }
  /* Dark is two alpha numbers, not a second fifteen-stop gradient: a 55% tail
     that reads over #fff disappears over #1B1E28. */
  .v2x.atd .atd-pc-col{ --pc-a1:.55; --pc-a2:.92; }
  body.theme-dark .v2x.atd .atd-pc-col{ --pc-a1:.68; --pc-a2:1; }

  @media (hover:hover) and (pointer:fine){
    .v2x.atd .atd-pc-col:hover::before{ opacity:1; animation-play-state:running; }
    /* The section card's own blue ring steps back the moment a panel claims
       the pointer — two rings chasing each other inside one card is noise.
       (0,7,1) against the reveal rule's (0,5,1), and later besides. */
    .v2x.atd .col-lg-8 > .v2-card.atd-pc:has(.atd-pc-col:hover)::before{ opacity:.3; }
  }
  @media (prefers-reduced-motion:reduce){
    .v2x.atd .atd-pc-col::before{ --atd-spin:135deg; animation:none !important; }
  }
}

/* ══ 8 · Responsive ══════════════════════════════════════════════════════
   The panels live in `.col-lg-8`, so the tightest two-up case is NOT a phone
   — it is the 992-1199px band, where the main column is ~600px and each
   panel gets ~250px of text. At the 58-character average of the live copy
   that is two lines a row, which holds; the padding steps down to buy it a
   little more. Below 768px the grid stacks outright.
   ══════════════════════════════════════════════════════════════════════ */
@media (min-width:992px) and (max-width:1199.98px){
  .v2x.atd .atd-pc-grid{ gap:14px; }
  .v2x.atd .atd-pc-col{ padding:16px 14px 14px; }
  .v2x.atd .atd-pc-item{ padding:9px 9px; gap:9px; }
  .v2x.atd .atd-pc-head{ gap:9px; }
}
@media (max-width:767.98px){
  .v2x.atd .atd-pc-grid{ grid-template-columns:minmax(0,1fr); gap:14px; }
}
@media (max-width:575.98px){
  /* The chips flank the bar down to 576px; below it they take a row of their
     own and the bar spans the full width beneath them. A wrapping flex row
     would have put the second chip on its own line and left the first one
     stranded beside the bar — the grid states the arrangement instead. */
  .v2x.atd .atd-pc-bal{ grid-template-columns:1fr 1fr; gap:10px 8px; margin-bottom:18px; }
  .v2x.atd .atd-pc-tag.is-pro{ grid-area:1 / 1; justify-self:start; }
  .v2x.atd .atd-pc-tag.is-con{ grid-area:1 / 2; justify-self:end; }
  .v2x.atd .atd-pc-bar{ grid-area:2 / 1 / 3 / 3; gap:3px; height:9px; }

  .v2x.atd .atd-pc-col{ padding:15px 13px 13px; border-radius:14px; }
  .v2x.atd .atd-pc-ic{ width:30px; height:30px; border-radius:9px; }
  .v2x.atd .atd-pc-ttl{ font-size:1.02rem; }
  .v2x.atd .atd-pc-item{ padding:8px 9px; gap:9px; border-radius:10px; }
  .v2x.atd .atd-pc-tx{ font-size:.92rem; line-height:1.58; }
  .v2x.atd .atd-pc-mk{ width:19px; height:19px; border-radius:6px; }
  .v2x.atd .atd-pc-tag{ padding:5px 11px; font-size:.79rem; }
}
/* The ring hangs 1px outside the panel, so its radius follows the panel's. */
@supports ((-webkit-mask-composite:xor) or (mask-composite:exclude)){
  @media (max-width:575.98px){
    .v2x.atd .atd-pc-col::before{ border-radius:15px; }
  }
}
@media (max-width:359.98px){
  /* At 320px a 15-tick strip leaves ~17px a segment, which still counts.
     The chips drop their glyphs before they drop any digits. */
  .v2x.atd .atd-pc-tag svg{ display:none; }
}

/* ══ 9 · Reduced motion ══════════════════════════════════════════════════
   Keep every hover STATE, drop the travel. The spine still appears — it just
   arrives at full height instead of growing into it — because a highlight
   that never shows up is a lost state, while one that slides is only a lost
   flourish.
   ══════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-pc-col,
  .v2x.atd .atd-pc-col::after,
  .v2x.atd .atd-pc-ic,
  .v2x.atd .atd-pc-item::before,
  .v2x.atd .atd-pc-item::after,
  .v2x.atd .atd-pc-mk,
  .v2x.atd .atd-pc-tx,
  .v2x.atd .atd-pc-tag,
  .v2x.atd .atd-pc-bar .seg{ transition:none !important; }
  .v2x.atd .atd-pc-col:hover::after{ transform:none; }
  .v2x.atd .atd-pc-col:hover .atd-pc-ic{ transform:none; }
  .v2x.atd .atd-pc-item:hover::after{ transform:scaleY(1); }
  .v2x.atd .atd-pc-item:hover .atd-pc-mk{ transform:none; }
  .v2x.atd .atd-pc:has(.atd-pc-col.is-pro:hover) .atd-pc-bar .seg.is-pro,
  .v2x.atd .atd-pc:has(.atd-pc-col.is-con:hover) .atd-pc-bar .seg.is-con{ transform:none; }
  .v2x.atd .atd-pc:has(.atd-pc-col.is-pro:hover) .atd-pc-tag.is-pro,
  .v2x.atd .atd-pc:has(.atd-pc-col.is-con:hover) .atd-pc-tag.is-con{ transform:none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   §TONE6) One six-tone ramp, shared by §UC and §INTEG.

   The values are the §SIDEBAR ramp's own (blue · violet · emerald · amber ·
   rose · cyan), which is the homepage's, so nothing here is a new colour.
   Three variables are NOT from that ramp and each is measured:

   · `--t-1p` — the light end of an ICON PLATE. A plate carries a white glyph,
     and the ramp's own light end does not always survive that: white on
     #10B981 is 2.54:1 and on #F59E0B far worse. Each plate ramp starts at the
     first step toward `--t-2` that clears 3:1 (blue and violet and rose are
     already there and are unchanged; emerald #0EA575, amber #D07E0A, cyan
     #1A9EBD). Same fix, same reason, as the §PROSCONS tile.
   · `--t-dot1` / `--t-dot2` — the §CHLOG node, which carries no glyph and so
     is measured against the CARD instead: 3.15:1 on the washed light card
     (#F4F8FE — the tinted ground, not #fff; tinting the ground toward the dot
     is what narrows the gap).

   ⚠️ DARK MODE RUNS THE DOT RAMP THE OTHER WAY. `--t-2` is the dark end of
   every tone and lands 2.03-3.11:1 on a #1A2336 card, so a light-to-dark dot
   would half vanish. The dark ramp walks DOWN from `--t-1` only as far as
   3.15 allows. Plates are opaque and need no dark twin at all.
   ══════════════════════════════════════════════════════════════════════════ */
.v2x.atd .atd-t0{ --t-rgb:76,141,242;  --t-1:#4C8DF2; --t-2:#2060C0; --t-1p:#1C6EEE;
                  --t-bg:#EAF2FD; --t-ink:#1B5BB5; --t-line:#CFE0FA; --t-dot1:#4A8BF0; --t-dot2:#2060C0; }
.v2x.atd .atd-t1{ --t-rgb:139,92,246;  --t-1:#8B5CF6; --t-2:#5B33C4; --t-1p:#8452F5;
                  --t-bg:#F0EBFE; --t-ink:#5B33C4; --t-line:#DED2FB; --t-dot1:#8B5CF6; --t-dot2:#5B33C4; }
.v2x.atd .atd-t2{ --t-rgb:16,185,129;  --t-1:#10B981; --t-2:#08795A; --t-1p:#0B855E;
                  --t-bg:#E6F8F1; --t-ink:#08795A; --t-line:#C6EEDF; --t-dot1:#0D9F71; --t-dot2:#08795A; }
.v2x.atd .atd-t3{ --t-rgb:245,158,11;  --t-1:#F59E0B; --t-2:#A85B08; --t-1p:#A76508;
                  --t-bg:#FEF4E4; --t-ink:#A85B08; --t-line:#FBE3C0; --t-dot1:#CA7809; --t-dot2:#A85B08; }
.v2x.atd .atd-t4{ --t-rgb:244,63,94;   --t-1:#F43F5E; --t-2:#B31D3C; --t-1p:#E80D33;
                  --t-bg:#FEECEF; --t-ink:#B31D3C; --t-line:#FBD2DA; --t-dot1:#F43F5E; --t-dot2:#B31D3C; }
.v2x.atd .atd-t5{ --t-rgb:34,184,217;  --t-1:#22B8D9; --t-2:#0A6E88; --t-1p:#157F98;
                  --t-bg:#E4F6FB; --t-ink:#0A6E88; --t-line:#C2E9F4; --t-dot1:#1898B6; --t-dot2:#0A6E88; }
body.theme-dark .v2x.atd .atd-t0{ --t-bg:rgba(54,128,237,.18); --t-ink:#8CBEFA; --t-line:rgba(96,164,245,.28); --t-dot1:#4C8DF2; --t-dot2:#2D6ECF; }
body.theme-dark .v2x.atd .atd-t1{ --t-bg:rgba(124,77,240,.20); --t-ink:#BFA6FB; --t-line:rgba(160,120,250,.32); --t-dot1:#8B5CF6; --t-dot2:#7E51E8; }
body.theme-dark .v2x.atd .atd-t2{ --t-bg:rgba(16,185,129,.18); --t-ink:#6EE7BE; --t-line:rgba(52,211,153,.30); --t-dot1:#10B981; --t-dot2:#097F5E; }
body.theme-dark .v2x.atd .atd-t3{ --t-bg:rgba(245,158,11,.20); --t-ink:#FBC97A; --t-line:rgba(251,191,36,.32); --t-dot1:#F59E0B; --t-dot2:#A95C08; }
body.theme-dark .v2x.atd .atd-t4{ --t-bg:rgba(244,63,94,.18);  --t-ink:#FB9BB0; --t-line:rgba(251,113,133,.30); --t-dot1:#F43F5E; --t-dot2:#D22D4C; }
body.theme-dark .v2x.atd .atd-t5{ --t-bg:rgba(6,182,212,.18);  --t-ink:#7CD9EE; --t-line:rgba(34,211,238,.30); --t-dot1:#22B8D9; --t-dot2:#0E7A95; }

/* ══════════════════════════════════════════════════════════════════════════
   §CHLOG) What's New — a dated timeline.

   WHAT WAS WRONG. Title, type pill and date sat on one line at nearly one
   weight, so the row had no anchor and the DATE — the one thing a changelog is
   scanned by — was the faintest thing on it. The date now owns a gutter beside
   the rail, stacked month / day / year, and the title is the only strong thing
   in the content column.

   THE RAIL IS DRAWN ON THE WRAPPER, not per entry. Each-entry connectors have
   to know whether they are last, which stops being knowable the moment an
   overflow list can expand beneath them; a wrapper-level rail spans exactly
   the visible lists for free. `--cl-x` is the node column's centre and is the
   single number that keeps the rail and the grid in step across breakpoints —
   change one, change both.

   The node's hue encodes the update TYPE (feature emerald · fix blue · pricing
   amber · news violet · other slate), so the rail can be scanned by colour and
   the dot agrees with the pill beside it rather than repeating brand blue five
   times. Values come from §TONE6.
   ══════════════════════════════════════════════════════════════════════════ */
.v2x.atd .atd-cl{ --cl-x:89px; --cl-card:#fff; }          /* 78px date + half of the 22px node column */
body.theme-dark .v2x.atd .atd-cl{ --cl-card:var(--dk-surface-2,#17171B); }

.v2x.atd .atd-cl-wrap{ position:relative; margin-top:2px; }
.v2x.atd .atd-cl-wrap::before{
  content:""; position:absolute; z-index:0; pointer-events:none;
  inset-inline-start:calc(var(--cl-x) - 1px);
  top:16px; bottom:16px; width:2px; border-radius:2px;
  /* Fades out downward: the timeline is newest-first, so the line should read
     as running back into the past rather than stopping dead. */
  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 .atd-cl-wrap::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 .atd-cl-line{ list-style:none; margin:0; padding:0; }
.v2x.atd .atd-cl-item{
  display:grid; align-items:start;
  grid-template-columns:78px 22px minmax(0,1fr);
  grid-template-areas:"date node body";
  padding-bottom:8px;
}
.v2x.atd .atd-cl-line:last-child > .atd-cl-item:last-child{ padding-bottom:0; }

/* ── Date gutter ──────────────────────────────────────────────────────────
   `flex-end` on a column flex box resolves against the WRITING DIRECTION, so
   this stays right-aligned in LTR and left-aligned in RTL with no twin. */
.v2x.atd .atd-cl-date{
  grid-area:date; display:flex; flex-direction:column; align-items:flex-end;
  padding-top:3px; padding-inline-end:15px; text-align:end; line-height:1;
}
.v2x.atd .atd-cl-date .mo{
  font-size:.68rem; font-weight:700; letter-spacing:.10em; text-transform:uppercase;
  color:var(--muted2); transition:color 200ms ease;
}
.v2x.atd .atd-cl-date .dy{
  font-size:1.4rem; font-weight:800; letter-spacing:-.03em; color:var(--ink);
  margin:4px 0 4px; font-variant-numeric:tabular-nums; transition:color 200ms ease;
}
.v2x.atd .atd-cl-date .yr{ font-size:.7rem; font-weight:600; color:var(--muted2); font-variant-numeric:tabular-nums; }
.v2x.atd .atd-cl-date.is-none{ display:block; }

/* ── Node ─────────────────────────────────────────────────────────────────
   z-index:1 so the dot sits over the rail it interrupts; the white/panel
   halo is what actually cuts the rail, so it has to follow the card colour. */
.v2x.atd .atd-cl-node{ grid-area:node; position:relative; z-index:1; display:flex; justify-content:center; }
.v2x.atd .atd-cl-node::before{
  content:""; margin-top:7px; width:12px; height:12px; border-radius:50%;
  background:linear-gradient(135deg, var(--t-dot1,#4C8DF2), var(--t-dot2,#2060C0));
  box-shadow:0 0 0 3px var(--cl-card), 0 0 0 4px rgba(var(--t-rgb,54,128,237),.28);
  transition:transform 320ms cubic-bezier(.16,1,.3,1), box-shadow 300ms ease;
}

/* ── Content ──────────────────────────────────────────────────────────────
   The wash is the §PROSCONS row's, wiped in by INSETS rather than a scaleX
   transform — `transform-origin` has no logical keyword and a scaleX wipe runs
   backwards in RTL. Its gradient is vertical for the same reason. */
.v2x.atd .atd-cl-body{
  grid-area:body; position:relative; isolation:isolate;
  padding:8px 14px 14px; border-radius:12px;
}
.v2x.atd .atd-cl-body::before{
  content:""; position:absolute; z-index:-1; pointer-events:none;
  top:0; bottom:0; inset-inline-start:0; inset-inline-end:100%;
  border-radius:inherit;
  background:linear-gradient(180deg, rgba(var(--t-rgb,54,128,237),.12), rgba(var(--t-rgb,54,128,237),.045));
  transition:inset-inline-end 420ms cubic-bezier(.16,1,.3,1);
}
.v2x.atd .atd-cl-head{ display:flex; align-items:center; gap:9px; flex-wrap:wrap; margin-bottom:5px; }
.v2x.atd .atd-cl-ttl{
  margin:0; font-family:var(--font); font-size:1.03rem; font-weight:700;
  letter-spacing:-.012em; line-height:1.32; color:var(--ink);
}
.v2x.atd .atd-cl-tx{
  margin:0; font-size:.93rem; line-height:1.62; color:var(--muted);
  transition:color 200ms ease;
}
.v2x.atd .atd-cl-head .atd-utype{ font-size:.63rem; padding:3px 9px; letter-spacing:.06em; flex:0 0 auto; }

/* ── Type tones. The pill palette (.atd-utype) already carries these hues and
   is left exactly as it is — 4.54:1 to 7.17:1, all measured, all with dark
   twins. This maps the same five types onto the §TONE6 variables the node and
   wash read, so the two can never drift apart. ── */
.v2x.atd .atd-cl-item[data-ut="feature"]     { --t-rgb:16,185,129;  --t-dot1:#0D9F71; --t-dot2:#08795A; --t-ink:#08795A; }
.v2x.atd .atd-cl-item[data-ut="fix"]         { --t-rgb:76,141,242;  --t-dot1:#4A8BF0; --t-dot2:#2060C0; --t-ink:#2060C0; }
/* --t-ink is #9E5507 here, not the ramp's #A85B08: this variable's only
   consumer is the month label on hover, .68rem uppercase — small text at
   4.5:1 — and #A85B08 on the amber hover wash measures 4.33. #9E5507 is
   4.80 and still plainly amber. The .atd-utype.pricing pill keeps its own
   #b45309, which sits on an opaque plate and was never affected. */
.v2x.atd .atd-cl-item[data-ut="pricing"]     { --t-rgb:245,158,11;  --t-dot1:#CA7809; --t-dot2:#A85B08; --t-ink:#9E5507; }
.v2x.atd .atd-cl-item[data-ut="announcement"]{ --t-rgb:139,92,246;  --t-dot1:#8B5CF6; --t-dot2:#5B33C4; --t-ink:#5B33C4; }
.v2x.atd .atd-cl-item[data-ut="other"]       { --t-rgb:100,110,130; --t-dot1:#6B7488; --t-dot2:#4B5364; --t-ink:#454C5C; }
body.theme-dark .v2x.atd .atd-cl-item[data-ut="feature"]     { --t-dot1:#10B981; --t-dot2:#097F5E; --t-ink:#6EE7BE; }
body.theme-dark .v2x.atd .atd-cl-item[data-ut="fix"]         { --t-dot1:#4C8DF2; --t-dot2:#2D6ECF; --t-ink:#8CBEFA; }
body.theme-dark .v2x.atd .atd-cl-item[data-ut="pricing"]     { --t-dot1:#F59E0B; --t-dot2:#A95C08; --t-ink:#FBC97A; }
body.theme-dark .v2x.atd .atd-cl-item[data-ut="announcement"]{ --t-dot1:#8B5CF6; --t-dot2:#7E51E8; --t-ink:#BFA6FB; }
body.theme-dark .v2x.atd .atd-cl-item[data-ut="other"]       { --t-dot1:#9BA3B5; --t-dot2:#6E7688; --t-ink:#B9C0CE; }

/* ── Hover. Entries are not links, so this is a reading highlight, not an
   affordance: no lift, no cursor change. Same rule, same reason, as the
   §PROSCONS rows. The month goes to the tone's INK, never to `--t-1` — the
   label is .68rem uppercase, i.e. small text at 4.5:1, and #10B981 on the card
   is 2.5:1. ── */
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-cl-item:hover .atd-cl-body::before{ inset-inline-end:0; }
  .v2x.atd .atd-cl-item:hover .atd-cl-tx{ color:var(--ink); }
  .v2x.atd .atd-cl-item:hover .atd-cl-date .dy{ color:var(--ink); }
  .v2x.atd .atd-cl-item:hover .atd-cl-date .mo{ color:var(--t-ink); }
  .v2x.atd .atd-cl-item:hover .atd-cl-node::before{
    transform:scale(1.28);
    box-shadow:0 0 0 3px var(--cl-card), 0 0 0 7px rgba(var(--t-rgb,54,128,237),.30);
  }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-cl-body::before,
  .v2x.atd .atd-cl-node::before,
  .v2x.atd .atd-cl-tx,
  .v2x.atd .atd-cl-date .mo,
  .v2x.atd .atd-cl-date .dy{ transition:none !important; }
  .v2x.atd .atd-cl-item:hover .atd-cl-node::before{ transform:none; }
}
@media (max-width:767.98px){
  /* The gutter goes: at this width 78px of date is 20% of the text column.
     The date folds into the content column as an inline kicker instead — same
     element, re-placed, because grid areas can move a child that CSS could
     never have moved between two containers. */
  .v2x.atd .atd-cl{ --cl-x:11px; }
  .v2x.atd .atd-cl-item{
    grid-template-columns:22px minmax(0,1fr);
    grid-template-areas:"node date" "node body";
  }
  .v2x.atd .atd-cl-date{
    flex-direction:row; align-items:baseline; gap:6px;
    padding-top:0; padding-inline:13px 0; padding-bottom:2px; text-align:start;
  }
  .v2x.atd .atd-cl-date .dy{ font-size:.72rem; font-weight:700; letter-spacing:0; color:var(--muted2); margin:0; }
  .v2x.atd .atd-cl-date .mo,
  .v2x.atd .atd-cl-date .yr{ font-size:.72rem; letter-spacing:.04em; }
  .v2x.atd .atd-cl-date.is-none{ display:none; }
  .v2x.atd .atd-cl-body{ padding:4px 13px 13px; }
  .v2x.atd .atd-cl-ttl{ font-size:.99rem; }
  .v2x.atd .atd-cl-tx{ font-size:.9rem; }
  .v2x.atd .atd-cl-node::before{ margin-top:3px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   §UC) Real-World Use Cases — the capability map.

   Six-to-eight tiles from the admin "Best for" field, each a §TONE6 surface on
   the §PROSCONS panel recipe at chip scale: diagonal wash, tinted edge, corner
   bloom, gradient plate, orbit ring on hover.

   THE TILES ARE NOT LINKS, so — like the §PROSCONS rows — they answer with
   light and never with a lift. The `.v2-feature` card they used to borrow DOES
   lift, which is correct for `template-show` and `compare-show` where it is a
   link; that class is untouched and still theirs.

   `text-transform:capitalize` is deliberately NOT carried over. The labels are
   authored properly cased ("Data analysis"), and capitalising them produced
   "Cost-sensitive Api Workloads".
   ══════════════════════════════════════════════════════════════════════════ */
.v2x.atd .atd-uc-grid{
  list-style:none; margin:0; padding:0;
  display:grid; gap:12px; align-items:stretch;
  grid-template-columns:repeat(auto-fit, minmax(min(100%,230px),1fr));
}
.v2x.atd .atd-uc-card{
  position:relative; isolation:isolate;
  display:flex; align-items:center; gap:13px;
  padding:15px 16px; border-radius:14px;
  background-image:linear-gradient(150deg,
    rgba(var(--t-rgb),.085) 0%, rgba(var(--t-rgb),.015) 46%, rgba(var(--t-rgb),.06) 100%);
  background-repeat:no-repeat; background-color:#fff;
  border:1px solid rgba(var(--t-rgb),.22);
  box-shadow:0 1px 2px rgba(16,24,40,.04), 0 4px 14px rgba(16,24,40,.045);
  transition:border-color .2s ease, box-shadow .24s ease;
}
.v2x.atd .atd-uc-card::after{
  content:""; position:absolute; inset:0; z-index:-1; pointer-events:none;
  border-radius:inherit;
  background:radial-gradient(150px 150px at calc(100% + 22px) -34px,
    rgba(var(--t-rgb),.24) 0%, rgba(var(--t-rgb),0) 70%) no-repeat;
  opacity:.9; transform-origin:100% 0;
  transition:opacity 360ms ease, transform 520ms cubic-bezier(.16,1,.3,1);
}
body.theme-dark .v2x.atd .atd-uc-card{
  background-image:linear-gradient(150deg,
    rgba(var(--t-rgb),.14) 0%, rgba(var(--t-rgb),.03) 46%, rgba(var(--t-rgb),.09) 100%);
  background-color:var(--dk-surface-3,#1D1D22);
  border-color:rgba(var(--t-rgb),.30);
  box-shadow:0 1px 2px rgba(0,0,0,.40), 0 4px 14px rgba(0,0,0,.32);
}
body.theme-dark .v2x.atd .atd-uc-card::after{
  background:radial-gradient(150px 150px at calc(100% + 22px) -34px,
    rgba(var(--t-rgb),.15) 0%, rgba(var(--t-rgb),0) 70%) no-repeat;
}
.v2x.atd .atd-uc-ic{
  flex:0 0 auto; width:42px; height:42px; border-radius:12px;
  display:flex; align-items:center; justify-content:center;
  background:linear-gradient(135deg, var(--t-1p), var(--t-2)); color:#fff;
  box-shadow:0 4px 12px rgba(var(--t-rgb),.32);
  transition:transform 380ms cubic-bezier(.16,1,.3,1), box-shadow 300ms ease;
}
.v2x.atd .atd-uc-lb{
  flex:1 1 auto; min-width:0;
  font-family:var(--font); font-size:1rem; font-weight:700; line-height:1.35;
  color:var(--ink); overflow-wrap:anywhere;
}
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-uc-card:hover{
    border-color:rgba(var(--t-rgb),.44);
    box-shadow:0 2px 6px rgba(16,24,40,.06), 0 14px 32px -12px rgba(var(--t-rgb),.34);
  }
  .v2x.atd .atd-uc-card:hover::after{ opacity:1; transform:scale(1.18); }
  .v2x.atd .atd-uc-card:hover .atd-uc-ic{
    transform:scale(1.07) rotate(-4deg);
    box-shadow:0 6px 16px rgba(var(--t-rgb),.46);
  }
  body.theme-dark .v2x.atd .atd-uc-card:hover{
    border-color:rgba(var(--t-rgb),.54);
    box-shadow:0 2px 6px rgba(0,0,0,.50), 0 14px 32px -12px rgba(0,0,0,.55);
  }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-uc-card,.v2x.atd .atd-uc-card::after,.v2x.atd .atd-uc-ic{ transition:none !important; }
  .v2x.atd .atd-uc-card:hover::after{ transform:none; }
  .v2x.atd .atd-uc-card:hover .atd-uc-ic{ transform:none; }
}
@media (max-width:575.98px){
  .v2x.atd .atd-uc-grid{ gap:10px; }
  .v2x.atd .atd-uc-card{ padding:13px 13px; gap:11px; border-radius:12px; }
  .v2x.atd .atd-uc-ic{ width:38px; height:38px; border-radius:11px; }
  .v2x.atd .atd-uc-lb{ font-size:.95rem; }
}

/* ══════════════════════════════════════════════════════════════════════════
   §INTEG) Integrations — the connector grid.

   ⚠️ THE OLD CHIP HID TEXT AND THAT IS THE POINT OF THIS PASS. `.nm` carried
   `white-space:nowrap` + `text-overflow:ellipsis` inside a 150px track, so
   "Microsoft OneDrive" rendered "Microsoft One…" and "Alibaba Cloud Model
   Studio" lost over half of itself. Names wrap now and nothing is clipped —
   `overflow-wrap:anywhere` is the guard for a future name with no spaces in it.

   THE TRACK FLOOR IS 205px, and it is a measurement, not a round number. At
   the card's ~840px that yields three columns of ~273px, which leaves ~182px
   of text — enough for the longest name on file (26 characters ≈ 179px) on ONE
   line. Dropping to 190px buys a fourth column and puts every long name onto
   two lines; the wider track is the better trade.

   THE ARROW IS ALWAYS VISIBLE, never a hover reveal. A revealed arrow either
   overlaps the name it appears on top of — hiding text at exactly the moment
   the user is reading it — or reflows the row under the pointer. It also earns
   its place: every one of these opens a new tab, and that is worth signalling.
   ══════════════════════════════════════════════════════════════════════════ */
.v2x.atd .atd-integs{
  display:grid; gap:10px; align-items:stretch;
  grid-template-columns:repeat(auto-fit, minmax(min(100%,205px),1fr));
}
.v2x.atd .atd-integ{
  position:relative; isolation:isolate;
  display:flex; align-items:center; gap:11px;
  padding:11px 13px; border-radius:12px;
  background-image:linear-gradient(150deg,
    rgba(var(--t-rgb),.075) 0%, rgba(var(--t-rgb),.012) 46%, rgba(var(--t-rgb),.05) 100%);
  background-repeat:no-repeat; background-color:#fff;
  border:1px solid rgba(var(--t-rgb),.20);
  color:var(--ink); text-decoration:none;
  box-shadow:0 1px 2px rgba(16,24,40,.04);
  transition:transform .22s cubic-bezier(.22,.61,.36,1), border-color .2s ease, box-shadow .24s ease;
}
body.theme-dark .v2x.atd .atd-integ{
  background-image:linear-gradient(150deg,
    rgba(var(--t-rgb),.13) 0%, rgba(var(--t-rgb),.025) 46%, rgba(var(--t-rgb),.08) 100%);
  background-color:var(--dk-surface-3,#1D1D22);
  border-color:rgba(var(--t-rgb),.28);
  box-shadow:0 1px 2px rgba(0,0,0,.40);
}
.v2x.atd .atd-integ-ic{
  flex:0 0 auto; width:32px; height:32px; border-radius:9px; overflow:hidden;
  display:flex; align-items:center; justify-content:center;
  background:linear-gradient(135deg, var(--t-1p), var(--t-2)); color:#fff;
  font-family:var(--font); font-weight:800; font-size:.86rem; line-height:1;
  box-shadow:0 3px 10px rgba(var(--t-rgb),.28);
  transition:transform 380ms cubic-bezier(.16,1,.3,1), box-shadow 300ms ease;
}
.v2x.atd .atd-integ-ic img{ width:100%; height:100%; object-fit:contain; border-radius:inherit; display:block; }
.v2x.atd .atd-integ-nm{
  flex:1 1 auto; min-width:0;
  font-family:var(--font); font-size:.88rem; font-weight:600; line-height:1.35;
  color:var(--ink);
  white-space:normal; overflow:visible; text-overflow:clip; overflow-wrap:anywhere;
}
.v2x.atd .atd-integ-go{
  flex:0 0 auto; color:var(--muted2); opacity:.85;
  transition:color 200ms ease, transform 320ms cubic-bezier(.16,1,.3,1), opacity 200ms ease;
}

/* These ARE links, so they get a real affordance — a lift, the tone edge, the
   plate and the arrow all answering together. The URL-less variant gets none
   of it: `.atd-integ:not(.is-link)` never moves, which is the rule §SIDEBAR-FIX
   had to restore to `.atd-plat` after a static span spent 27 pages pretending
   to be clickable. */
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-integ.is-link:hover{
    transform:translateY(-2px);
    border-color:rgba(var(--t-rgb),.48);
    box-shadow:0 2px 6px rgba(16,24,40,.06), 0 14px 30px -12px rgba(var(--t-rgb),.36);
    color:var(--ink); text-decoration:none;
  }
  .v2x.atd .atd-integ.is-link:hover .atd-integ-ic{
    transform:scale(1.07) rotate(-4deg);
    box-shadow:0 6px 16px rgba(var(--t-rgb),.44);
  }
  .v2x.atd .atd-integ.is-link:hover .atd-integ-go{
    color:var(--t-ink); opacity:1; transform:translateX(3px);
  }
  body.theme-dark .v2x.atd .atd-integ.is-link:hover{
    border-color:rgba(var(--t-rgb),.58);
    box-shadow:0 2px 6px rgba(0,0,0,.50), 0 14px 30px -12px rgba(0,0,0,.58);
  }
}
.v2x.atd .atd-integ.is-link:focus-visible{
  outline:none; box-shadow:0 0 0 3px rgba(var(--t-rgb),.42); border-color:rgba(var(--t-rgb),.55);
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-integ,.v2x.atd .atd-integ-ic,.v2x.atd .atd-integ-go{ transition:none !important; }
  .v2x.atd .atd-integ.is-link:hover{ transform:none; }
  .v2x.atd .atd-integ.is-link:hover .atd-integ-ic{ transform:none; }
  .v2x.atd .atd-integ.is-link:hover .atd-integ-go{ transform:none; }
}
@media (max-width:575.98px){
  .v2x.atd .atd-integs{ grid-template-columns:repeat(auto-fit, minmax(min(100%,165px),1fr)); gap:8px; }
  .v2x.atd .atd-integ{ padding:10px 11px; gap:9px; border-radius:11px; }
  .v2x.atd .atd-integ-ic{ width:29px; height:29px; border-radius:8px; font-size:.8rem; }
  .v2x.atd .atd-integ-nm{ font-size:.85rem; }
}

/* ══════════════════════════════════════════════════════════════════════════
   §UC-INTEG-ORBIT) The rail's rotating light on both grids.

   §SIDEBAR-ORBIT's recipe, hue-driven from §TONE6 so every tile orbits in the
   colour it already wears. Feature-gated for the same non-cosmetic reason:
   without mask-composite the two mask layers UNION and the conic paints a
   SOLID BLOCK over the tile, covering the label. Where it is missing there is
   simply no ring.

   Use-case tiles orbit at 4.2s and connector chips at 3.4s — slower than a tag
   chip, faster than a card, which is where they sit in the page's hierarchy.
   ══════════════════════════════════════════════════════════════════════════ */
@supports ((-webkit-mask-composite:xor) or (mask-composite:exclude)){
  .v2x.atd .atd-uc-card::before,
  .v2x.atd .atd-integ.is-link::before{
    content:""; position:absolute; pointer-events:none;
    inset:-1px; z-index:1; border-radius:inherit; padding:1.4px;
    --atd-spin:0deg;
    background:conic-gradient(from var(--atd-spin),
      rgba(var(--t-rgb), 0)              0deg,
      rgba(var(--t-rgb), var(--t-a1))   30deg,
      rgba(255,255,255, 1)              52deg,
      rgba(var(--t-rgb), var(--t-a2))   74deg,
      rgba(var(--t-rgb), 0)            118deg,
      rgba(var(--t-rgb), 0)            180deg,
      rgba(var(--t-rgb), var(--t-a1))  210deg,
      rgba(255,255,255, 1)             232deg,
      rgba(var(--t-rgb), var(--t-a2))  254deg,
      rgba(var(--t-rgb), 0)            298deg,
      rgba(var(--t-rgb), 0)            360deg);
    -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite:xor;
            mask-composite:exclude;
    opacity:0; transition:opacity .32s ease;
    animation-name:atd-orbit; animation-timing-function:linear; animation-iteration-count:infinite;
    animation-play-state:paused;
  }
  /* `border-radius:inherit` is wrong at inset:-1px — the ring sits one pixel
     OUTSIDE the box, so it needs the host radius plus that pixel. */
  .v2x.atd .atd-uc-card::before{ border-radius:15px; animation-duration:4.2s; }
  .v2x.atd .atd-integ.is-link::before{ border-radius:13px; animation-duration:3.4s; }
  .v2x.atd .atd-uc-card,
  .v2x.atd .atd-integ{ --t-a1:.55; --t-a2:.92; }
  body.theme-dark .v2x.atd .atd-uc-card,
  body.theme-dark .v2x.atd .atd-integ{ --t-a1:.68; --t-a2:1; }

  .v2x.atd .atd-integ.is-link:focus-visible::before{ opacity:1; animation-play-state:running; }
  @media (hover:hover) and (pointer:fine){
    .v2x.atd .atd-uc-card:hover::before,
    .v2x.atd .atd-integ.is-link:hover::before{ opacity:1; animation-play-state:running; }
    /* The section card's blue ring steps back while a tile inside it is lit. */
    .v2x.atd .col-lg-8 > .v2-card.atd-uc:has(.atd-uc-card:hover)::before,
    .v2x.atd .col-lg-8 > .v2-card.atd-integ-sec:has(.atd-integ.is-link:hover)::before{ opacity:.3; }
  }
  @media (hover:none){
    .v2x.atd .atd-integ.is-link:active::before{ opacity:1; animation-play-state:running; }
  }
  @media (prefers-reduced-motion:reduce){
    .v2x.atd .atd-uc-card::before,
    .v2x.atd .atd-integ.is-link::before{ --atd-spin:135deg; animation:none !important; }
  }
  @media (max-width:575.98px){
    .v2x.atd .atd-uc-card::before{ border-radius:13px; }
    .v2x.atd .atd-integ.is-link::before{ border-radius:12px; }
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   §FEAT) Key Features — grouped, iconed, toned.

   The old section was `.atd-feats` / `.atd-feat`: a flat two-column grid of up
   to 34 rows, every one of them wearing the SAME green check, with the
   `feature_group` and `icon_name` columns on `directory_features` unused. It
   is now six named groups from the shared §TONE6 ramp, each feature carrying
   its own glyph in its group's hue.

   NO PANEL PER GROUP. Six stacked bordered boxes inside an already-bordered
   section card is three levels of container for one list. The group is marked
   by a header — tone tile, name, count, a rule that fades out — and the rows
   below it stay open. That reads as a spec sheet, which is what it is.

   The rows are NOT links, so their hover is a reading highlight and never a
   lift: same rule as §PROSCONS and §CHLOG.
   ══════════════════════════════════════════════════════════════════════════ */
.v2x.atd .atd-ft-groups{ display:flex; flex-direction:column; gap:26px; }
.v2x.atd .atd-ft-groups + .atd-ft-groups{ margin-top:26px; }

/* ── Group header ─────────────────────────────────────────────────────── */
.v2x.atd .atd-ft-ghd{ display:flex; align-items:center; gap:10px; margin:0 0 14px; }
.v2x.atd .atd-ft-gic{
  flex:0 0 auto; width:30px; height:30px; border-radius:9px;
  display:flex; align-items:center; justify-content:center;
  background:linear-gradient(135deg, var(--t-1p), var(--t-2)); color:#fff;
  box-shadow:0 3px 10px rgba(var(--t-rgb),.30);
  transition:transform 380ms cubic-bezier(.16,1,.3,1), box-shadow 300ms ease;
}
.v2x.atd .atd-ft-gt{
  flex:0 0 auto; margin:0;
  font-family:var(--font); font-size:1.02rem; font-weight:700;
  letter-spacing:-.01em; line-height:1.25; color:var(--ink);
}
/* Fades to nothing rather than stopping at the card edge, so the eye is not
   pulled to a hard line the width of the section. */
.v2x.atd .atd-ft-grule{
  flex:1 1 auto; min-width:12px; height:1px;
  background:linear-gradient(90deg, rgba(var(--t-rgb),.34), rgba(var(--t-rgb),0));
}

/* ── Rows ─────────────────────────────────────────────────────────────── */
.v2x.atd .atd-ft-list{
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:4px 18px;
  align-items:start;
}
/* ⚠️ `.atd-ft` is the ROW. The section card is `.atd-ft-sec` — they were
   briefly the same class, and the card then inherited this rule's
   `display:flex` and laid its heading, its groups and the toggle out in a
   single row. Never name a container the same as the thing it contains. */
.v2x.atd .atd-ft{
  position:relative; isolation:isolate;
  display:flex; align-items:flex-start; gap:12px;
  padding:11px 12px; border-radius:12px;
}
/* The wipe-in wash, sized by INSETS rather than a scaleX transform:
   `transform-origin` has no logical keyword and a scaleX wipe runs backwards
   in RTL. Its gradient is vertical for the same reason. */
.v2x.atd .atd-ft::before{
  content:""; position:absolute; z-index:-1; pointer-events:none;
  top:0; bottom:0; inset-inline-start:0; inset-inline-end:100%;
  border-radius:inherit;
  background:linear-gradient(180deg, rgba(var(--t-rgb),.13), rgba(var(--t-rgb),.05));
  transition:inset-inline-end 420ms cubic-bezier(.16,1,.3,1);
}
.v2x.atd .atd-ft-ic{
  flex:0 0 auto; width:36px; height:36px; margin-top:1px; border-radius:11px;
  display:flex; align-items:center; justify-content:center;
  background:var(--t-bg); color:var(--t-ink); border:1px solid var(--t-line);
  transition:background 220ms ease, color 220ms ease, border-color 220ms ease,
             transform 380ms cubic-bezier(.16,1,.3,1), box-shadow 260ms ease;
}
.v2x.atd .atd-ft-tx{ flex:1 1 auto; min-width:0; }
.v2x.atd .atd-ft-nm{
  margin:0; font-family:var(--font); font-size:1rem; font-weight:700;
  letter-spacing:-.01em; line-height:1.3; color:var(--ink); overflow-wrap:anywhere;
}
/* The value chip. It used to be `.v2-chip.gray` in the MONO face — a
   typewriter pill on a prose row, and grey in a section that has six hues to
   choose from. It is the row's tone now, and it is a separate block rather
   than an inline run so a long value wraps as a chip instead of dragging the
   feature name onto a second line with it. */
.v2x.atd .atd-ft-v{
  display:inline-flex; align-items:center; margin:6px 0 0;
  padding:3px 10px; border-radius:var(--r-pill);
  background:var(--t-bg); color:var(--t-ink); border:1px solid var(--t-line);
  font-family:var(--font); font-size:.76rem; font-weight:600; line-height:1.35;
  overflow-wrap:anywhere;
}
.v2x.atd .atd-ft-ds{
  margin:6px 0 0; font-size:.9rem; line-height:1.58; color:var(--muted);
  overflow-wrap:anywhere; transition:color 200ms ease;
}

/* ── Hover ────────────────────────────────────────────────────────────── */
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-ft:hover::before{ inset-inline-end:0; }
  .v2x.atd .atd-ft:hover .atd-ft-ds{ color:var(--ink); }
  .v2x.atd .atd-ft:hover .atd-ft-ic{
    background:var(--t-2); border-color:var(--t-2); color:#fff;
    transform:scale(1.07) rotate(-4deg);
    box-shadow:0 4px 12px rgba(var(--t-rgb),.38);
  }
  /* Dark inverts the fill instead of dimming it: --t-2 is every tone's dark
     end and would vanish into a #171922 card, and a bright fill takes a DARK
     glyph, never white. Same rule as the §PROSCONS marker. */
  body.theme-dark .v2x.atd .atd-ft:hover .atd-ft-ic{
    background:var(--t-1); border-color:var(--t-1); color:var(--dk-bg-deep,#0A0A0C);
  }
  .v2x.atd .atd-ft-grp:hover .atd-ft-gic{
    transform:scale(1.07) rotate(-3deg);
    box-shadow:0 5px 14px rgba(var(--t-rgb),.44);
  }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-ft::before,.v2x.atd .atd-ft-ic,.v2x.atd .atd-ft-ds,
  .v2x.atd .atd-ft-gic{ transition:none !important; }
  .v2x.atd .atd-ft:hover .atd-ft-ic,
  .v2x.atd .atd-ft-grp:hover .atd-ft-gic{ transform:none; }
}

/* ── The toggle ───────────────────────────────────────────────────────── */
/* ⚠️ The chevron used to render as a bare CIRCLE. `chevron-down` was in
   neither lucide registry, so the icon component fell through to its `circle`
   fallback — visible on all 33 pages beside "View all features". Fixed by
   registering the glyph in components/lucide.blade.php, not here. */
.v2x.atd .atd-feats-toggle{
  background:#fff; border:1px solid rgba(54,128,237,.30); cursor:pointer;
  border-radius:var(--r-pill); padding:10px 20px;
  display:inline-flex; align-items:center; gap:9px;
  font-family:var(--font); font-size:.94rem; font-weight:700; color:var(--accent-dark);
  box-shadow:0 1px 2px rgba(16,24,40,.05);
  transition:background .2s ease, color .2s ease, border-color .2s ease,
             box-shadow .24s ease, transform .22s cubic-bezier(.22,.61,.36,1);
}
body.theme-dark .v2x.atd .atd-feats-toggle{ background:var(--dk-surface-2,#17171B); color:#8CBEFA; border-color:rgba(96,164,245,.34); }
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-feats-toggle:hover{
    background:#2060C0; color:#fff; border-color:#2060C0;
    transform:translateY(-2px); box-shadow:0 10px 24px -8px rgba(32,96,192,.55);
  }
  body.theme-dark .v2x.atd .atd-feats-toggle:hover{
    background:#2060C0; color:#fff; border-color:#2060C0;
  }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-feats-toggle{ transition:none !important; }
  .v2x.atd .atd-feats-toggle:hover{ transform:none; }
}

/* ── Responsive ───────────────────────────────────────────────────────── */
/* Two columns is a ~250px text measure in the 992-1199px band, which the
   67-character average description fills in three lines. It holds; below
   768px it stacks. */
@media (min-width:992px) and (max-width:1199.98px){
  .v2x.atd .atd-ft-list{ gap:4px 12px; }
  .v2x.atd .atd-ft{ padding:10px 9px; gap:10px; }
}
@media (max-width:767.98px){
  .v2x.atd .atd-ft-list{ grid-template-columns:minmax(0,1fr); }
  .v2x.atd .atd-ft-groups{ gap:22px; }
}
@media (max-width:575.98px){
  .v2x.atd .atd-ft{ padding:10px; gap:10px; border-radius:11px; }
  .v2x.atd .atd-ft-ic{ width:32px; height:32px; border-radius:10px; }
  .v2x.atd .atd-ft-nm{ font-size:.96rem; }
  .v2x.atd .atd-ft-ds{ font-size:.88rem; }
  .v2x.atd .atd-ft-gic{ width:28px; height:28px; border-radius:8px; }
  .v2x.atd .atd-ft-gt{ font-size:.97rem; }
  .v2x.atd .atd-feats-toggle{ width:100%; justify-content:center; }
}

/* ── The orbit, on the group header tile's own card-free surface ───────
   The rows carry no ring: 34 of them each hosting a masked conic is a lot of
   paint for a list, and the wash already answers the pointer. The toggle is
   the one control here, so it gets one. ─────────────────────────────── */
@supports ((-webkit-mask-composite:xor) or (mask-composite:exclude)){
  .v2x.atd .atd-feats-toggle{ position:relative; }
  .v2x.atd .atd-feats-toggle::before{
    content:""; position:absolute; pointer-events:none;
    inset:-1px; z-index:1; border-radius:999px; padding:1.5px;
    --atd-spin:0deg;
    background:conic-gradient(from var(--atd-spin),
      rgba(54,128,237, 0)     0deg, rgba(54,128,237,.55)  30deg,
      rgba(255,255,255, 1)   52deg, rgba(54,128,237,.92)  74deg,
      rgba(54,128,237, 0)   118deg, rgba(54,128,237, 0)  180deg,
      rgba(54,128,237,.55) 210deg, rgba(255,255,255, 1)  232deg,
      rgba(54,128,237,.92) 254deg, rgba(54,128,237, 0)  298deg,
      rgba(54,128,237, 0)  360deg);
    -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite:xor;
            mask-composite:exclude;
    opacity:0; transition:opacity .32s ease;
    animation:atd-orbit 3.4s linear infinite; animation-play-state:paused;
  }
  .v2x.atd .atd-feats-toggle:focus-visible::before{ opacity:1; animation-play-state:running; }
  @media (hover:hover) and (pointer:fine){
    .v2x.atd .atd-feats-toggle:hover::before{ opacity:1; animation-play-state:running; }
  }
  @media (prefers-reduced-motion:reduce){
    .v2x.atd .atd-feats-toggle::before{ --atd-spin:135deg; animation:none !important; }
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   §PLAN) Pricing — a tabbed, equal-length plan table on the §SPINE-BLUE card
   recipe.

   TABS, WITHOUT JAVASCRIPT. `plan_group` splits the plans ("Personal" /
   "Business" / "API & Developers"); the blade emits one clipped radio per
   group ahead of everything else, so `:checked ~` can reach both the strip and
   the panels. That buys three things a JS control does not: the open tab
   survives the Livewire morph that follows a favourite toggle, there is no
   first-paint flash of every panel at once, and the panels stay `display:block`
   until `.is-tabbed` is on the wrapper — a stylesheet that fails to load shows
   every plan instead of hiding four fifths of them behind a dead control.

   Six groups' worth of state selectors are written out. They are the one place
   in this file where a comma list beats a shorthand: `:nth-of-type(n)` has to
   be paired with `[data-g="n-1"]`, and nothing generates that.

   EQUAL LENGTH is three separate floors, because "the cards are different
   heights" had three separate causes:
     · the row — `align-items:stretch` on a wrapping flex row equalises the
       cards in ONE row, which is all the old grid ever did;
     · the price — a word price ("Custom") is set 0.85rem smaller than a
       numeral, so its divider used to sit ~16px higher than its neighbour's.
       `min-height` + `align-content:flex-end` drops every price onto one
       baseline and every divider onto one line;
     · the list — `--pl-rows` is the longest feature list in the SECTION, not
       in the row, so a three-line plan in one tab lines its CTA up with a
       seven-line plan in another and the page does not jump on tab change.
   All three are FLOORS. Text that wraps past them grows the card; nothing is
   ever clipped to fit.

   THE HOLE. The old grid was `auto-fit minmax(215px,1fr)`, and a grid's last
   row hangs left: five plans rendered 3 + 2 with an empty third cell. A
   wrapping flex row with `justify-content:center` centres the remainder, so no
   plan count can leave a gap. Grouping makes this matter more, not less — tabs
   hold 1 to 3 plans and a lone card has to look deliberate.
   ══════════════════════════════════════════════════════════════════════════ */
/* Secondary ink for this section only. --muted2 does not clear 4.5:1 on a
   plan card in EITHER theme (light #8a8a9a: 3.36:1 flat, 2.91:1 on the popular
   card's deeper wash; dark #8E94A8: 4.26:1 there), and it carries the period
   suffix and every excluded line. Re-toning the global token would move every
   other page as a side effect, so the fix is scoped to the section. */
.v2x.atd .atd-plan-sec{ --pl-mute:#5F6472; }
body.theme-dark .v2x.atd .atd-plan-sec{ --pl-mute:#9AA0B4; }

.v2x.atd .atd-plangrid{ position:relative; }

/* Clipped, NOT `display:none` — a hidden radio leaves the tab order and the
   strip stops being reachable by keyboard. Native radio semantics also give
   arrow-key movement between tabs for free. */
.v2x.atd .atd-pgrp-in{
  position:absolute; top:0; inset-inline-start:0;
  width:1px; height:1px; margin:0; padding:0; opacity:0; pointer-events:none;
}

/* ── The tab strip ────────────────────────────────────────────────────── */
/* Centred over centred cards, and WRAPPING rather than scrolling: an
   overflow container would clip the pills' own glow, and a hidden scrollbar
   on "API & Developers · Business" at 320px hides half a tab. */
.v2x.atd .atd-pgrp{ display:flex; justify-content:center; margin:2px 0 16px; }
.v2x.atd .atd-pgrp-track{
  display:inline-flex; flex-wrap:wrap; justify-content:center; gap:6px;
  max-width:100%; padding:6px; border-radius:18px;
  background:linear-gradient(180deg,#F3F7FE 0%,#E9F0FC 100%);
  border:1px solid rgba(54,128,237,.16);
  box-shadow:inset 0 1px 2px rgba(16,24,40,.05);
}
body.theme-dark .v2x.atd .atd-pgrp-track{
  background:linear-gradient(180deg,var(--dk-surface-4,#24242A) 0%,var(--dk-surface-3,#1D1D22) 100%);
  border-color:rgba(96,164,245,.22);
  box-shadow:inset 0 1px 2px rgba(0,0,0,.42);
}
.v2x.atd .atd-pgrp-tab{
  position:relative; isolation:isolate; cursor:pointer; -webkit-user-select:none; user-select:none;
  display:inline-flex; align-items:center; gap:8px; margin:0;
  padding:9px 17px; border-radius:var(--r-pill); border:1px solid transparent;
  font-family:var(--font); font-size:.92rem; font-weight:700; line-height:1.2;
  color:var(--muted); background:transparent;
  transition:color .2s ease, background-color .24s ease, border-color .2s ease,
             box-shadow .26s ease, transform .22s cubic-bezier(.22,.61,.36,1);
}
.v2x.atd .atd-pgrp-tab .ic{ display:inline-flex; flex:0 0 auto; opacity:.75; transition:opacity .2s ease, transform .3s cubic-bezier(.16,1,.3,1); }
.v2x.atd .atd-pgrp-tab .tx{ min-width:0; }

/* Active. White on #3680ED is 3.84:1 — under the bar for a label — so the fill
   starts one step darker at both ends, the same ramp as the primary CTA. */
.v2x.atd .atd-pgrp-in:nth-of-type(1):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(1),
.v2x.atd .atd-pgrp-in:nth-of-type(2):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(2),
.v2x.atd .atd-pgrp-in:nth-of-type(3):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(3),
.v2x.atd .atd-pgrp-in:nth-of-type(4):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(4),
.v2x.atd .atd-pgrp-in:nth-of-type(5):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(5),
.v2x.atd .atd-pgrp-in:nth-of-type(6):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(6){
  background:linear-gradient(135deg,#2B70D7 0%,#1B52A6 100%); color:#fff;
  box-shadow:0 6px 16px -6px rgba(32,96,192,.62), inset 0 1px 0 rgba(255,255,255,.18);
}
.v2x.atd .atd-pgrp-in:nth-of-type(1):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(1) .ic,
.v2x.atd .atd-pgrp-in:nth-of-type(2):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(2) .ic,
.v2x.atd .atd-pgrp-in:nth-of-type(3):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(3) .ic,
.v2x.atd .atd-pgrp-in:nth-of-type(4):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(4) .ic,
.v2x.atd .atd-pgrp-in:nth-of-type(5):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(5) .ic,
.v2x.atd .atd-pgrp-in:nth-of-type(6):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(6) .ic{ opacity:1; }

/* Keyboard focus lands on the clipped input, so the ring has to be drawn on
   the label it controls. */
.v2x.atd .atd-pgrp-in:nth-of-type(1):focus-visible ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(1),
.v2x.atd .atd-pgrp-in:nth-of-type(2):focus-visible ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(2),
.v2x.atd .atd-pgrp-in:nth-of-type(3):focus-visible ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(3),
.v2x.atd .atd-pgrp-in:nth-of-type(4):focus-visible ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(4),
.v2x.atd .atd-pgrp-in:nth-of-type(5):focus-visible ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(5),
.v2x.atd .atd-pgrp-in:nth-of-type(6):focus-visible ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(6){
  outline:2px solid var(--accent); outline-offset:2px;
}

@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-pgrp-tab:hover{
    color:var(--accent-dark); background-color:rgba(255,255,255,.85);
    border-color:rgba(54,128,237,.22); transform:translateY(-1px);
    box-shadow:0 4px 12px -6px rgba(32,96,192,.45);
  }
  .v2x.atd .atd-pgrp-tab:hover .ic{ opacity:1; transform:scale(1.08); }
  body.theme-dark .v2x.atd .atd-pgrp-tab:hover{
    color:#8CBEFA; background-color:rgba(96,164,245,.12);
    border-color:rgba(96,164,245,.26); box-shadow:0 4px 12px -6px rgba(0,0,0,.6);
  }
  /* The active pill keeps its own fill — the hover wash must not lighten it. */
  .v2x.atd .atd-pgrp-in:nth-of-type(1):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(1):hover,
  .v2x.atd .atd-pgrp-in:nth-of-type(2):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(2):hover,
  .v2x.atd .atd-pgrp-in:nth-of-type(3):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(3):hover,
  .v2x.atd .atd-pgrp-in:nth-of-type(4):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(4):hover,
  .v2x.atd .atd-pgrp-in:nth-of-type(5):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(5):hover,
  .v2x.atd .atd-pgrp-in:nth-of-type(6):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(6):hover,
  body.theme-dark .v2x.atd .atd-pgrp-in:nth-of-type(1):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(1):hover,
  body.theme-dark .v2x.atd .atd-pgrp-in:nth-of-type(2):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(2):hover,
  body.theme-dark .v2x.atd .atd-pgrp-in:nth-of-type(3):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(3):hover,
  body.theme-dark .v2x.atd .atd-pgrp-in:nth-of-type(4):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(4):hover,
  body.theme-dark .v2x.atd .atd-pgrp-in:nth-of-type(5):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(5):hover,
  body.theme-dark .v2x.atd .atd-pgrp-in:nth-of-type(6):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(6):hover{
    color:#fff; background-color:transparent; border-color:transparent;
    transform:translateY(-1px);
    box-shadow:0 9px 22px -8px rgba(32,96,192,.72), inset 0 1px 0 rgba(255,255,255,.18);
  }
}

/* ── Note line + the flat fallback's group heading ────────────────────── */
.v2x.atd .atd-plan-note{
  display:flex; align-items:flex-start; gap:7px; justify-content:center;
  margin:0 0 16px; font-size:.85rem; line-height:1.5; color:var(--muted); text-align:center;
}
.v2x.atd .atd-plan-note svg{ flex:0 0 auto; margin-top:3px; color:var(--accent-dark); opacity:.85; }
body.theme-dark .v2x.atd .atd-plan-note svg{ color:#8CBEFA; }
/* Only rendered when an admin turns the tab strip OFF on a grouped tool. */
.v2x.atd .atd-plan-gtitle{
  display:flex; align-items:center; gap:8px;
  margin:0 0 12px; font-family:var(--font); font-size:1.02rem; font-weight:800;
  letter-spacing:-.01em; color:var(--ink);
}
.v2x.atd .atd-plan-gtitle svg{ color:var(--accent-dark); }
body.theme-dark .v2x.atd .atd-plan-gtitle svg{ color:#8CBEFA; }
.v2x.atd .atd-plan-panel + .atd-plan-panel{ margin-top:22px; }

/* ── Panel switching ──────────────────────────────────────────────────── */
.v2x.atd .atd-plangrid.is-tabbed .atd-plan-panel{ display:none; }
.v2x.atd .atd-plangrid.is-tabbed .atd-plan-panel + .atd-plan-panel{ margin-top:0; }
.v2x.atd .atd-plangrid.is-tabbed .atd-pgrp-in:nth-of-type(1):checked ~ .atd-plan-panel[data-g="0"],
.v2x.atd .atd-plangrid.is-tabbed .atd-pgrp-in:nth-of-type(2):checked ~ .atd-plan-panel[data-g="1"],
.v2x.atd .atd-plangrid.is-tabbed .atd-pgrp-in:nth-of-type(3):checked ~ .atd-plan-panel[data-g="2"],
.v2x.atd .atd-plangrid.is-tabbed .atd-pgrp-in:nth-of-type(4):checked ~ .atd-plan-panel[data-g="3"],
.v2x.atd .atd-plangrid.is-tabbed .atd-pgrp-in:nth-of-type(5):checked ~ .atd-plan-panel[data-g="4"],
.v2x.atd .atd-plangrid.is-tabbed .atd-pgrp-in:nth-of-type(6):checked ~ .atd-plan-panel[data-g="5"]{ display:block; }

@keyframes atd-plan-in{ from{ opacity:0; transform:translateY(12px); } to{ opacity:1; transform:none; } }

/* ── The row ──────────────────────────────────────────────────────────── */
.v2x.atd .atd-plans{
  display:flex; flex-wrap:wrap; justify-content:center; align-items:stretch;
  gap:16px;
  /* room for the POPULAR tab, which hangs above its card */
  padding-top:13px;
}
.v2x.atd .atd-plans > .atd-plan{ flex:0 1 calc(33.333% - 11px); min-width:0; }
.v2x.atd .atd-plans[data-count="1"] > .atd-plan{ flex-basis:min(100%, 380px); }
.v2x.atd .atd-plans[data-count="2"] > .atd-plan,
.v2x.atd .atd-plans[data-count="4"] > .atd-plan{ flex-basis:calc(50% - 8px); }

/* ── The card ─────────────────────────────────────────────────────────── */
.v2x.atd .atd-plan{
  position:relative; isolation:isolate;
  display:flex; flex-direction:column;
  padding:24px 22px; border-radius:18px;
  background-image:linear-gradient(150deg,
    rgba(54,128,237,.06) 0%, rgba(54,128,237,.01) 46%, rgba(54,128,237,.045) 100%);
  background-repeat:no-repeat; background-color:#fff;
  border:1px solid rgba(54,128,237,.18);
  box-shadow:0 1px 2px rgba(16,24,40,.04), 0 6px 20px rgba(16,24,40,.05);
  transition:transform .22s cubic-bezier(.22,.61,.36,1), border-color .2s ease, box-shadow .24s ease;
  /* `backwards`, never `both`: a `both` fill would pin transform:none after the
     run and the hover lift would stop working. */
  animation:atd-plan-in .42s cubic-bezier(.16,1,.3,1) backwards;
}
.v2x.atd .atd-plans > .atd-plan:nth-child(2){ animation-delay:.06s; }
.v2x.atd .atd-plans > .atd-plan:nth-child(3){ animation-delay:.12s; }
.v2x.atd .atd-plans > .atd-plan:nth-child(4){ animation-delay:.18s; }
.v2x.atd .atd-plans > .atd-plan:nth-child(n+5){ animation-delay:.24s; }
body.theme-dark .v2x.atd .atd-plan{
  background-image:linear-gradient(150deg,
    rgba(54,128,237,.12) 0%, rgba(54,128,237,.02) 46%, rgba(54,128,237,.08) 100%);
  background-color:var(--dk-surface-3,#1D1D22);
  border-color:rgba(54,128,237,.28);
  box-shadow:0 1px 2px rgba(0,0,0,.40), 0 6px 20px rgba(0,0,0,.35);
}
.v2x.atd .atd-plan::after{
  content:""; position:absolute; inset:0; z-index:-1; pointer-events:none;
  border-radius:inherit;
  background:radial-gradient(200px 200px at calc(100% + 28px) -44px,
    rgba(54,128,237,.20) 0%, rgba(54,128,237,0) 70%) no-repeat;
  opacity:.9; transform-origin:100% 0;
  transition:opacity 360ms ease, transform 520ms cubic-bezier(.16,1,.3,1);
}
body.theme-dark .v2x.atd .atd-plan::after{
  background:radial-gradient(200px 200px at calc(100% + 28px) -44px,
    rgba(54,128,237,.15) 0%, rgba(54,128,237,0) 70%) no-repeat;
}

/* ── The hover sheen ──────────────────────────────────────────────────── */
/* A real element, not a third pseudo: ::after is the corner bloom and ::before
   is either the orbit ring or the popular card's lit edge. `z-index:-1` puts
   the sweep above the card's own wash and BELOW every line of text — at
   `z-index:0` a positioned layer paints over in-flow text and the sweep would
   wash the prices as it passed. Tinted brand light, not white: white on a
   white card is invisible, which is the whole point of the effect missing. */
.v2x.atd .atd-plan-sheen{
  position:absolute; inset:0; z-index:-1; pointer-events:none;
  border-radius:inherit; overflow:hidden; opacity:0;
  transition:opacity .3s ease;
}
.v2x.atd .atd-plan-sheen::before{
  content:""; position:absolute; top:-60%; bottom:-60%; width:46%; inset-inline-start:-70%;
  transform:skewX(-18deg);
  background:linear-gradient(100deg,
    rgba(54,128,237,0) 0%, rgba(54,128,237,.13) 48%, rgba(54,128,237,0) 100%);
}
body.theme-dark .v2x.atd .atd-plan-sheen::before{
  background:linear-gradient(100deg,
    rgba(140,190,250,0) 0%, rgba(140,190,250,.12) 48%, rgba(140,190,250,0) 100%);
}
@keyframes atd-plan-sheen{ from{ inset-inline-start:-70%; } to{ inset-inline-start:120%; } }

/* The one popular plan per tool. A ring, a lit top edge and a deeper wash —
   NOT a scale transform: scaling a card in a wrapping row shifts every card
   beside it. */
.v2x.atd .atd-plan.is-popular{
  border-color:rgba(54,128,237,.50);
  background-image:linear-gradient(150deg,
    rgba(54,128,237,.13) 0%, rgba(54,128,237,.025) 46%, rgba(54,128,237,.10) 100%);
  box-shadow:0 0 0 3px rgba(54,128,237,.14), 0 10px 30px -12px rgba(32,96,192,.34);
}
.v2x.atd .atd-plan.is-popular::before{
  content:""; position:absolute; inset-inline:18px; top:-1px; height:3px;
  border-radius:0 0 3px 3px; z-index:2;
  background:linear-gradient(90deg,
    rgba(54,128,237,0), var(--accent) 30%, var(--accent-light) 50%, var(--accent) 70%, rgba(54,128,237,0));
}
body.theme-dark .v2x.atd .atd-plan.is-popular{
  border-color:rgba(96,164,245,.55);
  background-image:linear-gradient(150deg,
    rgba(54,128,237,.20) 0%, rgba(54,128,237,.04) 46%, rgba(54,128,237,.14) 100%);
  box-shadow:0 0 0 3px rgba(96,164,245,.16), 0 10px 30px -12px rgba(0,0,0,.55);
}
.v2x.atd .atd-plan-pop{
  position:absolute; top:-13px; inset-inline-start:50%; transform:translateX(-50%);
  z-index:3; white-space:nowrap;
  display:inline-flex; align-items:center; gap:5px;
  background:linear-gradient(135deg,#2B70D7,#1B52A6); color:#fff;
  font-family:var(--font); font-size:.68rem; font-weight:800;
  letter-spacing:.06em; text-transform:uppercase;
  border-radius:var(--r-pill); padding:5px 13px;
  box-shadow:0 6px 16px -6px rgba(32,96,192,.8);
}
.v2x.atd .atd-plan-pop svg{ opacity:.9; }

/* ── Name · price ─────────────────────────────────────────────────────── */
.v2x.atd .atd-plan-name{
  margin:0 0 10px; font-family:var(--font); font-size:1.2rem; font-weight:700;
  letter-spacing:-.015em; line-height:1.25; color:var(--ink); overflow-wrap:anywhere;
}
/* `min-height` + `align-content:flex-end` is the price half of "equal length":
   it drops a 1.45rem word price onto the same baseline as a 2.3rem numeral, so
   the divider under it lands on the same line on every card in the row. */
.v2x.atd .atd-plan-price{
  display:flex; align-items:baseline; align-content:flex-end; flex-wrap:wrap; gap:3px 6px;
  min-height:2.55rem;
  margin:0 0 18px; padding-bottom:16px; border-bottom:1px solid var(--line);
}
.v2x.atd .atd-plan-price .amt{
  font-family:var(--font); font-size:2.3rem; font-weight:800;
  letter-spacing:-.035em; line-height:1.05; color:var(--ink); overflow-wrap:anywhere;
}
/* "Custom", "Pay as you go", "Premium tier", "Bundled" are words, not figures,
   and must never be set at the numeral size. The blade decides by looking for
   a digit, so a new free-text price is handled without a code change. */
.v2x.atd .atd-plan-price .amt.is-word{ font-size:1.45rem; letter-spacing:-.02em; line-height:1.3; }
.v2x.atd .atd-plan-price .per{ font-size:.86rem; font-weight:600; color:var(--pl-mute); }
body.theme-dark .v2x.atd .atd-plan-price{ border-bottom-color:var(--line); }

/* The popular plan's figure in brand gradient. Gated: without background-clip
   the transparent fill would leave the price INVISIBLE, which is the one
   failure mode this page does not tolerate. The ramp stops at #3680ED (3.85:1
   on white, 3.4:1 on the dark card) because at 2.3rem/800 this is large text
   at a 3:1 bar — #60A4F5's 2.68:1 on white would not have cleared it. */
@supports ((-webkit-background-clip:text) or (background-clip:text)){
  .v2x.atd .atd-plan.is-popular .atd-plan-price .amt{
    background:linear-gradient(135deg,#1B52A6 0%,#2B70D7 55%,#3680ED 100%);
    -webkit-background-clip:text; background-clip:text;
    -webkit-text-fill-color:transparent; color:transparent;
  }
  body.theme-dark .v2x.atd .atd-plan.is-popular .atd-plan-price .amt{
    background:linear-gradient(135deg,#CFE2FD 0%,#8CBEFA 55%,#60A4F5 100%);
    -webkit-background-clip:text; background-clip:text;
  }
}

/* ── Feature lines ────────────────────────────────────────────────────── */
.v2x.atd .atd-plan-inc{
  display:flex; align-items:center; gap:9px; margin:0 0 12px;
  font-family:var(--font); font-size:.68rem; font-weight:800;
  letter-spacing:.09em; text-transform:uppercase; color:var(--muted);
}
.v2x.atd .atd-plan-inc::after{
  content:""; flex:1 1 auto; height:1px;
  background:linear-gradient(90deg, var(--line-strong), rgba(54,128,237,0));
}
.v2x.atd .atd-plan-list{
  list-style:none; margin:0 0 20px; padding:0; flex:1 1 auto;
  display:flex; flex-direction:column; gap:11px;
  /* The list half of "equal length": floored to the longest list in the
     section, so a short plan's CTA lines up with a long one's — across rows
     AND across tabs, which `align-items:stretch` alone cannot reach. */
  min-height:calc(var(--pl-rows, 0) * (1.4265rem + 11px) - 11px);
}
.v2x.atd .atd-plan-list li{ display:flex; align-items:flex-start; gap:10px; }
.v2x.atd .atd-plan-list .mk{
  flex:0 0 auto; width:19px; height:19px; margin-top:2px; border-radius:6px;
  display:inline-flex; align-items:center; justify-content:center;
  background:#E6F8F1; color:#08795A; border:1px solid #C6EEDF;
  transition:transform .28s cubic-bezier(.16,1,.3,1), box-shadow .28s ease;
}
.v2x.atd .atd-plan-list .tx{
  flex:1 1 auto; min-width:0; font-size:.92rem; line-height:1.55; color:var(--muted);
  overflow-wrap:anywhere;
}
/* NOT included. `text-decoration:line-through` is gone: striking a line through
   copy is the one treatment on this page that genuinely obscures text, and it
   bought nothing the × and the muted ink do not already say. Three of the 530
   stored lines are excluded, so this is a rarity either way. */
.v2x.atd .atd-plan-list li.off .mk{ background:#EEF1F6; color:#454C5C; border-color:#DFE4EC; }
.v2x.atd .atd-plan-list li.off .tx{ color:var(--pl-mute); text-decoration:none; }
body.theme-dark .v2x.atd .atd-plan-list .mk{ background:rgba(16,185,129,.18); color:#6EE7BE; border-color:rgba(52,211,153,.30); }
body.theme-dark .v2x.atd .atd-plan-list li.off .mk{ background:rgba(255,255,255,.08); color:#B9C0CE; border-color:var(--dk-line-strong,rgba(255,255,255,.16)); }

/* ── CTA ──────────────────────────────────────────────────────────────── */
/* The fill is a background-IMAGE grown from 0% to 100% width, not an overlay
   element and not `overflow:hidden` + a wiping child: the orbit ring already
   owns ::before at `inset:-1px`, and clipping the button would cut it off. */
.v2x.atd .atd-plan-cta{
  margin-top:auto; width:100%;
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  padding:12px 16px; border-radius:10px;
  font-family:var(--font); font-size:.93rem; font-weight:700; text-decoration:none;
  color:var(--accent-dark); border:1px solid rgba(54,128,237,.34);
  background-color:#fff;
  background-image:linear-gradient(135deg,#2B70D7 0%,#1B52A6 100%);
  background-repeat:no-repeat; background-position:left center; background-size:0% 100%;
  box-shadow:0 1px 2px rgba(16,24,40,.05);
  transition:background-size .34s cubic-bezier(.22,.61,.36,1), color .2s ease 0s,
             border-color .2s ease, box-shadow .24s ease,
             transform .22s cubic-bezier(.22,.61,.36,1);
}
[dir="rtl"] .v2x.atd .atd-plan-cta,
[dir="rtl"] .v2x.atd .atd-plan-more{ background-position:right center; }
/* white on #3680ED is 3.84:1 — under the bar for a button label, so the
   gradient starts one step darker at both ends. Same ramp as §RVX's submit. */
.v2x.atd .atd-plan-cta.is-primary{
  background-size:100% 100%; color:#fff; border-color:transparent;
  box-shadow:0 4px 14px rgba(32,96,192,.30);
}
body.theme-dark .v2x.atd .atd-plan-cta{ background-color:var(--dk-surface-2,#17171B); color:#8CBEFA; border-color:rgba(96,164,245,.36); }
body.theme-dark .v2x.atd .atd-plan-cta.is-primary{ color:#fff; border-color:transparent; }
.v2x.atd .atd-plan-cta .lb{ position:relative; }
.v2x.atd .atd-plan-cta svg{ flex:0 0 auto; opacity:.85; transition:transform 320ms cubic-bezier(.16,1,.3,1); }
.v2x.atd .atd-plan-cta:focus-visible{ outline:none; box-shadow:0 0 0 3px rgba(54,128,237,.34); }

/* ── Section footer link ──────────────────────────────────────────────── */
.v2x.atd .atd-plan-more{
  display:inline-flex; align-items:center; gap:8px;
  padding:10px 20px; border-radius:var(--r-pill);
  color:var(--accent-dark); border:1px solid rgba(54,128,237,.30);
  background-color:#fff;
  background-image:linear-gradient(135deg,#2B70D7 0%,#1B52A6 100%);
  background-repeat:no-repeat; background-position:left center; background-size:0% 100%;
  font-family:var(--font); font-size:.93rem; font-weight:700; text-decoration:none;
  box-shadow:0 1px 2px rgba(16,24,40,.05);
  transition:background-size .34s cubic-bezier(.22,.61,.36,1), color .2s ease 0s,
             border-color .2s ease, box-shadow .24s ease,
             transform .22s cubic-bezier(.22,.61,.36,1);
}
body.theme-dark .v2x.atd .atd-plan-more{ background-color:var(--dk-surface-2,#17171B); color:#8CBEFA; border-color:rgba(96,164,245,.34); }
.v2x.atd .atd-plan-more svg{ transition:transform 320ms cubic-bezier(.16,1,.3,1); }

/* ── Hover ────────────────────────────────────────────────────────────── */
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-plan:hover{
    transform:translateY(-4px);
    border-color:rgba(54,128,237,.42);
    box-shadow:0 2px 6px rgba(16,24,40,.06), 0 20px 44px -16px rgba(32,96,192,.30);
  }
  .v2x.atd .atd-plan.is-popular:hover{
    border-color:rgba(54,128,237,.60);
    box-shadow:0 0 0 3px rgba(54,128,237,.18), 0 22px 48px -16px rgba(32,96,192,.42);
  }
  .v2x.atd .atd-plan:hover::after{ opacity:1; transform:scale(1.16); }
  .v2x.atd .atd-plan:hover .atd-plan-sheen{ opacity:1; }
  .v2x.atd .atd-plan:hover .atd-plan-sheen::before{ animation:atd-plan-sheen 1.05s cubic-bezier(.22,.61,.36,1); }
  .v2x.atd .atd-plan:hover .atd-plan-list li:not(.off) .mk{
    transform:scale(1.09); box-shadow:0 3px 8px -3px rgba(8,121,90,.42);
  }
  body.theme-dark .v2x.atd .atd-plan:hover{
    border-color:rgba(96,164,245,.52);
    box-shadow:0 2px 6px rgba(0,0,0,.50), 0 20px 44px -16px rgba(0,0,0,.60);
  }
  body.theme-dark .v2x.atd .atd-plan:hover .atd-plan-list li:not(.off) .mk{ box-shadow:0 3px 8px -3px rgba(0,0,0,.6); }

  /* The label turns white on a delay so the fill is already most of the way
     across — without it the text is white on white for ~150ms. Coming BACK the
     delay is 0s (that lives on the base rule), so the ink returns at once. */
  .v2x.atd .atd-plan-cta:hover,
  .v2x.atd .atd-plan-more:hover{
    background-size:100% 100%; color:#fff; border-color:transparent;
    transform:translateY(-2px); box-shadow:0 12px 28px -8px rgba(32,96,192,.58);
    transition:background-size .38s cubic-bezier(.22,.61,.36,1), color .18s ease .12s,
               border-color .2s ease, box-shadow .24s ease,
               transform .22s cubic-bezier(.22,.61,.36,1);
  }
  .v2x.atd .atd-plan-cta.is-primary:hover{
    background-image:linear-gradient(135deg,#2464C4 0%,#164694 100%);
    box-shadow:0 14px 30px -8px rgba(32,96,192,.66);
  }
  .v2x.atd .atd-plan-cta:hover svg,
  .v2x.atd .atd-plan-more:hover svg{ transform:translate(2px,-2px); opacity:1; }
  body.theme-dark .v2x.atd .atd-plan-cta:hover,
  body.theme-dark .v2x.atd .atd-plan-more:hover{
    color:#fff; border-color:transparent; box-shadow:0 12px 28px -8px rgba(0,0,0,.62);
  }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-plan,.v2x.atd .atd-plan::after,.v2x.atd .atd-plan-cta,
  .v2x.atd .atd-plan-cta svg,.v2x.atd .atd-plan-more,.v2x.atd .atd-plan-more svg,
  .v2x.atd .atd-pgrp-tab,.v2x.atd .atd-pgrp-tab .ic,.v2x.atd .atd-plan-list .mk{ transition:none !important; }
  .v2x.atd .atd-plan{ animation:none !important; }
  .v2x.atd .atd-plan-sheen{ display:none; }
  .v2x.atd .atd-plan:hover,.v2x.atd .atd-plan-cta:hover,.v2x.atd .atd-plan-more:hover,
  .v2x.atd .atd-pgrp-tab:hover{ transform:none; }
  .v2x.atd .atd-plan:hover::after{ transform:none; }
  .v2x.atd .atd-plan:hover .atd-plan-list li:not(.off) .mk{ transform:none; }
  .v2x.atd .atd-plan-cta:hover svg,.v2x.atd .atd-plan-more:hover svg{ transform:none; }
  .v2x.atd .atd-pgrp-tab:hover .ic{ transform:none; }
}

/* ── Responsive ───────────────────────────────────────────────────────── */
/* 1200-1399: the main column is ~700px, so a 3-plan tab holds at ~225px a card
   and 4+ drops to 2-up (which the [data-count="4"] basis already does). */
/* 992-1199 is the tightest band on this page — the main column is ~600px, so
   three across would leave ~190px a card. Everything drops to two. */
@media (min-width:992px) and (max-width:1199.98px){
  .v2x.atd .atd-plans > .atd-plan,
  .v2x.atd .atd-plans[data-count] > .atd-plan{ flex-basis:calc(50% - 8px); }
  .v2x.atd .atd-plans[data-count="1"] > .atd-plan{ flex-basis:min(100%, 380px); }
}
/* Tablet — the sidebar has dropped below, so the column is the full width and
   three across is comfortable again. */
@media (min-width:768px) and (max-width:991.98px){
  .v2x.atd .atd-plan{ padding:22px 19px; }
  .v2x.atd .atd-plans[data-count="4"] > .atd-plan,
  .v2x.atd .atd-plans[data-count="5"] > .atd-plan,
  .v2x.atd .atd-plans[data-count="6"] > .atd-plan{ flex-basis:calc(50% - 8px); }
}
@media (max-width:767.98px){
  .v2x.atd .atd-plans > .atd-plan,
  .v2x.atd .atd-plans[data-count] > .atd-plan{ flex-basis:calc(50% - 8px); }
  .v2x.atd .atd-plans[data-count="1"] > .atd-plan{ flex-basis:min(100%, 380px); }
  .v2x.atd .atd-pgrp-tab{ padding:8px 13px; font-size:.88rem; }
}
@media (max-width:575.98px){
  .v2x.atd .atd-plans{ gap:13px; }
  .v2x.atd .atd-plans > .atd-plan,
  .v2x.atd .atd-plans[data-count] > .atd-plan{ flex-basis:100%; }
  .v2x.atd .atd-plan{ padding:20px 17px; border-radius:15px; }
  .v2x.atd .atd-plan-price .amt{ font-size:2rem; }
  .v2x.atd .atd-plan-price{ min-height:2.3rem; }
  .v2x.atd .atd-plan-more{ width:100%; justify-content:center; }
  .v2x.atd .atd-pgrp-track{ width:100%; padding:5px; border-radius:16px; }
  .v2x.atd .atd-pgrp-tab{ flex:1 1 auto; justify-content:center; padding:9px 11px; gap:6px; }
  .v2x.atd .atd-plan-note{ font-size:.82rem; text-align:start; justify-content:flex-start; }
  /* One card a row already equalises them; the section-wide floor would only
     add empty space under a short list on the narrowest screen. */
  .v2x.atd .atd-plan-list{ min-height:0; }
}
/* Below ~360px the icon is the first thing to go — the LABEL never is. */
@media (max-width:359.98px){
  .v2x.atd .atd-pgrp-tab .ic{ display:none; }
  .v2x.atd .atd-pgrp-tab{ padding:9px 9px; font-size:.84rem; }
}

/* ── The orbit ring ───────────────────────────────────────────────────── */
@supports ((-webkit-mask-composite:xor) or (mask-composite:exclude)){
  /* Both pseudos on a plan card are spoken for: ::after is the corner bloom
     and ::before is the popular card's lit top edge. So the ring is drawn on
     ::before for the OTHER cards only — which is the right answer anyway. The
     popular card already wears a permanent 3px ring and a glow; adding a
     travelling one would be two rings on the one card that least needs help
     being noticed. */
  .v2x.atd .atd-plan:not(.is-popular)::before,
  .v2x.atd .atd-pgrp-tab::before,
  .v2x.atd .atd-plan-cta::before,
  .v2x.atd .atd-plan-more::before{
    content:""; position:absolute; pointer-events:none;
    inset:-1px; z-index:1; padding:1.5px;
    --atd-spin:0deg;
    background:conic-gradient(from var(--atd-spin),
      rgba(54,128,237, 0)     0deg, rgba(54,128,237,.55)  30deg,
      rgba(255,255,255, 1)   52deg, rgba(54,128,237,.92)  74deg,
      rgba(54,128,237, 0)   118deg, rgba(54,128,237, 0)  180deg,
      rgba(54,128,237,.55) 210deg, rgba(255,255,255, 1)  232deg,
      rgba(54,128,237,.92) 254deg, rgba(54,128,237, 0)  298deg,
      rgba(54,128,237, 0)  360deg);
    -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite:xor;
            mask-composite:exclude;
    opacity:0; transition:opacity .32s ease;
    animation:atd-orbit 6s linear infinite; animation-play-state:paused;
  }
  .v2x.atd .atd-plan:not(.is-popular)::before{ border-radius:19px; }
  .v2x.atd .atd-pgrp-tab::before{ border-radius:999px; animation-duration:3.2s; }
  .v2x.atd .atd-plan-cta{ position:relative; }
  .v2x.atd .atd-plan-cta::before{ border-radius:11px; animation-duration:3.2s; }
  .v2x.atd .atd-plan-more{ position:relative; }
  .v2x.atd .atd-plan-more::before{ border-radius:999px; animation-duration:3.2s; }
  .v2x.atd .atd-plan-cta.is-primary::before{ --atd-spin:0deg; }
  .v2x.atd .atd-plan-cta:focus-visible::before,
  .v2x.atd .atd-plan-more:focus-visible::before{ opacity:1; animation-play-state:running; }
  @media (hover:hover) and (pointer:fine){
    .v2x.atd .atd-plan:not(.is-popular):hover::before,
    .v2x.atd .atd-pgrp-tab:hover::before,
    .v2x.atd .atd-plan-cta:hover::before,
    .v2x.atd .atd-plan-more:hover::before{ opacity:1; animation-play-state:running; }
    /* the card's ring stands down while its own button is lit */
    .v2x.atd .atd-plan:not(.is-popular):has(.atd-plan-cta:hover)::before{ opacity:.3; }
    /* an ACTIVE tab is already filled — a ring on top of the fill is noise */
    .v2x.atd .atd-pgrp-in:nth-of-type(1):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(1):hover::before,
    .v2x.atd .atd-pgrp-in:nth-of-type(2):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(2):hover::before,
    .v2x.atd .atd-pgrp-in:nth-of-type(3):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(3):hover::before,
    .v2x.atd .atd-pgrp-in:nth-of-type(4):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(4):hover::before,
    .v2x.atd .atd-pgrp-in:nth-of-type(5):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(5):hover::before,
    .v2x.atd .atd-pgrp-in:nth-of-type(6):checked ~ .atd-pgrp .atd-pgrp-tab:nth-of-type(6):hover::before{ opacity:0; }
  }
  @media (prefers-reduced-motion:reduce){
    .v2x.atd .atd-plan:not(.is-popular)::before,
    .v2x.atd .atd-pgrp-tab::before,
    .v2x.atd .atd-plan-cta::before,
    .v2x.atd .atd-plan-more::before{ --atd-spin:135deg; animation:none !important; }
  }
  @media (max-width:575.98px){
    .v2x.atd .atd-plan:not(.is-popular)::before{ border-radius:16px; }
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   §AIM) Built on these AI Models — the LISTING grid card, on this page.

   THE REFERENCE MOVED. This kit used to reproduce `.hpx-card-showcase` (the
   homepage rail): a left-aligned card with a small logo beside the name. It
   now reproduces `.dir-tc` — the card the /ai-models grid ships — because that
   is the card a visitor has already met by the time they reach a tool page,
   and a model should not look like two different objects on two URLs.

   WHAT THAT CHANGES, part by part:
     · the column is CENTRED, not left-aligned (`align-items:center` +
       `text-align:center`), and the logo tile grows 46 → 60px and moves from
       a white chip to a `--t-bg` tinted plate;
     · the name/vendor/description drop to the listing's type scale
       (15.5 / 12 / 12.5px) so the card can be ~270px wide instead of ~420;
     · the static 4px top edge becomes the reference's CENTRE-OUT accent bar,
       drawn at zero width and grown on hover;
     · the surface gains §TCPRM's diagonal wash and corner bloom on top of the
       orbit ring this kit already had.

   ⚠️ THREE PAGES RENDER THIS CARD, not one. `.atd-aim` is a shared kit:
   §AIM on the tool page ("Built on these AI Models"), the products grid on
   /company/{slug}, and the alternatives grid on /ai-models/{slug} — all three
   host `<div class="v2x atd …">`, so every rule below lands on all three. The
   child structure is identical in all three blades; only `.is-static` (a
   product with nowhere to link) is extra, and the two sibling sheets own it.

   ⚠️ NO RANK CHIP. The reference carries one, and it is deliberately not
   ported: `.dir-tc` is a RANKED grid, so "1" there is a fact. The models a
   tool is built on are an unordered set, and gold/silver medals over
   ChatGPT and DALL·E would assert a ranking the pivot does not hold. The
   reference's top-left slot is left empty; the Featured / New flag keeps the
   top-right corner it already had.

   ⚠️ `--t-1` IS STILL NOT USABLE FOR THE CTA, even though the reference fills
   its button with the tone mid (`--dtc-ink`). That ramp is measured for a
   white GLYPH (3:1); a white LABEL needs 4.5:1, which #4C8DF2 (3.28) and
   #10B981 (2.54) do not reach. `--t-btn` is the first step toward `--t-2`
   that clears 4.6 on every tone — 4.60 to 4.63 at the light end, 5.04 to 7.73
   at the dark — and stays the fill here.
   ══════════════════════════════════════════════════════════════════════════ */
.v2x.atd .atd-t0{ --t-btn:#3373D6; }
.v2x.atd .atd-t1{ --t-btn:#8456EF; }
.v2x.atd .atd-t2{ --t-btn:#0A8561; }
.v2x.atd .atd-t3{ --t-btn:#AF6108; }
.v2x.atd .atd-t4{ --t-btn:#DA3150; }
.v2x.atd .atd-t5{ --t-btn:#107F9B; }

/* ── The grid ─────────────────────────────────────────────────────────────
   THE ROW IS FILLED. Every track is `1fr` and NOTHING here caps a width, so
   whatever the count, the cards stretch edge to edge of the panel. That is a
   direct instruction and it outranks the reference: `.dir-cards` is four fixed
   tracks and leaves the remainder of a short row empty, which is fine on a
   listing where pagination explains it and wrong here, where the count IS the
   whole set and the band above fills its own row.

   ⚠️ THE COLUMN COUNT IS STILL EXPLICIT PER `data-count`, and that is the half
   that cannot be replaced by `auto-fit`. `auto-fit` picks the track count from
   the container and then orphans the remainder: in the 1237px panel it makes
   five tracks, so six products split 5 + 1 with one card alone on row two. The
   ladder below picks a count that divides the set — 6 → 3 × 2, 8 → 4 × 2 — and
   `1fr` does the filling. Five is the one count with no clean divisor; 3 + 2
   leaves one gap on the second row, which is fewer than 4 + 1 leaves.

   ⚠️ THE TWO HOSTS ARE DIFFERENT WIDTHS. The tool page puts this section in a
   ~700px column beside a sidebar; /company and /ai-models are full width at
   ~1237px. Filling is what makes that difference harmless — the same three
   cards are 287px on a 1440px screen and 403px on an ultra-wide one, instead
   of being 287px on both and stranding a third of the wide panel.

   ⚠️ ONE CARD FILLS TOO — no exception, and the exception was tried. A lone
   card was capped at 288px on the argument that a single one stretched across
   the panel is a banner, not a card. It is the MAJORITY case (19 of the 20
   tools that have any models have exactly one), so that cap is not an edge
   case tucked away, it is what most tool pages would show: one small card
   against an otherwise empty panel — the exact emptiness the fill was asked
   for. Side by side at 1150px the filled one reads as a finished section and
   the capped one as a section still loading. Every count fills. */
.v2x.atd .atd-aims{
  --aim-g:14px;
  display:grid; gap:var(--aim-g); align-items:stretch;
  grid-template-columns:repeat(auto-fit, minmax(min(100%, 236px), 1fr));
}
.v2x.atd .atd-aims[data-count="1"]{ grid-template-columns:minmax(0,1fr); }
.v2x.atd .atd-aims[data-count="2"]{ grid-template-columns:repeat(2, minmax(0,1fr)); }
.v2x.atd .atd-aims[data-count="3"],
.v2x.atd .atd-aims[data-count="5"],
.v2x.atd .atd-aims[data-count="6"]{ grid-template-columns:repeat(3, minmax(0,1fr)); }
.v2x.atd .atd-aims[data-count="4"],
.v2x.atd .atd-aims[data-count="7"],
.v2x.atd .atd-aims[data-count="8"]{ grid-template-columns:repeat(4, minmax(0,1fr)); }

/* The tool page's column is roughly half the width of the other two hosts'.
   Four tracks in it would be ~160px — narrower than the logo plate plus its
   own padding — so the high counts drop a column before the phone break does
   it for them. Keyed to the viewport rather than the container because none
   of the three hosts is a container-query context. */
@media (max-width:1199.98px){
  .v2x.atd .atd-aims[data-count="4"],
  .v2x.atd .atd-aims[data-count="7"],
  .v2x.atd .atd-aims[data-count="8"]{ grid-template-columns:repeat(2, minmax(0,1fr)); }
}

/* ── The card ─────────────────────────────────────────────────────────────
   §TCPRM's surface: a diagonal wash over the card colour, a tone-tinted
   hairline, and the bloom + ring below.

   ⚠️ `background-image` ONLY, never the `background` shorthand — and the dark
   rule has to RESTATE the image for the same reason. See
   [[dark-background-shorthand-trap]]: a shorthand at higher specificity
   resets `background-image` to none in the same declaration that sets the
   colour, and the whole tone system then vanishes after dark and only after
   dark. Both rules below therefore set `background-color` and
   `background-image` as separate properties.

   The 152deg angle, the 48% dead stop and the fade to `rgba(same-hue, 0)`
   rather than the `transparent` KEYWORD are §HPXP-WASH's. The last one is not
   cosmetic: a gradient fading to `transparent` interpolates through
   transparent BLACK in sRGB and leaves a grey fringe down the middle.

   `padding-top` is 34px because the flag is absolute at 12px. Every card in
   the row carries it whether or not it has a flag — a padding that changed
   per card would step the logo tiles out of line across the row. */
.v2x.atd .atd-aim{
  --aim-a1:.075;   /* wash, the lit corner */
  --aim-a2:.055;   /* wash, the far corner */
  --aim-edge:.20;  /* the tinted hairline */
  --aim-bloom:.20; /* the corner bloom's hot end */
  position:relative; isolation:isolate; overflow:hidden;
  display:flex; flex-direction:column; align-items:center; text-align:center;
  padding:34px 15px 16px; border-radius:18px;
  background-color:#fff;
  background-image:linear-gradient(152deg,
    rgba(var(--t-rgb), var(--aim-a1)) 0%,
    rgba(var(--t-rgb), 0)            48%,
    rgba(var(--t-rgb), var(--aim-a2)) 100%);
  background-repeat:no-repeat;
  border:1px solid rgba(var(--t-rgb), var(--aim-edge));
  color:var(--ink); text-decoration:none;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.7), 0 1px 2px rgba(16,24,40,.04), 0 10px 24px -20px rgba(16,24,40,.30);
  transition:transform .26s cubic-bezier(.22,.61,.36,1), border-color .2s ease, box-shadow .26s ease;
}
/* Dark: the card is LIGHTER than the page ground and separates on its own, so
   the wash is free to carry hue rather than separation — and every alpha
   rises anyway, because a 5% tint that reads over white is invisible over
   near-black. */
body.theme-dark .v2x.atd .atd-aim{
  --aim-a1:.13; --aim-a2:.09; --aim-edge:.30; --aim-bloom:.17;
  background-color:var(--dk-surface-3,#1D1D22);
  background-image:linear-gradient(152deg,
    rgba(var(--t-rgb), var(--aim-a1)) 0%,
    rgba(var(--t-rgb), 0)            48%,
    rgba(var(--t-rgb), var(--aim-a2)) 100%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.06), 0 1px 2px rgba(0,0,0,.40), 0 10px 24px -20px rgba(0,0,0,.75);
}

/* The corner light — §TCPRM-BLOOM's geometry unchanged: 260×230 centred at
   `calc(100% + 32px) -60px`, so what lands on the card is the FALLOFF rather
   than a circle drawn on it. `z-index:-1` works because the card carries
   `isolation:isolate`: a negative descendant paints above the element's own
   background and below its in-flow content, without escaping to the page. */
.v2x.atd .atd-aim::after{
  content:''; position:absolute; inset:0; z-index:-1; pointer-events:none;
  border-radius:inherit;
  background:radial-gradient(260px 230px at calc(100% + 32px) -60px,
    rgba(var(--t-rgb), var(--aim-bloom)) 0%,
    rgba(var(--t-rgb), 0) 72%) no-repeat;
  opacity:.92;
  transform-origin:100% 0;
  transition:opacity .36s ease, transform .52s cubic-bezier(.16,1,.3,1);
}

/* ── The accent bar ───────────────────────────────────────────────────────
   Was a static 4px edge across the top. It is now the reference's bar: 3px,
   transparent → tone → transparent so it reads as light rather than as a
   rule, scaled to nothing at rest and grown from the CENTRE on hover.
   `transform` is on the span rather than `background-size` on the card
   because the card's `background-image` is already carrying the wash. */
.v2x.atd .atd-aim-edge{
  position:absolute; inset-inline:0; top:0; height:3px; z-index:1;
  background:linear-gradient(90deg,
    rgba(var(--t-rgb), 0) 0%, rgba(var(--t-rgb), .85) 50%, rgba(var(--t-rgb), 0) 100%);
  transform:scaleX(0); transform-origin:50% 0;
  transition:transform .32s cubic-bezier(.22,.61,.36,1);
}

/* ── Flag ─────────────────────────────────────────────────────────────────
   Amber on every card, exactly as the reference does it: the badge marks a
   property of the MODEL, so keying it to the card's rotating hue would make
   the same status look like five different things down a row. */
.v2x.atd .atd-aim-flag{
  position:absolute; top:12px; inset-inline-end:12px; z-index:2;
  padding:3px 9px; border-radius:var(--r-pill);
  background:#FEF4E4; color:#A85B08; box-shadow:inset 0 0 0 1px #FBE3C0;
  font-family:var(--font); font-size:.6rem; font-weight:800;
  letter-spacing:.07em; text-transform:uppercase; white-space:nowrap;
}
.v2x.atd .atd-aim-flag.is-new{ background:#E6F8F1; color:#08795A; box-shadow:inset 0 0 0 1px #C6EEDF; }
body.theme-dark .v2x.atd .atd-aim-flag{ background:rgba(245,158,11,.20); color:#FBC97A; box-shadow:inset 0 0 0 1px rgba(251,191,36,.32); }
body.theme-dark .v2x.atd .atd-aim-flag.is-new{ background:rgba(16,185,129,.18); color:#6EE7BE; box-shadow:inset 0 0 0 1px rgba(52,211,153,.30); }

/* ── Identity ─────────────────────────────────────────────────────────────
   The logo is a TINTED plate now, not a white chip — `--t-bg` is the same
   tint the rank chip and the category pill use on the listing card, so the
   tile agrees with the button below it instead of floating free of the tone.
   `74%` on the image is the reference's inset; it replaces the old 7px pad,
   which does not scale with the tile. */
.v2x.atd .atd-aim-logo{
  width:60px; height:60px; border-radius:18px; margin-bottom:12px; flex:0 0 auto;
  display:grid; place-items:center; overflow:hidden;
  background:var(--t-bg); color:var(--t-ink);
  font-family:var(--font); font-weight:800; font-size:1.5rem; line-height:1;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.5);
  transition:transform .28s cubic-bezier(.22,.61,.36,1), box-shadow .24s ease;
}
.v2x.atd .atd-aim-logo img{ width:74%; height:74%; object-fit:contain; display:block; }
body.theme-dark .v2x.atd .atd-aim-logo{ box-shadow:inset 0 0 0 1px rgba(255,255,255,.06); }

/* A one-line name is the case; `min-height` reserves that one line so every
   card in the row starts its vendor line at the same y. A two-line name is
   allowed to take the second line and make its own card taller — the grid
   equalises the row and the CTA is floor-pinned, so nothing drifts. */
.v2x.atd .atd-aim-name{
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
  overflow:hidden; max-width:100%; min-height:21px;
  font-family:var(--font); font-size:15.5px; font-weight:760;
  line-height:1.35; letter-spacing:-.016em; color:var(--ink);
  overflow-wrap:anywhere; transition:color .2s ease;
}
/* The vendor line in the card's own hue — the strongest cue that the row is a
   set of differently-coloured cards rather than copies of one. */
.v2x.atd .atd-aim-by{
  display:block; max-width:100%; margin-top:7px; min-height:17px;
  font-family:var(--font); font-size:12px; font-weight:640; line-height:1.4;
  color:var(--t-ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
/* Two lines, clamped, with the two lines RESERVED — a one-line tagline beside
   a two-line one would otherwise lift its whole card's facts row. */
.v2x.atd .atd-aim-desc{
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
  overflow:hidden; max-width:100%;
  margin-top:10px; margin-bottom:12px; min-height:calc(2 * 1.55em);
  font-size:12.5px; line-height:1.55; color:var(--muted);
  overflow-wrap:anywhere;
}

/* ── Facts ────────────────────────────────────────────────────────────────
   ⚠️ THE GAP ABOVE THE CTA IS A `margin-bottom` HERE, NOT A `margin-top` ON
   THE BUTTON. `.atd-aim-go` is floor-pinned with `margin-top:auto`, and a
   sibling rule of the form `.atd-aim-facts + .atd-aim-go{ margin-top:14px }`
   would out-rank that pin and dump the leftover height BELOW the button — the
   exact defect [[card-footer-margin-auto-trap]] records on `.dir-tc`, where
   it read as stretched cards rather than as a sizing bug. Separation lives on
   the element above; position lives on the button. They never share a
   property. The same reason `.atd-aim-desc` carries its own margin-bottom:
   a card with no facts row still needs a floor gap. */
.v2x.atd .atd-aim-facts{
  display:flex; align-items:center; justify-content:center; flex-wrap:wrap;
  gap:8px; margin-top:0; margin-bottom:14px;
}
.v2x.atd .atd-aim-rate{ display:inline-flex; align-items:center; gap:4px; font-size:12px; font-weight:640; color:var(--muted); }
.v2x.atd .atd-aim-rate svg{ color:var(--gold); flex:0 0 auto; filter:drop-shadow(0 1px 2px rgba(245,158,11,.25)); }
body.theme-dark .v2x.atd .atd-aim-rate svg{ filter:drop-shadow(0 1px 0 rgba(0,0,0,.45)); }
.v2x.atd .atd-aim-rate strong{ font-weight:780; color:var(--ink); letter-spacing:-.005em; font-variant-numeric:tabular-nums; }
.v2x.atd .atd-aim-rate small{ font-size:11px; font-weight:600; color:var(--muted2); font-variant-numeric:tabular-nums; }
/* The pill is keyed to the PRICING, not to the card — "Freemium" has to mean
   the same thing on every card in the row. The hairline is an inset shadow
   rather than a border so the pill's box height does not change with it. */
.v2x.atd .atd-aim-price{
  display:inline-flex; align-items:center; padding:3px 9px; border-radius:var(--r-pill);
  font-family:var(--font); font-size:10.5px; font-weight:720; line-height:1.5;
  letter-spacing:.01em; white-space:nowrap;
}
.v2x.atd .atd-aim-price.is-free{ background:#E6F8F1; color:#08795A; box-shadow:inset 0 0 0 1px #C6EEDF; }
.v2x.atd .atd-aim-price.is-freemium{ background:#FEF4E4; color:#A85B08; box-shadow:inset 0 0 0 1px #FBE3C0; }
.v2x.atd .atd-aim-price.is-paid{ background:#FEECEF; color:#B31D3C; box-shadow:inset 0 0 0 1px #FBD2DA; }
body.theme-dark .v2x.atd .atd-aim-price.is-free{ background:rgba(16,185,129,.18); color:#6EE7BE; box-shadow:inset 0 0 0 1px rgba(52,211,153,.30); }
body.theme-dark .v2x.atd .atd-aim-price.is-freemium{ background:rgba(245,158,11,.20); color:#FBC97A; box-shadow:inset 0 0 0 1px rgba(251,191,36,.32); }
body.theme-dark .v2x.atd .atd-aim-price.is-paid{ background:rgba(244,63,94,.18); color:#FB9BB0; box-shadow:inset 0 0 0 1px rgba(251,113,133,.30); }

/* ── CTA ──────────────────────────────────────────────────────────────────
   The reference's fill: a flat tone with a 160deg sheen laid over it, which
   brightens on hover by widening the sheen rather than by changing the hue —
   so the measured contrast of the label never moves. */
.v2x.atd .atd-aim-go{
  margin-top:auto; width:100%;
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  padding:11px 14px; border-radius:13px;
  background-color:var(--t-btn);
  background-image:linear-gradient(160deg, rgba(255,255,255,.20) 0%, rgba(255,255,255,0) 58%);
  color:#fff;
  font-family:var(--font); font-size:13px; font-weight:720; letter-spacing:-.006em;
  box-shadow:0 8px 18px -10px var(--t-btn);
  transition:background-image .2s ease, box-shadow .22s ease, gap .2s ease, transform .2s cubic-bezier(.22,.61,.36,1);
}
.v2x.atd .atd-aim-go svg{ flex:0 0 auto; width:14px; height:14px; color:#fff; transition:transform .22s cubic-bezier(.22,.61,.36,1); }
body.theme-dark .v2x.atd .atd-aim-go{
  background-image:linear-gradient(160deg, rgba(255,255,255,.20) 0%, rgba(255,255,255,0) 58%);
  box-shadow:0 8px 18px -12px rgba(0,0,0,.90);
}

/* ── Hover. The whole card is one link, so it lifts — and the CTA answers
      with it rather than needing its own pointer target. ─────────────── */
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-aim:hover{
    transform:translateY(-6px);
    border-color:rgba(var(--t-rgb), .46);
    box-shadow:0 26px 46px -30px rgba(var(--t-rgb), .90), 0 8px 18px -10px rgba(16,24,40,.08);
    color:var(--ink); text-decoration:none;
  }
  body.theme-dark .v2x.atd .atd-aim:hover{
    border-color:rgba(var(--t-rgb), .56);
    box-shadow:0 26px 46px -30px rgba(0,0,0,.88), 0 8px 18px -10px rgba(0,0,0,.50);
  }
  .v2x.atd .atd-aim:hover .atd-aim-edge{ transform:scaleX(1); }
  .v2x.atd .atd-aim:hover::after{ opacity:1; transform:scale(1.14); }
  .v2x.atd .atd-aim:hover .atd-aim-name{ color:var(--t-ink); }
  .v2x.atd .atd-aim:hover .atd-aim-logo{ transform:translateY(-2px) scale(1.06); box-shadow:inset 0 0 0 1px rgba(var(--t-rgb), .55); }
  .v2x.atd .atd-aim:hover .atd-aim-go{
    gap:10px; transform:translateY(-1px);
    background-image:linear-gradient(160deg, rgba(255,255,255,.34) 0%, rgba(255,255,255,.04) 62%);
    box-shadow:0 14px 26px -10px var(--t-btn);
  }
  body.theme-dark .v2x.atd .atd-aim:hover .atd-aim-go{
    background-image:linear-gradient(160deg, rgba(255,255,255,.30) 0%, rgba(255,255,255,.04) 62%);
    box-shadow:0 14px 26px -12px rgba(0,0,0,.95);
  }
  .v2x.atd .atd-aim:hover .atd-aim-go svg{ transform:translateX(3px); }
}
.v2x.atd .atd-aim:focus-visible{ outline:none; box-shadow:0 0 0 3px rgba(var(--t-rgb),.42); }
.v2x.atd .atd-aim:focus-visible .atd-aim-edge{ transform:scaleX(1); }
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-aim,
  .v2x.atd .atd-aim-edge,
  .v2x.atd .atd-aim-logo,
  .v2x.atd .atd-aim-go,
  .v2x.atd .atd-aim-go svg,
  .v2x.atd .atd-aim::after{ transition:none !important; }
  .v2x.atd .atd-aim:hover{ transform:none; }
  .v2x.atd .atd-aim:hover::after{ transform:none; }
  .v2x.atd .atd-aim:hover .atd-aim-logo,
  .v2x.atd .atd-aim:hover .atd-aim-go,
  .v2x.atd .atd-aim:hover .atd-aim-go svg{ transform:none; }
}

/* ── Responsive ───────────────────────────────────────────────────────────
   Below the tablet break every explicit column count and every cap is handed
   back to `auto-fit`: a 176px floor puts two cards across a phone-width
   column and collapses to one on its own under ~370px, which is the same
   cascade `.dir-tc` runs.

   ⚠️ THE `[data-count]` SELECTOR HAS TO BE THE BARE ATTRIBUTE, not a list of
   the values. The ladder above names eight of them, and a list here would
   silently miss whichever one is added next — the new count would keep its
   desktop `max-width` on a phone and strand a single card at two-thirds of
   the column with the section head running full bleed above it. Matching on
   the attribute alone covers every value that exists and every value that
   ever will, at (0,4,0), which ties the ladder and wins on document order. */
@media (max-width:767.98px){
  .v2x.atd .atd-aims,
  .v2x.atd .atd-aims[data-count]{
    grid-template-columns:repeat(auto-fit, minmax(min(100%, 176px), 1fr));
    max-width:none; gap:12px;
  }
}
@media (max-width:575.98px){
  .v2x.atd .atd-aim{ padding:32px 12px 14px; border-radius:15px; }
  .v2x.atd .atd-aim-logo{ width:52px; height:52px; border-radius:15px; font-size:1.3rem; }
  .v2x.atd .atd-aim-name{ font-size:14.5px; }
  .v2x.atd .atd-aim-go{ padding:10px 12px; border-radius:11px; }
  /* The flag would otherwise sit over a long model name at this width. */
  .v2x.atd .atd-aim-flag{ top:10px; inset-inline-end:10px; font-size:.56rem; padding:3px 7px; }
}

/* ── The orbit ring ───────────────────────────────────────────────────────
   Unchanged from the previous design apart from the radius, which follows the
   card's. `overflow:hidden` clips anything hung outside the card, so the ring
   sits ON the padding edge at inset:0 — the same fix §SIDEBAR-ORBIT needed
   for the claim card. */
@supports ((-webkit-mask-composite:xor) or (mask-composite:exclude)){
  .v2x.atd .atd-aim::before{
    content:""; position:absolute; pointer-events:none;
    inset:0; z-index:3; border-radius:17px; padding:1.5px;
    --atd-spin:0deg;
    background:conic-gradient(from var(--atd-spin),
      rgba(var(--t-rgb), 0)              0deg,
      rgba(var(--t-rgb), var(--t-a1))   30deg,
      rgba(255,255,255, 1)              52deg,
      rgba(var(--t-rgb), var(--t-a2))   74deg,
      rgba(var(--t-rgb), 0)            118deg,
      rgba(var(--t-rgb), 0)            180deg,
      rgba(var(--t-rgb), var(--t-a1))  210deg,
      rgba(255,255,255, 1)             232deg,
      rgba(var(--t-rgb), var(--t-a2))  254deg,
      rgba(var(--t-rgb), 0)            298deg,
      rgba(var(--t-rgb), 0)            360deg);
    -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite:xor;
            mask-composite:exclude;
    opacity:0; transition:opacity .32s ease;
    animation:atd-orbit 5.4s linear infinite; animation-play-state:paused;
  }
  .v2x.atd .atd-aim{ --t-a1:.55; --t-a2:.92; }
  body.theme-dark .v2x.atd .atd-aim{ --t-a1:.68; --t-a2:1; }
  .v2x.atd .atd-aim:focus-visible::before{ opacity:1; animation-play-state:running; }
  @media (hover:hover) and (pointer:fine){
    .v2x.atd .atd-aim:hover::before{ opacity:1; animation-play-state:running; }
  }
  @media (hover:none){
    .v2x.atd .atd-aim:active::before{ opacity:1; animation-play-state:running; }
  }
  @media (prefers-reduced-motion:reduce){
    .v2x.atd .atd-aim::before{ --atd-spin:135deg; animation:none !important; }
  }
  @media (max-width:575.98px){
    .v2x.atd .atd-aim::before{ border-radius:14px; }
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   §ABOUT + §LF) The prose sections — capability strip and editorial blocks.

   Both are long-read surfaces, so the rule is the opposite of the card
   sections: nothing here competes with the text. The tone appears only in the
   heading tile, the list markers and the strip's plates.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── The capability strip ─────────────────────────────────────────────────
   `repeat(6,1fr)` used to force six columns at every width: "Web Search &
   Live Answers" wrapped to two lines beside single-word neighbours and the
   row came out ragged, and below ~900px each cell was too narrow for its own
   label. auto-fit lets it settle at 6 / 3 / 2 and keeps every label whole. */
.v2x.atd .atd-caps{
  list-style:none; margin:26px 0 0; padding:22px 0 0;
  border-top:1px solid var(--line);
  display:grid; gap:10px;
  grid-template-columns:repeat(auto-fit, minmax(min(100%,138px),1fr));
}
.v2x.atd .atd-cap{
  position:relative; isolation:isolate;
  display:flex; flex-direction:column; align-items:center; text-align:center;
  gap:9px; padding:14px 10px; border-radius:14px;
}
/* These are not links, so the hover is a reading highlight — no lift. The old
   strip lifted its icon on hover while doing nothing, which is the dead
   affordance §SIDEBAR-FIX had to take off `.atd-plat`. */
.v2x.atd .atd-cap::before{
  content:""; position:absolute; inset:0; z-index:-1; border-radius:inherit;
  background:linear-gradient(180deg, rgba(var(--t-rgb),.13), rgba(var(--t-rgb),.05));
  opacity:0; transition:opacity .28s ease;
}
.v2x.atd .atd-cap .ic{
  width:46px; height:46px; border-radius:14px; flex:0 0 auto;
  display:flex; align-items:center; justify-content:center;
  background:linear-gradient(135deg, var(--t-1p), var(--t-2)); color:#fff;
  box-shadow:0 4px 12px rgba(var(--t-rgb),.30);
  transition:transform 380ms cubic-bezier(.16,1,.3,1), box-shadow 300ms ease;
}
.v2x.atd .atd-cap .ic img{ width:19px; height:19px; object-fit:contain; }
.v2x.atd .atd-cap .lb{
  font-family:var(--font); font-size:.85rem; font-weight:700; line-height:1.35;
  color:var(--ink); overflow-wrap:anywhere;
}
.v2x.atd .atd-cap .gp{
  font-size:.7rem; font-weight:600; line-height:1.3; color:var(--muted);
  overflow-wrap:anywhere;
}
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-cap:hover::before{ opacity:1; }
  .v2x.atd .atd-cap:hover .ic{ transform:scale(1.07) rotate(-4deg); box-shadow:0 6px 16px rgba(var(--t-rgb),.42); }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-cap::before,.v2x.atd .atd-cap .ic{ transition:none !important; }
  .v2x.atd .atd-cap:hover .ic{ transform:none; }
}
@media (max-width:575.98px){
  .v2x.atd .atd-caps{ grid-template-columns:repeat(auto-fit, minmax(min(100%,118px),1fr)); gap:8px; }
  .v2x.atd .atd-cap{ padding:12px 7px; gap:8px; }
  .v2x.atd .atd-cap .ic{ width:40px; height:40px; border-radius:12px; }
  .v2x.atd .atd-cap .lb{ font-size:.8rem; }
}

/* ── Per-block heading tile ───────────────────────────────────────────────
   §SPINE-BLUE turns the heading's first <svg> into a gradient tile, hard-coded
   brand blue at (0,4,1)+1 element. These blocks each carry their own hue, so
   the override names the block class as well — (0,5,1) — and wins outright
   rather than by document order. */
.v2x.atd .col-lg-8 > .v2-card.atd-lf .v2-section-title > svg:first-child{
  background:linear-gradient(135deg, var(--t-1p), var(--t-2));
  box-shadow:0 4px 12px rgba(var(--t-rgb),.30);
}
@media (hover:hover) and (pointer:fine){
  .v2x.atd .col-lg-8 > .v2-card.atd-lf:hover .v2-section-title > svg:first-child{
    box-shadow:0 6px 16px rgba(var(--t-rgb),.42);
  }
  /* The card's own wash and edge follow the block's hue too, so the three
     blocks read as three chapters rather than three copies. */
  .v2x.atd .col-lg-8 > .v2-card.atd-lf:hover{
    border-color:rgba(var(--t-rgb),.34);
    box-shadow:0 2px 6px rgba(16,24,40,.06), 0 18px 44px -14px rgba(var(--t-rgb),.24);
  }
  body.theme-dark .v2x.atd .col-lg-8 > .v2-card.atd-lf:hover{
    border-color:rgba(var(--t-rgb),.46);
    box-shadow:0 2px 6px rgba(0,0,0,.50), 0 18px 44px -14px rgba(0,0,0,.55);
  }
}
/* A tone hairline along the top edge — the same device §HERO-BLUE uses, at
   block scale, and the only place the hue touches the reading column. */
.v2x.atd .col-lg-8 > .v2-card.atd-lf{
  background-image:
    linear-gradient(90deg,
      rgba(var(--t-rgb),0)   0%,
      rgba(var(--t-rgb),.55) 22%,
      var(--t-dot1) 50%,
      rgba(var(--t-rgb),.55) 78%,
      rgba(var(--t-rgb),0)  100%),
    linear-gradient(150deg,
      rgba(var(--t-rgb),.055) 0%,
      rgba(var(--t-rgb),0)   46%,
      rgba(var(--t-rgb),.04) 100%);
  background-repeat:no-repeat;
  background-size:100% 2px, auto;
  background-position:0 0, 0 0;
  background-color:#fff;
  border-color:rgba(var(--t-rgb),.17);
}
body.theme-dark .v2x.atd .col-lg-8 > .v2-card.atd-lf{
  background-image:
    linear-gradient(90deg,
      rgba(var(--t-rgb),0)   0%,
      rgba(var(--t-rgb),.50) 22%,
      rgba(var(--t-rgb),.95) 50%,
      rgba(var(--t-rgb),.50) 78%,
      rgba(var(--t-rgb),0)  100%),
    linear-gradient(150deg,
      rgba(var(--t-rgb),.10) 0%,
      rgba(var(--t-rgb),0)  46%,
      rgba(var(--t-rgb),.07) 100%);
  background-repeat:no-repeat;
  background-size:100% 2px, auto;
  background-position:0 0, 0 0;
  background-color:var(--dk-surface-2,#17171B);
  border-color:rgba(var(--t-rgb),.26);
}
/* The corner bloom and the orbit ring follow the block's hue as well —
   §SPINE-BLUE and §SIDEBAR-ORBIT both hard-code brand blue for the column. */
.v2x.atd .col-lg-8 > .v2-card.atd-lf::after{
  background:radial-gradient(280px 280px at calc(100% + 40px) -60px,
    rgba(var(--t-rgb),.20) 0%, rgba(var(--t-rgb),0) 70%) no-repeat;
}
body.theme-dark .v2x.atd .col-lg-8 > .v2-card.atd-lf::after{
  background:radial-gradient(280px 280px at calc(100% + 40px) -60px,
    rgba(var(--t-rgb),.17) 0%, rgba(var(--t-rgb),0) 70%) no-repeat;
}

/* ── Lists inside the reading column ──────────────────────────────────────
   The stored HTML is 350 <li> across the four prose columns, almost all of
   them opening with a bold lead-in. The browser's default disc sat at the
   text's own colour and size; a tone marker separates the lead-in from the
   run of body copy without touching the measure.

   Scoped to `.v2x.atd`, so the six other V2 pages that render `.v2-rich` are
   untouched. */
.v2x.atd .v2-rich ul{ list-style:none; padding-inline-start:0; }
.v2x.atd .v2-rich ul > li{
  position:relative; padding-inline-start:26px; margin-bottom:.72rem;
}
.v2x.atd .v2-rich ul > li::before{
  content:""; position:absolute; inset-inline-start:2px; top:.62em;
  width:8px; height:8px; border-radius:3px;
  background:linear-gradient(135deg, var(--t-dot1, #4A8BF0), var(--t-2, #2060C0));
  box-shadow:0 1px 4px rgba(var(--t-rgb,54,128,237),.34);
}
.v2x.atd .v2-rich ol{ padding-inline-start:1.35rem; }
.v2x.atd .v2-rich ol > li{ margin-bottom:.72rem; }
.v2x.atd .v2-rich ol > li::marker{ color:var(--t-ink, var(--accent-dark)); font-weight:700; }
/* The bold lead-in is the list's real structure — it gets the ink, and the
   sentence after it stays body colour. */
.v2x.atd .v2-rich li > strong:first-child{ color:var(--ink); font-weight:700; letter-spacing:-.005em; }
.v2x.atd .v2-rich em{ color:var(--ink); font-style:italic; }
.v2x.atd .v2-rich code{
  font-family:var(--mono); font-size:.9em; padding:2px 6px; border-radius:6px;
  background:var(--accent-soft); color:var(--accent-dark);
}
body.theme-dark .v2x.atd .v2-rich code{ background:rgba(54,128,237,.18); color:#9DC8FF; }
@media (max-width:575.98px){
  .v2x.atd .v2-rich ul > li{ padding-inline-start:22px; }
  .v2x.atd .v2-rich ul > li::before{ top:.58em; width:7px; height:7px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   §HERO-X) Hero LEFT column — the premium pass over §HERO-PRO.

   Scope was agreed before any code: the LEFT column only. The section rail
   below the hero is untouched (two redesigns of it were reverted on
   2026-08-13 and its width behaviour is not up for grabs), and so is the
   gallery in the right column.

   Appended at the very end because it has to out-cascade §HERO-PRO, §HERO-BLUE
   and the dark-mode surface list — same reason those two are where they are.
   The SHELL is not touched: the diagonal wash, top hairline, corner bloom and
   orbit ring are §HERO-BLUE's and they already read the way they should.

   Three things carry the pass:

   · THE STAT RAIL WAS THREE BOXES; IT IS NOW ONE INSTRUMENT. Three separate
     cards with their own borders read as a form, and at 600px they were three
     grey rectangles competing with the CTA row directly beneath them. They are
     now cells of a single inset surface, divided by hairlines that are the
     container's own background showing through a 1px grid gap — which means
     the dividers are correct for ANY wrap configuration without a single
     nth-child rule.
   · THE CHIPS LOSE THE PLATE. A white circle inside a pale tint is a hole in
     the middle of the pill; four of them made the row read as four badges
     rather than one capability line. The glyph now sits inline in the hue's
     own ink — the SAME ink-on-tint pair the label already uses, so the ramp
     stays measured and nothing needed re-toning.
   · THE ORBIT REACHES THE HERO'S OWN CONTROLS. The logo plate, the secondary
     button and the upvote pick up the page's rotating comet on hover. The
     primary keeps its sheen instead — two travelling lights on one button is
     noise, and the sheen is what the primary already answered with.

   PALETTE IS BLUE, DELIBERATELY. The violet was removed from this hero on
   request so the page reads as one blue system; amber appears only where it
   is semantic — the rating cell, which carries amber stars.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 1 · Capability chips ──────────────────────────────────────────────── */
/* The `!important` is inherited from §HERO-PRO's own war with the FEEDBACK-PASS
   block further up; matching it here is what makes these land. */
.v2x.atd .atd-chip{
  padding:7px 15px !important; gap:7px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.7) !important;
}
/* The span STAYS — a (0,5,0) rule above uses it to defend the glyph from a
   `color:#fff !important` that would otherwise paint it white on the tint.
   Only its plate is removed. */
.v2x.atd .atd-chip-ic{
  width:auto; height:auto; border-radius:0;
  background:transparent; box-shadow:none;
  transition:transform .38s cubic-bezier(.16,1,.3,1);
}
body.theme-dark .v2x.atd .atd-chip{ box-shadow:inset 0 1px 0 rgba(255,255,255,.06) !important; }
body.theme-dark .v2x.atd .atd-chip-ic{ background:transparent; box-shadow:none; }
@media (hover:hover) and (pointer:fine){
  /* No plate left to spin, so the glyph nudges instead of rotating. */
  .v2x.atd .atd-chip:hover .atd-chip-ic{
    background:transparent; box-shadow:none; transform:translateX(-1px) scale(1.12);
  }
  body.theme-dark .v2x.atd .atd-chip:hover .atd-chip-ic{ background:transparent; }
}

/* ══════════════════════════════════════════════════════════════════════════
   §SPECRAIL) Hero stat rail — the one-line spec strip. Static.

   THREE DESIGNS HAVE BEEN REJECTED HERE. Read this before adding anything to
   the rail; every one of them was removed for taking more than three small
   facts earn.
     1. The inset instrument — a bordered container, three `1fr` cells edge to
        edge, hairline gaps, stretched across the full ~850px column.
        → "dont want big box design" (2026-08-17).
     2. The frameless cluster — right idea, wrong height: the figure sat OVER
        its caption in a two-row cell, a ~28px number with a 25px icon
        medallion under it, 103px of hero all in.
        → "taking too much space … make it simple and premium" (same day).
     3. The hover plate — a rounded, bordered panel that materialised under the
        cell you were on, with a lift, a sheen pass, an accent bar and a
        staggered star lift.
        → "remove hover effects and rounded effect" (same day).

   WHAT IT IS NOW. Type on the hero, and nothing else:

       4.8 ★★★★★ RATING │ 2K ▢ REVIEWS │ 40.8K+ ◉ VISITS

   Figure, stars and caption on one row per cell; columns sized to their own
   content (`grid-auto-flow:column` + `grid-auto-columns:minmax(0,max-content)`)
   so the strip is exactly as wide as its data; a faded hairline between cells.
   No container surface, no cell surface, no radius, no hover state, no
   transition — there is nothing left to reveal, so nothing responds to a
   pointer. ~28px tall.

   TWO THINGS THE ONE-LINE FOLD DELETED, both still correct:
     · THE ICON PLATES. A 25px tinted medallion is a button-sized object next
       to an 11px caption; inline at 14px in the cell's own accent it is a
       bullet, which is all a caption glyph should be.
     · THE RATING CELL'S STAR GLYPH (`.is-rating .lcd`, display:none). One gold
       star immediately after five gold stars is a stutter. The other two
       captions KEEP their glyph on purpose — the stars are the rating cell's
       colour, and without those two the strip is one gold burst and then grey.

   Colour is still one hook per cell (`--sc-ink`), so `.is-rating` moves to
   §GOLD and dark mode re-points the same token rather than restating rules.

   PHONES KEEP THE TWO-ROW CELL (see §4). The strip needs ~350px and a 320px
   card has 286 — below 576px the cell folds back to figure-over-caption in
   three columns, which is the same ~50px tall and stays balanced.
   ══════════════════════════════════════════════════════════════════════════ */

.v2x.atd .atd-statrail{
  --sc-px:16px;   /* cell inline padding — the rail's negative margin reads this */
  --sc-py:5px;

  display:grid;
  grid-auto-flow:column;
  grid-auto-columns:minmax(0,max-content);  /* hugs the data; shrinks before it clips */
  grid-template-columns:none;
  justify-content:start;
  align-items:stretch;
  gap:0;
  margin:0 0 20px;
  /* Pulls the first figure back to the text column's edge, so the strip lines
     up with the description and chips above it at every width. */
  margin-inline:calc(-1 * var(--sc-px));
  /* The old container surface, retired — border, radius, hairline background,
     inset highlight and the clip that rounded the corner cells. */
  background:none; border:0; border-radius:0; box-shadow:none; overflow:visible;
}
/* `.is-N` sized the old explicit grid. Auto-flow does that job now, and the
   one/two-cell listings no longer need a cap to stop a lone cell stretching. */
.v2x.atd .atd-statrail.is-1,
.v2x.atd .atd-statrail.is-2,
.v2x.atd .atd-statrail.is-3,
.v2x.atd .atd-statrail.is-4,
.v2x.atd .atd-statrail.is-5{ grid-template-columns:none; max-width:none; }
body.theme-dark .v2x.atd .atd-statrail{
  background:none; border-color:transparent; box-shadow:none;
}

/* ── The cell ──────────────────────────────────────────────────────────── */
.v2x.atd .atd-stat{
  --sc-ink:#1D5CBE;   /* the caption glyph, and the only colour hook left */

  position:relative;  /* the divider ::before is positioned against this */
  min-width:0;
  display:flex; flex-direction:row; align-items:center; gap:8px;
  padding:var(--sc-py) var(--sc-px);
  /* Every surface property is stated, not merely omitted: the two older stat
     rail blocks above still set a border, a radius, a gradient and a shadow on
     this selector and would otherwise win nothing back but paint them. */
  border:0; border-radius:0; background:none; box-shadow:none; overflow:visible;
  transform:none; transition:none;
}
/* Gold where gold is meaningful — this is the cell the stars sit in, and the
   amber is §GOLD's, the same one the glyphs use. The amber CHIP/BADGE family
   keeps its own burnt orange on purpose: those mean "featured", not "rating". */
.v2x.atd .atd-stat.is-rating{ --sc-ink:var(--gold-deep); }
body.theme-dark .v2x.atd .atd-stat{
  --sc-ink:#8FBEFA;
  border:0; background:none; box-shadow:none;
}
/* (0,5,1) — it has to out-rank the dark base above, which is (0,4,1) and would
   otherwise repaint the rating glyph blue. */
body.theme-dark .v2x.atd .atd-stat.is-rating{ --sc-ink:#F7C46A; }

/* ── Divider. The old ::before was a bottom accent bar; it is killed outright
      rather than re-pointed, so the ONLY ::before on this component is the
      sibling rule below and no first cell can inherit a stray bar. ───────── */
.v2x.atd .atd-stat::before{ content:none; }
.v2x.atd .atd-stat + .atd-stat::before{
  content:""; position:absolute; z-index:0; pointer-events:none;
  inset-inline-start:0; inset-inline-end:auto;
  top:18%; bottom:18%; width:1px; height:auto;
  /* Faded at both ends: a full-height rule reads as a table border, which is
     the box this component exists to not be. */
  background:linear-gradient(180deg,
    rgba(122,132,155,0)  0%,
    var(--line-strong)  30%,
    var(--line-strong)  70%,
    rgba(122,132,155,0) 100%);
  transform:none; transform-origin:50% 50%; opacity:1; transition:none;
}
/* The hover plate and the underline sweep lived on these two. Both are killed
   here rather than deleted, because the earlier blocks in this file still
   declare them and a missing rule is not the same as an overriding one. */
.v2x.atd .atd-stat::after,
.v2x.atd .atd-stat-top::after{ content:none; }

/* ── The row ───────────────────────────────────────────────────────────── */
.v2x.atd .atd-stat-top{
  position:static; min-width:0;
  display:flex; align-items:center; flex-wrap:nowrap; gap:7px;
  min-height:0; padding-bottom:0;
}
.v2x.atd .atd-stat-val{
  font-size:1.12rem; font-weight:800; letter-spacing:-.025em; line-height:1;
  color:var(--ink); white-space:nowrap;
  /* CountUp rewrites this node every frame on load; tabular figures stop the
     rating ticking 4.1 → 4.8 from resizing the row under the animation. */
  font-variant-numeric:tabular-nums lining-nums;
  transform:none; transition:none;
}
.v2x.atd .atd-stat .v2-stars{
  font-size:.66rem; letter-spacing:1.4px; line-height:1;
  color:var(--gold); white-space:nowrap;
}
.v2x.atd .atd-stat .v2-stars i{ display:inline-block; transform:none; transition:none; }

/* ── Caption ───────────────────────────────────────────────────────────── */
.v2x.atd .atd-stat-lbl{
  display:inline-flex; align-items:center; gap:6px;
  margin-top:0; min-width:0;
  font-size:.68rem; font-weight:700; letter-spacing:.08em; text-transform:uppercase;
  color:var(--muted);
  transition:none;
}
/* The caption glyph — a bullet, not a badge. The selector is deliberately
   (0,6,0): `body.theme-dark .v2x.atd .atd-stat-lbl .lcd` further up is (0,5,1)
   and would otherwise repaint it its old flat blue in dark mode. */
.v2x.atd .atd-statrail .atd-stat .atd-stat-lbl .lcd{
  box-sizing:border-box;
  width:14px; height:14px; flex:none;
  padding:0; border-radius:0; background:none; box-shadow:none;
  color:var(--sc-ink);
  transform:none; transition:none;
}
/* Five gold stars then a sixth gold star is a stutter — see the header note. */
.v2x.atd .atd-statrail .atd-stat.is-rating .atd-stat-lbl .lcd{ display:none; }

/* ── No hover state. Every hover rule the earlier blocks in this file still
      declare on the rail is cancelled here, at a specificity that beats them
      — a lift, a blue drop shadow, a background wash and a corner glow are all
      still sitting above §HERO-PRO and FEEDBACK-PASS waiting to fire. ────── */
.v2x.atd .atd-stat:hover{
  transform:none; box-shadow:none; background:none;
  border-color:transparent; border-radius:0;
}
.v2x.atd .atd-stat:hover::before,
.v2x.atd .atd-stat:hover + .atd-stat::before{ opacity:1; }
.v2x.atd .atd-stat:hover .atd-stat-val,
.v2x.atd .atd-stat:hover .v2-stars i,
.v2x.atd .atd-statrail .atd-stat:hover .atd-stat-lbl .lcd{ transform:none; }
.v2x.atd .atd-stat:hover .atd-stat-lbl{ color:var(--muted); }
.v2x.atd .atd-statrail .atd-stat:hover .atd-stat-lbl .lcd{ color:var(--sc-ink); }

/* ── 3 · Copy rhythm ───────────────────────────────────────────────────── */
/* The dark green chip's hover fill takes its own ink to 4.41:1 — the only one
   of the eight chip states under the bar, and it was under it before this pass
   too. Lifting the INK rather than thinning the fill fixes hover (4.75) and
   improves rest (7.47) in one move. */
body.theme-dark .v2x.atd .atd-chip-green{ --c-ink:#71E3A6; }

.v2x.atd .atd-desc{ max-width:66ch; margin-bottom:20px; }
.v2x.atd .atd-chips{ margin-bottom:22px; }

/* ── 4 · Responsive ────────────────────────────────────────────────────── */
/* The strip's ramp is one number per step (--sc-px) plus type; --sc-px is also
   the rail's negative margin, so the first figure stays flush with the copy
   above it at every width and only one number moves per breakpoint. */
@media (max-width:1199.98px){
  .v2x.atd .atd-statrail{ --sc-px:14px; margin-bottom:18px; }
}
@media (max-width:767.98px){
  /* Below lg the hero is a single column (~700px at 768) and the strip needs
     ~350px — it still fits on one line, so only the type steps down. */
  .v2x.atd .atd-statrail{ --sc-px:12px; margin-bottom:16px; }
  .v2x.atd .atd-stat{ gap:7px; }
  .v2x.atd .atd-stat-val{ font-size:1.06rem; }
  .v2x.atd .atd-stat-lbl{ font-size:.65rem; letter-spacing:.06em; gap:5px; }
  .v2x.atd .atd-statrail .atd-stat .atd-stat-lbl .lcd{ width:13px; height:13px; }
  .v2x.atd .atd-stat .v2-stars{ font-size:.62rem; letter-spacing:1.1px; }
}
/* Phones. THE STRIP DOES NOT FIT: a 320px card leaves 286px and one line of
   `4.8 ★★★★★ RATING · 2K ▢ REVIEWS · 40.8K+ ◉ VISITS` measures ~350. The cell
   folds back to figure-over-caption in three equal columns — the same ~50px
   tall as the strip, and balanced rather than wrapped mid-row. The only thing
   the fold costs is the leading hairline on the first cell of each row. */
@media (max-width:575.98px){
  .v2x.atd .atd-statrail{
    --sc-px:10px; --sc-py:4px;
    grid-auto-flow:row;
    justify-content:stretch;
    row-gap:18px;
    margin-bottom:16px;
  }
  /* ⚠️ EVERY `.is-N` is named here on purpose. The base block resets those
     same classes to `grid-template-columns:none` at (0,3,0), and a media query
     adds NO specificity — a plain `.atd-statrail{…}` column rule here is
     (0,2,0) and loses to it, which drops the auto-flow:row grid to a single
     implicit column and stacks the three figures down the phone one per row. */
  .v2x.atd .atd-statrail.is-3,
  .v2x.atd .atd-statrail.is-5{ grid-template-columns:repeat(3,minmax(0,1fr)); }
  .v2x.atd .atd-statrail.is-1{ grid-template-columns:minmax(0,1fr); }
  .v2x.atd .atd-statrail.is-2,
  .v2x.atd .atd-statrail.is-4{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  /* No cell that starts a row may carry a leading hairline, and "starts a row"
     depends on the column count — so each rule is scoped to the variants that
     actually run that count. An unscoped `3n+1` also matches cell 4, which on
     the TWO-column `.is-4` rail (AI-model pages) is the second cell of row 2
     and must keep its divider. */
  .v2x.atd .atd-statrail.is-3 .atd-stat:nth-child(3n+1)::before,
  .v2x.atd .atd-statrail.is-5 .atd-stat:nth-child(3n+1)::before,
  .v2x.atd .atd-statrail.is-1 .atd-stat::before,
  .v2x.atd .atd-statrail.is-2 .atd-stat:nth-child(2n+1)::before,
  .v2x.atd .atd-statrail.is-4 .atd-stat:nth-child(2n+1)::before{ content:none; }

  /* The fold. `margin-top:auto` is what lands every caption on one line even
     when the rating cell wraps its stars under the figure. */
  .v2x.atd .atd-stat{ flex-direction:column; align-items:flex-start; gap:5px; }
  .v2x.atd .atd-stat-top{ flex-wrap:wrap; gap:5px; }
  .v2x.atd .atd-stat-lbl{
    margin-top:auto;
    font-size:.6rem; letter-spacing:.04em; gap:5px; line-height:1.3;
    /* A 320px column leaves ~57px of caption after the glyph and "REVIEWS" is
       ~46 at this size. `anywhere` is the backstop for a longer word an admin
       types into `reviews_suffix` / `visits_suffix`: it breaks onto a second
       line rather than running out of the cell. Nothing is ever clipped. */
    overflow-wrap:anywhere;
  }
  .v2x.atd .atd-stat-val{ font-size:1.14rem; letter-spacing:-.03em; }
  .v2x.atd .atd-statrail .atd-stat .atd-stat-lbl .lcd{ width:13px; height:13px; }
  .v2x.atd .atd-stat .v2-stars{ font-size:.58rem; letter-spacing:.7px; }
  .v2x.atd .atd-chip{ padding:6px 13px !important; }
}
@media (max-width:399.98px){
  .v2x.atd .atd-statrail{ --sc-px:8px; row-gap:16px; }
  .v2x.atd .atd-stat-val{ font-size:1.06rem; }
  .v2x.atd .atd-stat-lbl{ font-size:.57rem; letter-spacing:.03em; gap:4px; }
  .v2x.atd .atd-statrail .atd-stat .atd-stat-lbl .lcd{ width:12px; height:12px; }
  .v2x.atd .atd-stat .v2-stars{ font-size:.55rem; letter-spacing:.5px; }
}

/* ── 5 · Motion preferences ────────────────────────────────────────────── */
/* The stat rail has no transition, transform or hover state left to disable —
   §SPECRAIL sets `transition:none` on every part of it. Only the chips, which
   still animate their glyph, need anything here. */
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-chip-ic{ transition:none !important; }
  .v2x.atd .atd-chip:hover .atd-chip-ic{ transform:none; }
}

/* ── 6 · The orbit, on the hero's own controls ─────────────────────────── */
/* Same recipe as the section rail and the sidebar: a conic gradient the size
   of the box, masked to a ring by two full-box mask layers composited xor.
   The gate is not cosmetic — without mask-composite the two layers UNION and
   the conic paints a solid block over the label. */
@supports ((-webkit-mask-composite:xor) or (mask-composite:exclude)){
  .v2x.atd .atd-logo-plate::after,
  .v2x.atd .atd-cta-row .atd-btn-outline::before,
  .v2x.atd .atd-cta-row .atd-upvote::before{
    content:""; position:absolute; pointer-events:none;
    inset:-1px; z-index:1; padding:1.5px;
    --atd-spin:0deg;
    background:conic-gradient(from var(--atd-spin),
      rgba(54,128,237, 0)     0deg, rgba(54,128,237,.55)  30deg,
      rgba(255,255,255, 1)   52deg, rgba(54,128,237,.92)  74deg,
      rgba(54,128,237, 0)   118deg, rgba(54,128,237, 0)  180deg,
      rgba(54,128,237,.55) 210deg, rgba(255,255,255, 1)  232deg,
      rgba(54,128,237,.92) 254deg, rgba(54,128,237, 0)  298deg,
      rgba(54,128,237, 0)  360deg);
    -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite:xor;
            mask-composite:exclude;
    opacity:0; transition:opacity .32s ease;
    animation:atd-orbit 6s linear infinite; animation-play-state:paused;
  }
  /* The plate's box IS the tile's box — the halo is absolutely positioned and
     takes no layout — so the ring follows the tile's own 24px radius. */
  .v2x.atd .atd-logo-plate::after{ border-radius:25px; animation-duration:5s; }
  .v2x.atd .atd-cta-row .atd-btn-outline{ position:relative; }
  .v2x.atd .atd-cta-row .atd-btn-outline::before{ border-radius:14px; animation-duration:3.2s; }
  .v2x.atd .atd-cta-row .atd-upvote{ position:relative; }
  .v2x.atd .atd-cta-row .atd-upvote::before{ border-radius:14px; animation-duration:3.2s; }
  /* A voted upvote is a filled emerald state; a blue ring on it is a mixed
     signal, so it stands down. */
  .v2x.atd .atd-cta-row .atd-upvote.voted::before{ display:none; }
  .v2x.atd .atd-cta-row .atd-btn-outline:focus-visible::before,
  .v2x.atd .atd-cta-row .atd-upvote:focus-visible::before{ opacity:1; animation-play-state:running; }
  @media (hover:hover) and (pointer:fine){
    .v2x.atd .atd-logo-plate:hover::after,
    .v2x.atd .atd-cta-row .atd-btn-outline:hover::before,
    .v2x.atd .atd-cta-row .atd-upvote:not(.voted):hover::before{ opacity:1; animation-play-state:running; }
  }
  @media (prefers-reduced-motion:reduce){
    .v2x.atd .atd-logo-plate::after,
    .v2x.atd .atd-cta-row .atd-btn-outline::before,
    .v2x.atd .atd-cta-row .atd-upvote::before{ --atd-spin:135deg; animation:none !important; }
  }
  @media (max-width:767.98px){
    .v2x.atd .atd-logo-plate::after{ border-radius:21px; }
  }
  @media (max-width:575.98px){
    .v2x.atd .atd-logo-plate::after{ border-radius:18px; }
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   §CTAX) The closing CTA band — rebuilt on its own class.

   It used to borrow `.v2-cta`, a class the COMPARE page also uses, so every
   change here had to be written as an override of a shared component that
   `.v2x.atd` then re-overrode. It has its own class now and a clean slate; the
   old `.v2x.atd .v2-cta` / `.atd-cta-banner` rules were deleted rather than
   left to rot, and the scroll-reveal selector that pointed at
   `.atd-cta-banner` — a class NOTHING has ever emitted, so the band never
   revealed — now points here.

   ⚠️ THE RAMP IS CAPPED AT #2B70D7, AND THAT IS A CONTRAST DECISION.
   The band used `--grad-brand`, which ends at #60A4F5: white text on that stop
   measures 2.58:1. On a 1400px band the light end is the right third, which is
   where the sub-line reaches on a wide screen and where the WHOLE gradient
   compresses on a phone. #2B70D7 is the lightest blue that still clears 4.5:1
   for white (4.77), so every word on this band passes wherever it lands.

   For the same reason the sub-line is SOLID white, not white at 92%. Fading it
   to separate it from the heading costs contrast (.94 alpha is 4.40:1 — under
   the bar); size and weight separate them for free.
   ══════════════════════════════════════════════════════════════════════════ */
.v2x.atd .atd-ctax{
  position:relative; isolation:isolate; overflow:hidden;
  margin-top:8px; padding:clamp(24px,3vw,38px) clamp(20px,3vw,40px);
  border-radius:22px; border:1px solid rgba(255,255,255,.16);
  background-image:linear-gradient(135deg,#17458F 0%,#1E56AD 54%,#2464C4 100%);
  box-shadow:0 1px 2px rgba(15,23,42,.10), 0 26px 54px -26px rgba(27,82,166,.78);
}
body.theme-dark .v2x.atd .atd-ctax{
  border-color:var(--dk-line-strong,rgba(255,255,255,.16));
  background-image:linear-gradient(135deg,#123A7C 0%,#1A4C9C 54%,#215CB4 100%);
  box-shadow:0 1px 2px rgba(0,0,0,.5), 0 26px 54px -26px rgba(0,0,0,.9);
}
/* The aurora. A real element rather than a pseudo because ::before is the
   orbit's and ::after is the top sheen — and it has to travel on hover, which
   a background layer cannot do. */
.v2x.atd .atd-ctax-aur{
  position:absolute; z-index:0; pointer-events:none;
  width:min(560px,72%); aspect-ratio:1; inset-inline-end:-14%; top:-58%;
  border-radius:50%;
  /* .10, not .20: this is the ONLY white overlay on the band now, and at the
     ramp's lightest stop it still leaves white text at 4.63:1 where the glow
     is brightest. */
  background:radial-gradient(50% 50% at 50% 50%, rgba(255,255,255,.10) 0%, rgba(255,255,255,0) 70%);
  transition:transform .8s cubic-bezier(.16,1,.3,1), opacity .5s ease;
}
/* A lit top edge, the same device the hero and the sidebar cards use. */
.v2x.atd .atd-ctax::after{
  content:""; position:absolute; inset-inline:0; top:0; height:2px; z-index:1; pointer-events:none;
  background:linear-gradient(90deg,
    rgba(255,255,255,0) 0%, rgba(255,255,255,.45) 22%,
    rgba(255,255,255,.85) 50%, rgba(255,255,255,.45) 78%, rgba(255,255,255,0) 100%);
}

/* ── Layout ────────────────────────────────────────────────────────────── */
.v2x.atd .atd-ctax-in{
  position:relative; z-index:2;
  display:flex; align-items:center; justify-content:space-between;
  flex-wrap:wrap; gap:22px 26px;
}
.v2x.atd .atd-ctax-lead{
  display:flex; align-items:center; gap:18px;
  flex:1 1 440px; min-width:0;
}
.v2x.atd .atd-ctax-tx{ min-width:0; }
.v2x.atd .atd-ctax-acts{ display:flex; flex-wrap:wrap; gap:12px; flex:0 0 auto; }

/* ── Logo ──────────────────────────────────────────────────────────────── */
/* White plate in BOTH themes, for the reason the hero tile keeps one: brand
   marks are drawn for a light ground and a dark tile puts a near-black logo on
   a near-black plate. */
.v2x.atd .atd-ctax-logo{
  flex:none; width:62px; height:62px; border-radius:17px;
  display:inline-flex; align-items:center; justify-content:center;
  background:#fff; padding:9px;
  border:1px solid rgba(255,255,255,.55);
  box-shadow:0 1px 2px rgba(15,23,42,.16), 0 14px 26px -14px rgba(0,0,0,.5);
  transition:transform .45s cubic-bezier(.16,1,.3,1), box-shadow .4s ease;
}
.v2x.atd .atd-ctax-logo img{ width:100%; height:100%; object-fit:contain; display:block; }
.v2x.atd .atd-ctax-logo.is-letter{
  font-family:var(--font); font-size:1.6rem; font-weight:800; line-height:1;
  color:#1B52A6; padding:0;
}

/* Paired marks in the closing band — a page about a PAIR, e.g. /compare/{slug}.
   Each member keeps its own .atd-ctax-logo, so the white plate, the real border,
   the :has(img) fill rule and the .is-letter fallback all still apply per tile;
   only the size and the overlap are new. Selectors are (0,3,0) so they outrank
   the breakpoint rules further down that re-set width/height on the base class,
   which is why the duo carries its own phone step rather than inheriting one. */
.v2x.atd .atd-ctax-duo{ flex:none; display:inline-flex; align-items:center; }
/* NO padding here. `.atd-ctax-logo:has(img)` a few hundred lines up sets
   `padding:0; overflow:hidden` because this plate has a REAL 1px border drawn
   outside the content box — the edge survives without the margin, so the
   margin only costs size. Declaring padding at (0,4,0) here out-ranked that
   (0,3,1) rule and put the marks back in white boxes. Size and overlap only. */
.v2x.atd .atd-ctax-duo .atd-ctax-logo{ width:48px; height:48px; border-radius:13px; }
.v2x.atd .atd-ctax-duo .atd-ctax-logo.is-letter{ font-size:1.24rem; padding:0; }
.v2x.atd .atd-ctax-duo > * + *{ margin-left:-11px; }
.v2x.atd .atd-ctax-duo > *:last-child{ z-index:2; }
/* The band-level hover lifts the single plate; the pair splits slightly instead,
   which reads as two marks rather than one wide one. Kept DELIBERATELY small:
   two plates moving together at the single plate's -3px read as one wide slab
   shifting. The shadow steps only from the resting 14/26/.5 to 16/28/.54 —
   the base hover's 20/34/.6 is a lot of weight for a 48px tile, and going the
   other way and landing UNDER the resting value would read as the plate
   sinking into the band rather than lifting off it. */
.v2x.atd .atd-ctax:hover .atd-ctax-duo > *:first-child{ transform:translateY(-2px) translateX(-1px); }
.v2x.atd .atd-ctax:hover .atd-ctax-duo > *:last-child{ transform:translateY(-2px) translateX(1px); }
.v2x.atd .atd-ctax:hover .atd-ctax-duo .atd-ctax-logo{ box-shadow:0 1px 2px rgba(15,23,42,.16), 0 16px 28px -14px rgba(0,0,0,.54); }
@media (max-width:640px){
  .v2x.atd .atd-ctax-duo .atd-ctax-logo{ width:41px; height:41px; border-radius:11px; }
  .v2x.atd .atd-ctax-duo .atd-ctax-logo.is-letter{ font-size:1.05rem; padding:0; }
  .v2x.atd .atd-ctax-duo > * + *{ margin-left:-9px; }
}

/* ── Copy ──────────────────────────────────────────────────────────────── */
.v2x.atd .atd-ctax-h{
  margin:0 0 7px; font-family:var(--font);
  font-size:clamp(1.32rem,1.05rem+1.05vw,1.8rem);
  font-weight:800; letter-spacing:-.02em; line-height:1.2;
  color:#fff; overflow-wrap:anywhere;
}
/* Phones step explicitly rather than through the clamp. Lowering the clamp
   FLOOR looked like the one-line fix and bought ~1px: below about 410px the
   PREFERRED term (1.05rem + 1.05vw ~= 20.9px at 390) is what is active, not
   the floor, so the floor was not the number on screen. Changing the
   preferred term instead would have dragged 1143-1341px desktop widths down
   with it, and this pass is mobile-only. */
@media (max-width:575.98px){
  .v2x.atd .atd-ctax-h{ font-size:1.26rem; }
  .v2x.atd .atd-ctax-p{ font-size:.96rem; }
}
@media (max-width:399.98px){
  .v2x.atd .atd-ctax-h{ font-size:1.16rem; }
}
.v2x.atd .atd-ctax-p{
  margin:0; font-size:1.02rem; line-height:1.6; font-weight:500;
  color:#fff; overflow-wrap:anywhere;
}

/* ── Buttons ───────────────────────────────────────────────────────────── */
.v2x.atd .atd-ctax-btn{
  position:relative; isolation:isolate;
  display:inline-flex; align-items:center; justify-content:center; gap:9px;
  height:52px; padding:0 24px; border-radius:14px;
  font-family:var(--font); font-size:.97rem; font-weight:700; letter-spacing:-.005em;
  text-decoration:none; white-space:nowrap;
  transition:transform .3s cubic-bezier(.16,1,.3,1), box-shadow .3s ease,
             background-color .26s ease, color .22s ease, border-color .26s ease;
}
.v2x.atd .atd-ctax-btn .lb{ min-width:0; }
.v2x.atd .atd-ctax-btn svg{ flex:none; transition:transform .34s cubic-bezier(.16,1,.3,1); }
/* Solid — a white pill. #1B52A6 on white is 7.49:1. */
.v2x.atd .atd-ctax-btn.is-solid{
  background-color:#fff; color:#1B52A6; border:1px solid transparent;
  box-shadow:0 1px 2px rgba(15,23,42,.14), 0 14px 26px -12px rgba(0,0,0,.42);
}
/* Ghost — outlined. The border is the button's ONLY boundary, so it carries
   the 3:1 requirement: 75% white over the ramp's lightest stop is 3.4:1, where
   the 55% the old design would have used measures 2.54. */
.v2x.atd .atd-ctax-btn.is-ghost{
  background-color:transparent; color:#fff;
  border:1.5px solid rgba(255,255,255,.75);
}
.v2x.atd .atd-ctax-btn:focus-visible{
  outline:none;
  box-shadow:0 0 0 3px rgba(255,255,255,.95), 0 0 0 6px rgba(27,82,166,.55);
}

@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-ctax:hover .atd-ctax-aur{ transform:translate3d(-4%,4%,0) scale(1.1); opacity:.9; }
  .v2x.atd .atd-ctax:hover .atd-ctax-logo{
    transform:translateY(-3px) scale(1.03);
    box-shadow:0 1px 2px rgba(15,23,42,.16), 0 20px 34px -14px rgba(0,0,0,.6);
  }
  .v2x.atd .atd-ctax-btn.is-solid:hover{
    color:#16418C; transform:translateY(-3px);
    box-shadow:0 2px 4px rgba(15,23,42,.16), 0 22px 38px -14px rgba(0,0,0,.55);
  }
  /* Before → after: the outline FILLS to the same white pill the primary is,
     so the two buttons meet in the same place and the ink flips with the fill
     rather than after it. */
  .v2x.atd .atd-ctax-btn.is-ghost:hover{
    background-color:#fff; color:#1B52A6; border-color:#fff;
    transform:translateY(-3px);
    box-shadow:0 2px 4px rgba(15,23,42,.16), 0 22px 38px -14px rgba(0,0,0,.55);
  }
  .v2x.atd .atd-ctax-btn:hover svg{ transform:translate(2px,-2px); }
  .v2x.atd .atd-ctax-btn.is-ghost:hover svg{ transform:translateX(2px); }
}
.v2x.atd .atd-ctax-btn:active{ transform:translateY(-1px) scale(.985); }

/* ── The orbit, in white ───────────────────────────────────────────────── */
/* Same recipe as the rest of the page, recoloured: a blue comet on a blue band
   is invisible. The gate is load-bearing — without mask-composite the two mask
   layers UNION and the conic paints a solid block over the label. */
@supports ((-webkit-mask-composite:xor) or (mask-composite:exclude)){
  .v2x.atd .atd-ctax-btn::before{
    content:""; position:absolute; pointer-events:none;
    inset:-1px; z-index:1; padding:1.5px; border-radius:15px;
    --atd-spin:0deg;
    background:conic-gradient(from var(--atd-spin),
      rgba(255,255,255, 0)     0deg, rgba(255,255,255,.55)  30deg,
      rgba(255,255,255, 1)    52deg, rgba(214,230,254,.95)  74deg,
      rgba(255,255,255, 0)   118deg, rgba(255,255,255, 0)  180deg,
      rgba(255,255,255,.55) 210deg, rgba(255,255,255, 1)   232deg,
      rgba(214,230,254,.95) 254deg, rgba(255,255,255, 0)  298deg,
      rgba(255,255,255, 0)  360deg);
    -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite:xor;
            mask-composite:exclude;
    opacity:0; transition:opacity .32s ease;
    animation:atd-orbit 3.2s linear infinite; animation-play-state:paused;
  }
  .v2x.atd .atd-ctax-btn:focus-visible::before{ opacity:1; animation-play-state:running; }
  @media (hover:hover) and (pointer:fine){
    .v2x.atd .atd-ctax-btn:hover::before{ opacity:1; animation-play-state:running; }
  }
  @media (prefers-reduced-motion:reduce){
    .v2x.atd .atd-ctax-btn::before{ --atd-spin:135deg; animation:none !important; }
  }
}

/* ── Responsive ────────────────────────────────────────────────────────── */
/* The band is full width at every breakpoint, so the only question is when the
   actions stop fitting beside the copy. `flex:1 1 440px` answers it without a
   query: below ~840px of inner width the two flex children wrap. These steps
   are for the pieces, not the arrangement. */
@media (max-width:991.98px){
  .v2x.atd .atd-ctax-in{ gap:20px 22px; }
  .v2x.atd .atd-ctax-logo{ width:56px; height:56px; border-radius:15px; }
}
@media (max-width:767.98px){
  .v2x.atd .atd-ctax{ border-radius:18px; }
  .v2x.atd .atd-ctax-lead{ flex:1 1 100%; gap:15px; }
  .v2x.atd .atd-ctax-acts{ flex:1 1 100%; }
  .v2x.atd .atd-ctax-btn{ flex:1 1 auto; }
}
/* Full-width, stacked, every label complete — a two-up row clipped
   "Visit Company Page" at 360px, and truncated button text is worse than a
   taller stack. Same rule the hero's CTA row follows. */
@media (max-width:575.98px){
  .v2x.atd .atd-ctax{ padding:22px 17px; border-radius:16px; }
  .v2x.atd .atd-ctax-logo{ width:50px; height:50px; border-radius:14px; padding:7px; }
  .v2x.atd .atd-ctax-logo.is-letter{ font-size:1.32rem; }
  .v2x.atd .atd-ctax-lead{ gap:13px; }
  .v2x.atd .atd-ctax-p{ font-size:.97rem; }
  .v2x.atd .atd-ctax-acts{ gap:10px; }
  .v2x.atd .atd-ctax-btn{ flex:1 1 100%; width:100%; height:50px; padding:0 18px; }
  .v2x.atd .atd-ctax-aur{ width:min(360px,92%); top:-42%; }
}

/* ── Motion preferences ────────────────────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-ctax-aur,.v2x.atd .atd-ctax-logo,
  .v2x.atd .atd-ctax-btn,.v2x.atd .atd-ctax-btn svg{ transition:none !important; }
  .v2x.atd .atd-ctax:hover .atd-ctax-aur,
  .v2x.atd .atd-ctax:hover .atd-ctax-logo,
  .v2x.atd .atd-ctax-btn:hover,.v2x.atd .atd-ctax-btn:active{ transform:none !important; }
  .v2x.atd .atd-ctax-btn:hover svg{ transform:none !important; }
}

/* ══════════════════════════════════════════════════════════════════════════
   §PILL) Share + Save — the two pills beside the breadcrumb.

   THE HEART IS A BOOKMARK NOW, on request, and that changes the colour logic
   with it. The old design justified a ROSE favourite ("a heart is a
   universally red affordance, and brand blue would read as a second Share").
   A bookmark carries no such convention, so the two pills are identical at
   rest and identical on hover — both brand — and the SAVED state is what
   separates them: a filled brand pill. State, not hue, does the work, which is
   also what makes it legible at a glance on a page that is already blue.

   Three states, three colours, and they cannot be confused:
     rest      neutral surface, hairline
     saved     filled brand pill, white ink, bookmark-check glyph
     copied    green — deliberately NOT blue, because this site remaps its own
               --red / --danger tokens to brand blue elsewhere, so a blue
               confirmation is indistinguishable from a hover.

   The sheen that used to sweep these two is gone: every other control on this
   page answers hover with the orbit, and two different travelling lights on
   one page is noise. `::before` stays the wash, `::after` becomes the ring —
   which also means `overflow:hidden` had to go, since the ring hangs 1px out.
   ══════════════════════════════════════════════════════════════════════════ */
.v2x.atd .atd-topbar-actions{ gap:10px; }

.v2x.atd .atd-pillbtn{
  overflow:visible; isolation:isolate;
  min-height:42px; padding:0 20px; gap:9px;
  font-family:var(--font); font-size:.88rem; font-weight:700; letter-spacing:-.005em;
  color:var(--muted);
  background:#fff; border:1px solid var(--line-strong); border-radius:var(--r-pill);
  box-shadow:0 1px 2px rgba(15,23,42,.05);
  transition:color .22s ease, background-color .24s ease, border-color .22s ease,
             box-shadow .3s cubic-bezier(.16,1,.3,1),
             transform .3s cubic-bezier(.16,1,.3,1);
}
.v2x.atd .atd-pillbtn .ic{
  display:inline-flex; align-items:center; flex:none; color:var(--muted);
  transition:color .22s ease, transform .36s cubic-bezier(.16,1,.3,1);
}
.v2x.atd .atd-pillbtn .ic svg{ display:block; }
.v2x.atd .atd-pillbtn .lb{ min-width:0; }
/* Both glyphs ship in the DOM; the class swaps them. Nothing rewrites a class
   string on a timer any more, so a double click cannot strand the wrong icon. */
.v2x.atd .atd-pillbtn .ic-ok{ display:none; }
.v2x.atd .atd-pillbtn.is-copied .ic-main{ display:none; }
.v2x.atd .atd-pillbtn.is-copied .ic-ok{ display:inline-flex; }

/* The wash is brand on BOTH pills now — the rose only existed for the heart. */
.v2x.atd .atd-pillbtn::before,
.v2x.atd .atd-fav-btn::before{
  background:linear-gradient(135deg, rgba(54,128,237,.15), rgba(54,128,237,.06));
  transform:scale(.9);
}
body.theme-dark .v2x.atd .atd-pillbtn::before,
body.theme-dark .v2x.atd .atd-fav-btn::before{
  background:linear-gradient(135deg, rgba(96,164,245,.20), rgba(96,164,245,.08));
}
body.theme-dark .v2x.atd .atd-pillbtn{ box-shadow:none; }
body.theme-dark .v2x.atd .atd-pillbtn .ic{ color:var(--muted); }

/* ── Saved ─────────────────────────────────────────────────────────────── */
/* White on #2B70D7 is 4.77:1; the ramp starts there rather than at #3680ED
   (3.84) for exactly that reason — the same ramp every filled control on this
   page uses. */
.v2x.atd .atd-pillbtn.is-fav{
  background:linear-gradient(135deg,#2B70D7,#1B52A6);
  border-color:transparent; color:#fff;
  box-shadow:0 1px 2px rgba(15,23,42,.12), 0 10px 22px -10px rgba(32,96,192,.75);
}
.v2x.atd .atd-pillbtn.is-fav .ic{ color:#fff; }
.v2x.atd .atd-pillbtn.is-fav::before{ opacity:0; }
body.theme-dark .v2x.atd .atd-pillbtn.is-fav{
  background:linear-gradient(135deg,#2B70D7,#1B52A6);
  border-color:transparent; color:#fff;
  box-shadow:0 10px 22px -10px rgba(0,0,0,.9);
}
body.theme-dark .v2x.atd .atd-pillbtn.is-fav .ic{ color:#fff; }

/* ── Copied ────────────────────────────────────────────────────────────── */
.v2x.atd .atd-pillbtn.is-copied{
  color:#0B6E4B; border-color:rgba(18,166,111,.5);
  background:linear-gradient(135deg,#ECFDF5,#D7F5E7);
  box-shadow:0 2px 10px rgba(18,166,111,.18);
}
.v2x.atd .atd-pillbtn.is-copied .ic{ color:#0B6E4B; transform:none; }
.v2x.atd .atd-pillbtn.is-copied::before{ opacity:0; }
body.theme-dark .v2x.atd .atd-pillbtn.is-copied{
  background:rgba(18,166,111,.18); border-color:rgba(18,166,111,.45);
  color:#6EE7B7; box-shadow:none;
}
body.theme-dark .v2x.atd .atd-pillbtn.is-copied .ic{ color:#6EE7B7; }

/* ── Hover ─────────────────────────────────────────────────────────────── */
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-pillbtn:hover{
    color:var(--accent-dark); border-color:rgba(54,128,237,.55);
    transform:translateY(-2px);
    box-shadow:0 10px 22px -10px rgba(32,96,192,.55), 0 2px 6px rgba(15,23,42,.06);
  }
  .v2x.atd .atd-pillbtn:hover::before{ opacity:1; transform:scale(1); }
  .v2x.atd .atd-pillbtn:hover .ic{ color:var(--accent-dark); }
  /* Share lifts out of its tray; the bookmark drops INTO its slot. */
  .v2x.atd .atd-share-btn:hover .ic{ transform:translateY(-2px); }
  .v2x.atd .atd-fav-btn:hover .ic{ transform:translateY(2px) scale(1.08); }
  /* The rose hover the favourite used to get is gone with the heart. */
  .v2x.atd .atd-fav-btn:hover{
    color:var(--accent-dark); border-color:rgba(54,128,237,.55);
    box-shadow:0 10px 22px -10px rgba(32,96,192,.55), 0 2px 6px rgba(15,23,42,.06);
  }
  /* A saved pill is already filled — it deepens rather than washing out. */
  .v2x.atd .atd-pillbtn.is-fav:hover{
    background:linear-gradient(135deg,#2464C4,#16418C); color:#fff;
    border-color:transparent;
    box-shadow:0 2px 4px rgba(15,23,42,.14), 0 14px 28px -10px rgba(32,96,192,.85);
  }
  .v2x.atd .atd-pillbtn.is-fav:hover .ic{ color:#fff; transform:translateY(2px) scale(1.08); }
  body.theme-dark .v2x.atd .atd-pillbtn:hover,
  body.theme-dark .v2x.atd .atd-fav-btn:hover{
    color:#9CC5F9; border-color:rgba(96,164,245,.55);
    box-shadow:0 10px 22px -10px rgba(0,0,0,.75);
  }
  body.theme-dark .v2x.atd .atd-pillbtn:hover .ic{ color:#9CC5F9; }
  body.theme-dark .v2x.atd .atd-pillbtn.is-fav:hover{
    background:linear-gradient(135deg,#2464C4,#16418C); color:#fff; border-color:transparent;
  }
  body.theme-dark .v2x.atd .atd-pillbtn.is-fav:hover .ic{ color:#fff; }
  /* A confirmation must not change under the pointer that caused it. */
  .v2x.atd .atd-pillbtn.is-copied:hover{
    color:#0B6E4B; border-color:rgba(18,166,111,.5);
    background:linear-gradient(135deg,#ECFDF5,#D7F5E7); transform:none;
  }
  .v2x.atd .atd-pillbtn.is-copied:hover .ic{ color:#0B6E4B; transform:none; }
  body.theme-dark .v2x.atd .atd-pillbtn.is-copied:hover{
    color:#6EE7B7; border-color:rgba(18,166,111,.45); background:rgba(18,166,111,.18);
  }
  body.theme-dark .v2x.atd .atd-pillbtn.is-copied:hover .ic{ color:#6EE7B7; }
}
.v2x.atd .atd-pillbtn:active{ transform:translateY(0) scale(.975); }
.v2x.atd .atd-pillbtn[disabled]{ opacity:.62; cursor:default; transform:none; box-shadow:none; }
.v2x.atd .atd-pillbtn[disabled]::before{ opacity:0; }

/* ── Responsive ────────────────────────────────────────────────────────── */
/* The pair is never stretched to fill the row: "Add to favorites" needs ~168px
   and half of a 320px card is 148 — an equal-width pair would have to clip the
   label, and a clipped label is the one thing this page does not do. They keep
   their natural width and wrap instead. */
@media (max-width:575.98px){
  .v2x.atd .atd-topbar-actions{ gap:8px; }
  .v2x.atd .atd-pillbtn{ min-height:40px; padding:0 16px; font-size:.85rem; gap:8px; }
}

/* ── Motion preferences ────────────────────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-pillbtn,.v2x.atd .atd-pillbtn .ic,.v2x.atd .atd-pillbtn::before{ transition:none !important; }
  .v2x.atd .atd-pillbtn:hover,.v2x.atd .atd-pillbtn:active{ transform:none !important; }
  .v2x.atd .atd-share-btn:hover .ic,
  .v2x.atd .atd-fav-btn:hover .ic,
  .v2x.atd .atd-pillbtn.is-fav:hover .ic{ transform:none !important; }
}

/* ── The orbit ─────────────────────────────────────────────────────────── */
@supports ((-webkit-mask-composite:xor) or (mask-composite:exclude)){
  .v2x.atd .atd-pillbtn::after{
    content:""; position:absolute; pointer-events:none;
    inset:-1px; z-index:1; padding:1.5px; border-radius:999px;
    --atd-spin:0deg;
    background:conic-gradient(from var(--atd-spin),
      rgba(54,128,237, 0)     0deg, rgba(54,128,237,.55)  30deg,
      rgba(255,255,255, 1)   52deg, rgba(54,128,237,.92)  74deg,
      rgba(54,128,237, 0)   118deg, rgba(54,128,237, 0)  180deg,
      rgba(54,128,237,.55) 210deg, rgba(255,255,255, 1)  232deg,
      rgba(54,128,237,.92) 254deg, rgba(54,128,237, 0)  298deg,
      rgba(54,128,237, 0)  360deg);
    -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite:xor;
            mask-composite:exclude;
    opacity:0; transition:opacity .32s ease;
    animation:atd-orbit 3.2s linear infinite; animation-play-state:paused;
    /* the sheen's leftovers, explicitly cleared */
    inset-inline-start:-1px; width:auto; top:-1px; bottom:-1px; transform:none;
  }
  /* On a filled pill the blue comet disappears into the fill, so it goes white
     there — the same recolour the CTA band's buttons needed. */
  .v2x.atd .atd-pillbtn.is-fav::after{
    background:conic-gradient(from var(--atd-spin),
      rgba(255,255,255, 0)     0deg, rgba(255,255,255,.55)  30deg,
      rgba(255,255,255, 1)    52deg, rgba(214,230,254,.95)  74deg,
      rgba(255,255,255, 0)   118deg, rgba(255,255,255, 0)  180deg,
      rgba(255,255,255,.55) 210deg, rgba(255,255,255, 1)   232deg,
      rgba(214,230,254,.95) 254deg, rgba(255,255,255, 0)  298deg,
      rgba(255,255,255, 0)  360deg);
  }
  /* A confirmation does not need a light show. */
  .v2x.atd .atd-pillbtn.is-copied::after{ opacity:0 !important; animation-play-state:paused !important; }
  .v2x.atd .atd-pillbtn:focus-visible::after{ opacity:1; animation-play-state:running; }
  @media (hover:hover) and (pointer:fine){
    .v2x.atd .atd-pillbtn:hover::after{ opacity:1; animation-play-state:running; }
  }
  @media (prefers-reduced-motion:reduce){
    .v2x.atd .atd-pillbtn::after{ --atd-spin:135deg; animation:none !important; }
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   §GALFIX) The gallery's pre-initialisation state, and the glitch it caused.

   THE BUG WAS NOT IN THIS STYLESHEET. Swiper's own CSS gives every
   `.swiper-slide` `width:100%` before its JS runs — correct for the stage,
   catastrophic for the THUMB RAIL, where four slides at 100% render as ONE
   full-width thumbnail sitting under the stage like a second broken panel.
   That is the "two stacked panels" in the report, and it lasted for as long as
   the init was delayed — which was until `window.load`, i.e. after every
   image, font and third-party file on the page had finished.

   Two fixes, and they are independent on purpose:
     · the init moved to DOMContentLoaded (in the page's own script), which
       shrinks the window to almost nothing on a normal load;
     · these rules make the window HARMLESS, so a slow CDN, a blocked CDN or a
       JS error leaves a correct-looking gallery instead of a broken one.

   Everything here is gated on `:not(.swiper-initialized)`, the class Swiper
   adds to its container, so not one declaration survives into the running
   slider.
   ══════════════════════════════════════════════════════════════════════════ */

/* The thumb rail — the actual glitch. Four across, matching what Swiper lays
   out with slidesPerView:4 / spaceBetween:10 once it takes over. */
.v2x.atd .atd-gal-thumbs:not(.swiper-initialized) .swiper-wrapper{
  display:flex; gap:10px; align-items:stretch;
}
.v2x.atd .atd-gal-thumbs:not(.swiper-initialized) .swiper-slide{
  flex:0 0 calc(25% - 7.5px); width:calc(25% - 7.5px); min-width:0;
}

/* The stage. Swiper's overflow already clips slides 2..n, but only once its
   stylesheet has arrived — and that sheet is now conditional. Belt and braces:
   show the first slide, hold the ratio, hide the rest. */
.v2x.atd .atd-gal-main:not(.swiper-initialized) .swiper-wrapper{ display:block; }
.v2x.atd .atd-gal-main:not(.swiper-initialized) .swiper-slide{ width:100%; }
.v2x.atd .atd-gal-main:not(.swiper-initialized) .swiper-slide ~ .swiper-slide{ display:none; }

/* Controls that cannot work yet are not shown. An arrow that does nothing is
   worse than no arrow, and the counter would read "1 / 5" beside a stage that
   cannot reach slide 2. */
.v2x.atd .atd-gal-main:not(.swiper-initialized) .atd-gal-nav,
.v2x.atd .atd-gal-main:not(.swiper-initialized) .atd-gal-count{
  opacity:0; pointer-events:none;
}
.v2x.atd .atd-gal-main.swiper-initialized .atd-gal-count{ opacity:1; }

/* Tablet and phone. Below 992px the gallery stops being a 5-column sidebar and
   becomes the full width of the page, so the thumbs get a real size rather
   than the desktop rail's proportions. */
@media (max-width:991.98px){
  .v2x.atd .atd-gallery{ margin-top:4px; }
  .v2x.atd .atd-gal-thumbs{ margin-top:10px; }
}
@media (max-width:575.98px){
  /* Three thumbs across, not four: at 320px a quarter of the row is 72px and
     a 16:10 thumb at that width is 45px tall — too small to identify. Swiper
     is told the same number below, so the two agree. */
  .v2x.atd .atd-gal-thumbs:not(.swiper-initialized) .swiper-slide{
    flex-basis:calc(33.333% - 6.67px); width:calc(33.333% - 6.67px);
  }
  .v2x.atd .atd-gal-thumbs{ margin-top:9px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   §RHYTHM) One vertical rhythm for the page's sections.

   THE HOLE UNDER THE RAIL WAS A GRID TRAP. The content row was
   `<div class="row g-4 mt-1">`. Tabler's `.row` cancels its own vertical
   gutter with `margin-top:calc(-1 * var(--tblr-gutter-y))`, and `.mt-1` is a
   utility — `margin-top:.25rem !important` — so it REPLACED that cancellation.
   Each column's own `margin-top:2rem` was then left uncancelled and the gap
   under the tab rail became 26 + 4 + 32 = **62px**, where every other gap on
   the page is 26. Removing `mt-1` from the markup is the fix; nothing here
   papers over it.

   What the page measured before this block:
     · main-column sections   26px, and 26px at EVERY width — no ramp at all,
                              so a 320px phone ran the same gaps as a 1440px
                              desktop;
     · rail to first section  54px (above);
     · main column to sidebar 58px when stacked — the last section's own 26px
                              margin PLUS the column's 32px gutter margin;
     · row to the CTA band    34px (26 + the band's own 8).
   Four different numbers for one idea.

   Now: one token, ramped once, read by all four. The SIDEBAR's internal
   density is deliberately left alone — 16 / 14 / 12 is an authored decision
   about a rail of eight small cards, not an inconsistency.
   ══════════════════════════════════════════════════════════════════════════ */
.v2x.atd{ --atd-sec:26px; }
@media (max-width:1199.98px){ .v2x.atd{ --atd-sec:24px; } }
@media (max-width:991.98px) { .v2x.atd{ --atd-sec:22px; } }
@media (max-width:575.98px) { .v2x.atd{ --atd-sec:18px; } }

.v2x.atd .v2-section{ margin-bottom:var(--atd-sec); }

/* The row's VERTICAL gutter is the main-column-to-sidebar hand-off once they
   stack, so it reads the same token. On desktop the columns sit side by side
   and the row's negative margin cancels it, exactly as before — this changes
   nothing above 992px. */
/* ⚠️ `--tblr-gutter-y`. This grid is TABLER, not vanilla Bootstrap — a
   `--bs-gutter-y` override here sets a variable nothing reads, and looks
   completely correct while doing nothing. Tabler's `.g-4` is 2rem, and its
   `.row > *` takes MARGIN-top, not padding-top. */
.v2x.atd .row.g-4{ --tblr-gutter-y:var(--atd-sec); }

/* …and the last section in a column must not add its own margin on top of
   that gutter, or the hand-off is double-spaced. */
.v2x.atd .row.g-4 > [class*="col-"] > .v2-section:last-child{ margin-bottom:0; }

/* The closing band follows the row on the same rhythm rather than its own 8px. */
.v2x.atd .atd-ctax{ margin-top:var(--atd-sec); }

/* ══════════════════════════════════════════════════════════════════════════
   §UPVOTE) The hero's upvote control.

   THE PROBLEM WITH THE OLD ONE. It was a white pill that turned a soft blue
   tint on hover and an emerald gradient once voted, with the arrow nudging up
   3px and a round count badge flipping colour. Three separate things moved and
   none of them said "vote": the arrow slid a little and came back, the tint
   was the same wash five other controls on this page use, and the badge-in-a-
   pill read as a notification dot rather than a tally.

   WHAT IT IS NOW. One idea, carried by every state: **the button fills upward.**
     · REST — a white (dark: #1B1E28) pill matched to the two buttons beside it,
       a brand-blue chevron, and the tally in its own segment behind a short
       hairline. It reads as a control with a count, not a badge.
     · HOVER — `.atd-up-wash` wipes the brand ramp up from the bottom edge
       (`clip-path`, so the gradient does not stretch), ink and tally invert to
       white, the divider goes translucent, the pill lifts 3px onto a brand
       glow, and the chevron RISES OUT OF ITS SLOT while an identical one takes
       its place. The direction of every one of those is up.
     · VOTED — the emerald fill, and the icon track locks onto its third slot,
       a check. The label stays "Upvote" and the count has already ticked, so
       the state is legible from the glyph, the colour and the number.

   THE ICON IS A THREE-SLOT TRACK (markup: `.atd-up-ic > .atd-up-track >
   chevron, chevron, check`) inside an 18px clip. Slot height and the two
   translate distances are the SAME number — change `--uv-slot` and all three
   follow. This is why the arrow can leave the box without ever leaving the
   button, which a single translated <svg> cannot do.

   MEASURED. White ink needs 4.5:1 here (the label is 15.4px bold — under the
   18.66px "large text" line, so the large-text 3:1 allowance does not apply).
   The hover ramp is the PRIMARY button's own blue for that reason: #2F72DA is
   the lightest stop that clears it (4.62:1) and #1E56B0 the dark end (6.97:1).
   The emerald is the ramp already measured for the voted state further up this
   file — #0E7A45 (5.40) → #12874C (4.57) → #0F7F58 (5.00). Do not lighten
   either lightest stop without re-measuring; both are within 0.1 of the bar.

   ⚠️ THE ORBIT RING STANDS DOWN ON THIS BUTTON (§6 still runs it on the
   outline button and the logo plate). A conic ring spinning around the rim
   while the face fills is two effects competing for the same 340ms, and on the
   voted state it was already disabled for the same reason.
   ══════════════════════════════════════════════════════════════════════════ */

.v2x.atd .atd-cta-row .atd-upvote{
  --uv-slot:18px;                       /* icon slot height = both translate steps */
  --uv-bg:#fff;
  --uv-bd:var(--line-strong);
  --uv-ink:var(--ink);
  --uv-key:#1B54A8;                     /* chevron + tally at rest — 7.29:1 on white */
  --uv-div:rgba(15,23,42,.16);
  --uv-fill:linear-gradient(180deg,#2F72DA 0%,#2261C4 50%,#1E56B0 100%);
  --uv-fill-bd:#2A66C4;
  --uv-glow:0 1px 2px rgba(15,23,42,.10), 0 16px 30px -16px rgba(32,96,192,.9);
  --uv-rest-sh:0 1px 2px rgba(15,23,42,.07);

  position:relative; overflow:hidden;
  display:inline-flex; align-items:center; gap:10px;
  padding:0 18px;
  border:1.5px solid var(--uv-bd); border-radius:13px;
  background:var(--uv-bg); color:var(--uv-ink);
  font-weight:700; line-height:1;
  cursor:pointer; -webkit-tap-highlight-color:transparent;
  box-shadow:var(--uv-rest-sh);
  transition:color .3s ease, border-color .3s ease, box-shadow .34s ease,
             transform .34s cubic-bezier(.16,1,.3,1);
}
/* The dark rules for this button live at (0,5,1) further up (§dark surfaces
   paints it #171922, and the CTA block repaints it #1B1E28), which out-ranks
   the (0,4,0) base above — so the three painted properties are restated here,
   not just the tokens they read. */
body.theme-dark .v2x.atd .atd-cta-row .atd-upvote{
  --uv-bg:var(--dk-surface-3,#1D1D22);
  --uv-bd:var(--line-strong);
  --uv-ink:var(--ink);
  --uv-key:#8FBEFA;
  --uv-div:rgba(255,255,255,.16);
  --uv-glow:0 1px 2px rgba(0,0,0,.5), 0 18px 34px -18px rgba(0,0,0,.95);
  --uv-rest-sh:0 1px 2px rgba(0,0,0,.4);
  background:var(--uv-bg); border-color:var(--uv-bd); color:var(--uv-ink);
}

/* ── The fill. clip-path, not scaleY: a scaled gradient stretches its own
      stops and the ramp arrives lighter at the top than it ends up. ─────── */
.v2x.atd .atd-cta-row .atd-upvote .atd-up-wash{
  position:absolute; inset:0; z-index:0; pointer-events:none;
  background:var(--uv-fill);
  clip-path:inset(100% 0 0 0);
  transition:clip-path .42s cubic-bezier(.16,1,.3,1);
}

/* ── The icon track ────────────────────────────────────────────────────── */
.v2x.atd .atd-cta-row .atd-upvote .atd-up-ic{
  position:relative; z-index:2; flex:none;
  display:block; width:18px; height:var(--uv-slot); overflow:hidden;
}
.v2x.atd .atd-cta-row .atd-upvote .atd-up-track{
  display:flex; flex-direction:column; align-items:center;
  transform:translateY(0);
  transition:transform .46s cubic-bezier(.16,1,.3,1);
}
.v2x.atd .atd-cta-row .atd-upvote .atd-up-track > svg{
  flex:none; width:18px; height:var(--uv-slot);
  color:var(--uv-key);
  transition:color .3s ease;
}
/* The old per-glyph nudges are retired at the specificity that beat them:
   `.atd-upvote:not(.voted):hover svg` and `.atd-upvote.voted svg` are both
   (0,5,0) and would move each icon INSIDE the track, tearing the stack apart. */
.v2x.atd .atd-cta-row .atd-upvote:not(.voted):hover .atd-up-track > svg,
.v2x.atd .atd-cta-row .atd-upvote.voted .atd-up-track > svg{ transform:none; }

/* ── Label + tally ─────────────────────────────────────────────────────── */
.v2x.atd .atd-cta-row .atd-upvote .lbl{
  position:relative; z-index:2; letter-spacing:-.005em;
}
.v2x.atd .atd-cta-row .atd-upvote .cnt{
  position:relative; z-index:2;
  display:inline-flex; align-items:center; justify-content:center;
  min-width:0; height:auto; border-radius:0; background:none;
  margin-inline-start:14px; padding-inline-start:15px;
  font-size:.94rem; font-weight:800; letter-spacing:-.01em;
  font-variant-numeric:tabular-nums lining-nums;
  color:var(--uv-key);
  transition:color .3s ease;
}
/* Dark needs its own twin: the CTA block up the file paints this count a blue
   pill at (0,6,1) (`background:rgba(54,128,237,.20)`), which out-ranks the
   (0,5,0) rule above and would leave a badge sitting inside the segment. */
body.theme-dark .v2x.atd .atd-cta-row .atd-upvote .cnt{
  background:none; color:var(--uv-key);
}
/* A short centred rule, not a full-height one — a divider that runs into both
   rims turns a button into a segmented control. */
.v2x.atd .atd-cta-row .atd-upvote .cnt::before{
  content:""; position:absolute; inset-inline-start:0; top:50%;
  width:1px; height:20px; margin-top:-10px;
  background:var(--uv-div);
  transition:background .3s ease;
}

/* ── Hover — pointer devices only, and never once voted ────────────────── */
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-cta-row .atd-upvote:not(.voted):hover{
    transform:translateY(-3px);
    border-color:var(--uv-fill-bd);
    background:var(--uv-bg);          /* the wash paints the face, not this */
    color:#fff;
    box-shadow:var(--uv-glow);
  }
  .v2x.atd .atd-cta-row .atd-upvote:not(.voted):hover .atd-up-wash{ clip-path:inset(0 0 0 0); }
  .v2x.atd .atd-cta-row .atd-upvote:not(.voted):hover .atd-up-track{ transform:translateY(calc(-1 * var(--uv-slot))); }
  .v2x.atd .atd-cta-row .atd-upvote:not(.voted):hover .atd-up-track > svg{ color:#fff; }
  /* Restated at (0,6,0) and (0,7,1): the old blocks set both of these on the
     hover state and the dark one sits at (0,6,1). */
  .v2x.atd .atd-cta-row .atd-upvote:not(.voted):hover .cnt,
  body.theme-dark .v2x.atd .atd-cta-row .atd-upvote:not(.voted):hover .cnt{
    background:none; color:#fff;
  }
  .v2x.atd .atd-cta-row .atd-upvote:not(.voted):hover .cnt::before{ background:rgba(255,255,255,.38); }
  body.theme-dark .v2x.atd .atd-cta-row .atd-upvote:not(.voted):hover{
    border-color:var(--uv-fill-bd); background:var(--uv-bg); color:#fff;
    box-shadow:var(--uv-glow);
  }
}
.v2x.atd .atd-cta-row .atd-upvote:active{ transform:translateY(-1px) scale(.985); }

/* ── Voted ─────────────────────────────────────────────────────────────── */
.v2x.atd .atd-cta-row .atd-upvote.voted,
body.theme-dark .v2x.atd .atd-cta-row .atd-upvote.voted{
  cursor:default; border-color:transparent; color:#fff;
  background:linear-gradient(135deg,#0E7A45 0%,#12874C 55%,#0F7F58 100%);
  box-shadow:0 1px 2px rgba(15,23,42,.14), 0 16px 30px -16px rgba(14,122,69,.95),
             inset 0 1px 0 rgba(255,255,255,.24);
  transform:none;
}
.v2x.atd .atd-cta-row .atd-upvote.voted .atd-up-wash{ display:none; }
/* Slot 3 — the check. Two slots down, from the one number. */
.v2x.atd .atd-cta-row .atd-upvote.voted .atd-up-track{ transform:translateY(calc(-2 * var(--uv-slot))); }
.v2x.atd .atd-cta-row .atd-upvote.voted .atd-up-track > svg{ color:#fff; }
.v2x.atd .atd-cta-row .atd-upvote.voted .cnt,
body.theme-dark .v2x.atd .atd-cta-row .atd-upvote.voted .cnt{ background:none; color:#fff; }
.v2x.atd .atd-cta-row .atd-upvote.voted .cnt::before{ background:rgba(255,255,255,.42); }

/* The one-shot confirmation, unchanged in behaviour: `.just-voted` is added by
   the click handler only, never on reload, so a returning visitor does not get
   a celebration for something they did last week. z-index clears the fill and
   the copy so the sweep is visible over both. */
.v2x.atd .atd-cta-row .atd-upvote.just-voted::after{
  content:""; position:absolute; inset:0; z-index:3; border-radius:inherit; pointer-events:none;
  background:linear-gradient(120deg,transparent 22%,rgba(255,255,255,.5) 50%,transparent 78%);
  transform:translateX(-120%); animation:atd-up-sheen .7s ease .05s 1;
}

/* Keyboard parity. Declared AFTER the hover block so a focused-and-hovered
   button still shows its ring instead of only the glow. */
.v2x.atd .atd-cta-row .atd-upvote:focus-visible{
  outline:none; border-radius:13px;
  box-shadow:0 0 0 3px rgba(54,128,237,.85), 0 0 0 6px rgba(54,128,237,.22);
}
@supports ((-webkit-mask-composite:xor) or (mask-composite:exclude)){
  .v2x.atd .atd-cta-row .atd-upvote::before{ display:none; }
}

/* ── Responsive ────────────────────────────────────────────────────────── */
@media (max-width:575.98px){
  /* Full width beside the other two CTAs, contents centred as a group — the
     tally stays attached to the label rather than being pushed to the rim,
     which at 100% width would read as an unrelated number. */
  .v2x.atd .atd-cta-row .atd-upvote{ width:100%; justify-content:center; padding:0 16px; }
  .v2x.atd .atd-cta-row .atd-upvote .cnt{ margin-inline-start:12px; padding-inline-start:13px; }
}

/* ── Motion preferences ────────────────────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  /* The states still SWITCH — the fill, the check and the colours all arrive,
     they just do not travel. The icon track is the exception that must keep
     its transform: it is not decoration, it is which glyph is on screen. */
  .v2x.atd .atd-cta-row .atd-upvote,
  .v2x.atd .atd-cta-row .atd-upvote .atd-up-wash,
  .v2x.atd .atd-cta-row .atd-upvote .atd-up-track,
  .v2x.atd .atd-cta-row .atd-upvote .atd-up-track > svg,
  .v2x.atd .atd-cta-row .atd-upvote .cnt,
  .v2x.atd .atd-cta-row .atd-upvote .cnt::before{ transition:none !important; }
  .v2x.atd .atd-cta-row .atd-upvote:not(.voted):hover,
  .v2x.atd .atd-cta-row .atd-upvote:active{ transform:none; }
  .v2x.atd .atd-cta-row .atd-upvote.just-voted{ animation:none; }
  .v2x.atd .atd-cta-row .atd-upvote.just-voted::after{ display:none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   §MEASURE-FULL) Body-column prose fills its card

   `.v2-rich > p/ul/ol` is capped at `min(100%, 80ch)` further up this file —
   855px inside an 1185px card at 2560px, so About / What is / Benefits / Who
   Should Use each stopped 28% short of the card edge with a permanent hole to
   the right of them.

   The cap is lifted rather than worked around: the copy keeps its own shape and
   simply runs to the edge of the card. The card is what limits the line length,
   because `.v2x` caps the container — this is not "full viewport width".

   `:not(.cmp)` keeps /company/{slug} on the original measure; it was not part
   of this request. /gpts/{slug} sets the same rule in its own sheet, so the two
   agree rather than fight. Applies to the BODY COLUMN only — the sidebar is
   narrow enough that 80ch never bites there.
   ══════════════════════════════════════════════════════════════════════════ */
.v2x.atd:not(.cmp) .col-lg-8 .v2-rich > p,
.v2x.atd:not(.cmp) .col-lg-8 .v2-rich > ul,
.v2x.atd:not(.cmp) .col-lg-8 .v2-rich > ol,
.v2x.atd:not(.cmp) .col-lg-8 .v2-rich > h2,
.v2x.atd:not(.cmp) .col-lg-8 .v2-rich > h3,
.v2x.atd:not(.cmp) .col-lg-8 .v2-rich > h4,
.v2x.atd:not(.cmp) .col-lg-8 .v2-rich > blockquote{ max-width:100%; }

/* ══════════════════════════════════════════════════════════════════════════
   §VSROW) Popular Comparisons — the matchup row

   Supersedes the `.atd-comp` flex row above and the §CMPDUO overlapped logo
   pair that briefly replaced its single tile. Both put ONE small cropped logo
   beside a "A vs B" string; this makes the row what it actually is — two
   named tools facing each other.

   FIVE decisions that are load-bearing, not taste:

   1. `.atd-comp` STAYS ON THE ELEMENT. The sidebar orbit ring is wired by
      class: `.atd-comp::before` is the conic comet, and the card dims its own
      ring via `:has(.atd-comp:hover)`. Keeping the class inherits the hover,
      focus-visible, touch-:active and reduced-motion answers with no edit to
      any of those selector lists. `.atd-vs` then supersedes only the layout,
      at (0,5,0) over the base (0,4,0).

   2. NO `overflow:hidden` ON THE ROW. That ring hangs at `inset:-1px`, i.e.
      one pixel OUTSIDE the box, so clipping the row erases it. Any sheen or
      wash here has to be a background layer, never a clipped child. The ring
      radius is restated below for the same reason the other hosts restate it:
      the row is 16px, so the ring one pixel out is 17px.

   3. THE LOGO PLATE IS WHITE IN BOTH THEMES. This is the hero's own recipe —
      `.atd-logo-tile` is `background:#fff` under `body.theme-dark` too — and
      it is the only treatment that survives the real logo set: half of these
      marks are near-black glyphs on transparent, which vanish on a dark
      plate. `object-fit:contain` + a percentage inset shows the WHOLE mark;
      `cover` (what the row used to do) crops every non-square logo.

   4. THE BREAKPOINTS ARE CONTAINER QUERIES, NOT MEDIA QUERIES. This card's
      width does not track the viewport: the rail is ~384px at 1280px, ~603px
      at 2560px, and §SIDEBAR-RESP turns it into a ~940px full-width stack
      below 992px. A viewport query would shrink the row exactly where the
      card gets WIDER. `container-type` goes on `.atd-vslist`, a wrapper this
      block owns outright — never on the card, which already runs an orbit
      ::before, a `z-index:-1` bloom ::after and an `isolation:isolate` that
      containment would disturb. Where @container is unsupported the stacked
      base layout stands on its own.

   5. NAMES WRAP, THEY NEVER TRUNCATE. Each side owns a `1fr` track, so the
      longest pair in the set ("GitHub Copilot vs Cursor") has ~115px a side
      at the narrowest rail and still sets on one line; anything longer wraps
      to a second. No ellipsis, no clipped tool name.
   ══════════════════════════════════════════════════════════════════════════ */
.v2x.atd .atd-vslist{
  container-type:inline-size;
  container-name:atdvs;
  display:grid; gap:10px;
}

.v2x.atd .atd-comp.atd-vs{
  --vs-tile:46px;      /* the logo plate; everything else is derived from it */
  --vs-badge:29px;
  --vs-go:30px;
  --vs-nm:.82rem;
  position:relative;
  display:flex; align-items:flex-start; gap:10px;
  margin-inline:0; padding:12px;
  border-radius:16px;
  border:1px solid rgba(var(--tone-rgb,54,128,237), .17);
  background-color:rgba(var(--tone-rgb,54,128,237), .05);
  color:var(--ink); text-decoration:none;
  transition:transform 380ms cubic-bezier(.16,1,.3,1), box-shadow 320ms ease,
             border-color 240ms ease, background-color 240ms ease;
}
body.theme-dark .v2x.atd .atd-comp.atd-vs{
  border-color:rgba(var(--tone-rgb,54,128,237), .26);
  background-color:rgba(255,255,255,.028);
}
/* Ring geometry only — the reveal, the pace and the reduced-motion freeze all
   come from the shared `.atd-comp::before` rules. */
@supports ((-webkit-mask-composite:xor) or (mask-composite:exclude)){
  .v2x.atd .atd-comp.atd-vs::before{ border-radius:17px; --orb-sp:4.2s; }
}

.v2x.atd .atd-vs-rail{
  position:relative; flex:1 1 auto; min-width:0;
  display:grid; grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);
  align-items:start; gap:6px;
}
/* The bracket — a hairline drawn tile-centre to tile-centre with the badge
   sitting on it, so the pair reads as a matchup and not as two logos that
   happen to be near each other. The tiles are opaque and lifted to z-index:1,
   so only the gap between them ever shows. Hidden in the wide layout, where
   the line would have to cross the names to reach anything. */
.v2x.atd .atd-vs-rail::before{
  content:""; position:absolute; z-index:0; pointer-events:none;
  left:15%; right:15%; top:calc(var(--vs-tile) / 2); height:2px; margin-top:-1px;
  border-radius:2px;
  background:linear-gradient(90deg,
    rgba(var(--tone-rgb,54,128,237),0)    0%,
    rgba(var(--tone-rgb,54,128,237),.34) 24%,
    rgba(var(--tone-rgb,54,128,237),.34) 76%,
    rgba(var(--tone-rgb,54,128,237),0)  100%);
  transition:opacity 280ms ease;
}

.v2x.atd .atd-vs-side{
  position:relative; z-index:1; min-width:0;
  display:flex; flex-direction:column; align-items:center; gap:7px; text-align:center;
}

.v2x.atd .atd-vs-tile{
  flex:none; width:var(--vs-tile); height:var(--vs-tile);
  border-radius:calc(var(--vs-tile) * .27);
  display:flex; align-items:center; justify-content:center;
  background:#fff; border:1px solid var(--line);
  box-shadow:0 1px 2px rgba(15,23,42,.06), 0 8px 18px -12px rgba(15,23,42,.42);
  transition:transform 420ms cubic-bezier(.16,1,.3,1), box-shadow 320ms ease,
             border-color 240ms ease;
}
.v2x.atd .atd-vs-tile img{
  display:block; width:100%; height:100%;
  object-fit:contain; padding:calc(var(--vs-tile) * .155);
  border-radius:inherit;
}
/* Overrides the width/height ATTRIBUTES <x-lucide> writes, so the placeholder
   scales with the plate instead of staying 18px inside a 54px tile. */
.v2x.atd .atd-vs-tile svg{ width:42%; height:42%; color:var(--muted2); }
body.theme-dark .v2x.atd .atd-vs-tile{
  border-color:var(--dk-line-strong,rgba(255,255,255,.16));
  box-shadow:0 1px 2px rgba(0,0,0,.5), 0 10px 22px -14px rgba(0,0,0,.9);
}

.v2x.atd .atd-vs-nm{
  max-width:100%;
  font-size:var(--vs-nm); font-weight:650; line-height:1.25; letter-spacing:-.006em;
  color:var(--ink); overflow-wrap:break-word;
  transition:color 200ms ease;
}

/* The badge wears the CARD's tone, matching `.atd-side-ic` in the head — one
   teal chip at the top, one on every row. Its top margin centres it on the
   tile row from the tile and badge sizes, so no breakpoint has to re-nudge it. */
.v2x.atd .atd-vs-badge{
  position:relative; z-index:2; flex:none;
  width:var(--vs-badge); height:var(--vs-badge);
  margin-top:calc(var(--vs-tile) / 2 - var(--vs-badge) / 2);
  display:flex; align-items:center; justify-content:center;
  border-radius:var(--r-pill);
  background:linear-gradient(135deg, var(--tone-1,#4C8DF2), var(--tone-2,#2060C0));
  color:#fff; font-size:calc(var(--vs-badge) * .35); font-weight:800;
  line-height:1; text-transform:uppercase; letter-spacing:.03em;
  box-shadow:0 4px 12px color-mix(in srgb, var(--tone-2,#2060C0) 36%, transparent),
             inset 0 1px 0 rgba(255,255,255,.34);
  transition:transform 420ms cubic-bezier(.16,1,.3,1), box-shadow 320ms ease;
}
@supports not (color: color-mix(in srgb, red 50%, transparent)){
  .v2x.atd .atd-vs-badge{
    box-shadow:0 4px 12px rgba(16,24,40,.22), inset 0 1px 0 rgba(255,255,255,.34);
  }
}

/* The go button takes BRAND blue on hover, not the card tone: it makes the
   same "this is a link" promise as the `.atd-link` in the head, and the head
   link is brand blue on every one of the eight toned cards. */
.v2x.atd .atd-vs-go{
  flex:none; width:var(--vs-go); height:var(--vs-go);
  margin-top:calc(var(--vs-tile) / 2 - var(--vs-go) / 2);
  display:flex; align-items:center; justify-content:center;
  border-radius:var(--r-pill);
  background-color:var(--atd-surface,#fff);
  border:1px solid var(--line); color:var(--muted2);
  transition:transform 380ms cubic-bezier(.16,1,.3,1), background-color 240ms ease,
             border-color 240ms ease, color 240ms ease, box-shadow 300ms ease;
}

/* ── Hover ──────────────────────────────────────────────────────────────── */
@media (hover:hover) and (pointer:fine){
  .v2x.atd .atd-comp.atd-vs:hover{
    transform:translateY(-3px);
    background-color:rgba(var(--tone-rgb,54,128,237), .10);
    border-color:rgba(var(--tone-rgb,54,128,237), .40);
    box-shadow:0 16px 30px -16px rgba(var(--tone-rgb,54,128,237), .70);
    color:var(--ink); text-decoration:none;
  }
  /* The two plates tip TOWARD each other — the whole point of the row in one
     8px gesture. Direction is per side, so it reads as a clash rather than as
     two things drifting the same way. */
  .v2x.atd .atd-comp.atd-vs:hover .atd-vs-side:first-child .atd-vs-tile{
    transform:translate(3px,-3px) rotate(-5deg);
  }
  .v2x.atd .atd-comp.atd-vs:hover .atd-vs-side:last-child .atd-vs-tile{
    transform:translate(-3px,-3px) rotate(5deg);
  }
  .v2x.atd .atd-comp.atd-vs:hover .atd-vs-tile{
    border-color:rgba(var(--tone-rgb,54,128,237), .48);
    box-shadow:0 1px 2px rgba(15,23,42,.06),
               0 16px 26px -14px rgba(var(--tone-rgb,54,128,237), .75);
  }
  .v2x.atd .atd-comp.atd-vs:hover .atd-vs-badge{
    transform:scale(1.12);
    box-shadow:0 6px 18px color-mix(in srgb, var(--tone-2,#2060C0) 54%, transparent),
               inset 0 1px 0 rgba(255,255,255,.40),
               0 0 0 4px rgba(var(--tone-rgb,54,128,237), .17);
  }
  .v2x.atd .atd-comp.atd-vs:hover .atd-vs-rail::before{ opacity:.45; }
  /* --tone-ink is the ramp's own contrast-checked reading colour, light and
     dark: #0B6E68 on the teal wash, #79DDD5 on the dark panel. */
  .v2x.atd .atd-comp.atd-vs:hover .atd-vs-nm{ color:var(--tone-ink, var(--accent-dark)); }
  .v2x.atd .atd-comp.atd-vs:hover .atd-vs-go{
    transform:translateX(3px);
    background-image:linear-gradient(135deg,#4C8DF2,#2060C0);
    background-color:#3680ED; border-color:transparent; color:#fff;
    box-shadow:0 6px 16px rgba(32,96,192,.42);
  }
  body.theme-dark .v2x.atd .atd-comp.atd-vs:hover{
    background-color:rgba(var(--tone-rgb,54,128,237), .16);
    border-color:rgba(var(--tone-rgb,54,128,237), .46);
    box-shadow:0 18px 32px -18px rgba(0,0,0,.9);
  }
}
/* Press. Also the ONLY state a touch device gets, so it carries the whole
   feedback there — hence a real displacement, not just a tint. */
.v2x.atd .atd-comp.atd-vs:active{ transform:translateY(-1px) scale(.994); }

/* The shared focus rule re-states `border-radius:var(--r-card)` (12px) on the
   ring it draws; this row is 16px, so it has to be said again at (0,6,1). */
body:not(.admin-shell) .v2x.atd .atd-comp.atd-vs:focus-visible{ border-radius:16px; }

/* ── Card-width steps ───────────────────────────────────────────────────── */
@container atdvs (min-width:330px){
  .v2x.atd .atd-comp.atd-vs{ --vs-tile:52px; --vs-badge:32px; --vs-go:32px; --vs-nm:.88rem; padding:14px 13px; }
}
/* Past 510px the stack has more height than it needs and more width than it
   can fill, so each side turns into a row and mirrors: name outward, plate
   inward, flanking the badge. The bracket goes away here — it would have to
   cross the names to reach anything.

   510px, NOT 470px, and the 40px is measured rather than chosen. The mirrored
   row spends its track on the plate BEFORE the name gets any, so the longest
   pair in the set — "GitHub Copilot vs Cursor" — needs 510px of list to keep
   both names on one line here, while the stacked layout it replaces still fits
   them on one line at 246px. Switching at 470px put a two-line name into the
   one layout whose symmetry depends on both sides matching. */
@container atdvs (min-width:510px){
  .v2x.atd .atd-comp.atd-vs{ --vs-tile:58px; --vs-badge:35px; --vs-go:36px; --vs-nm:.94rem; padding:16px 18px; }
  .v2x.atd .atd-comp.atd-vs,
  .v2x.atd .atd-vs-rail{ align-items:center; }
  .v2x.atd .atd-vs-rail{ gap:12px; }
  .v2x.atd .atd-vs-rail::before{ display:none; }
  .v2x.atd .atd-vs-side{ flex-direction:row; align-items:center; justify-content:center; gap:11px; }
  .v2x.atd .atd-vs-side:first-child{ text-align:right; }
  .v2x.atd .atd-vs-side:first-child .atd-vs-tile{ order:2; }
  .v2x.atd .atd-vs-side:last-child{ text-align:left; }
  .v2x.atd .atd-vs-badge,
  .v2x.atd .atd-vs-go{ margin-top:0; }
}
/* Full size. Held back to 540px for the same reason the step below it is held
   to 510px: the plate is taken out of the track before the name is measured.
   Measured at the boundary — a 64px plate leaves 126px for the name where the
   longest one in the set needs 113px. */
@container atdvs (min-width:540px){
  .v2x.atd .atd-comp.atd-vs{ --vs-tile:64px; --vs-badge:39px; --vs-go:38px; --vs-nm:1rem; padding:18px 20px; }
  .v2x.atd .atd-vs-side{ gap:13px; }
}

@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-comp.atd-vs,
  .v2x.atd .atd-vs-tile,
  .v2x.atd .atd-vs-badge,
  .v2x.atd .atd-vs-go,
  .v2x.atd .atd-vs-nm{ transition:none !important; }
  .v2x.atd .atd-comp.atd-vs:hover,
  .v2x.atd .atd-comp.atd-vs:active,
  .v2x.atd .atd-comp.atd-vs:hover .atd-vs-tile,
  .v2x.atd .atd-comp.atd-vs:hover .atd-vs-badge,
  .v2x.atd .atd-comp.atd-vs:hover .atd-vs-go{ transform:none; }
}
/* ══════════════════════════════════════════════════════════════════════════
   §PLATICO) PLATFORM CHIPS HOLD OFFICIAL BRAND MARKS.

   They used to hold Font Awesome brand glyphs, which are single-path and
   single-colour: the chip painted them in the card tone, so Android, Windows
   and Chrome all came out the same flat cyan and read as generic pictograms
   rather than the real logos. The marks are now inline SVG
   (v2.public.partials.platform-icon) in their official colours, and the chip
   has to change with them -- a tinted plate and a gradient hover fill both
   destroy a polychrome logo.

   The chip carries the kind, set in the blade:
     .is-poly    Android / Windows / Linux / Chrome. Fixed brand colours baked
                 into the SVG. The chip must never tint or fill behind them.
     .is-mono    Apple. Officially black, so it flips to white after dark --
                 drawn with fill:currentColor and coloured from here.
     .is-generic Web and API are not brands. They keep currentColor and answer
                 in the card tone, like every other glyph in the sidebar.

   SPECIFICITY, because three older rules sit above these:
     .v2x.atd .atd-plat-ic                          (0,3,0)  base chip
     body.theme-dark .v2x.atd .atd-plat-ic          (0,4,1)  dark chip
     .v2x.atd .atd-plat.is-link:hover .atd-plat-ic  (0,6,0)  gradient fill
   so the plate is written at .atd-plat .atd-plat-ic (0,4,0), its dark twin at
   (0,5,1), and every hover rule names the kind class to reach (0,7,0).
   ══════════════════════════════════════════════════════════════════════════ */

/* A NEUTRAL plate, not a tinted one. Brand colour only reads correctly on a
   neutral ground -- a cyan wash behind the Chrome disc greys the blue and
   kills the red. The hairline is what separates the plate from the pill,
   since both are near-white by day. */
.v2x.atd .atd-plat .atd-plat-ic{
  background:#F4F6FA;
  box-shadow:inset 0 0 0 1px rgba(15,23,42,.07);
  color:var(--tone-ink, var(--accent-dark));
}
.v2x.atd .atd-plat .atd-plat-ic.is-mono{ color:#000; }
.v2x.atd .atd-plat-ic svg{ display:block; flex:none; }
/* The mark must not inherit the pill's .86rem -- these are sized in px on the
   element, and a stray font-size would only matter for the <i> fallback. */
.v2x.atd .atd-plat-ic svg.atd-plat-svg{ pointer-events:none; }

body.theme-dark .v2x.atd .atd-plat .atd-plat-ic{
  background:var(--dk-surface-4,#24242A);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.10);
  color:var(--tone-ink, #9CC5F9);
}
/* Apple's mark is black by day and white after dark. This is the whole reason
   .is-mono exists as a separate kind from .is-poly. */
body.theme-dark .v2x.atd .atd-plat .atd-plat-ic.is-mono{ color:#fff; }

/* Tux is the other officially-black mark, but he cannot simply flip: he is
   polychrome, and a white penguin with a yellow beak is not the logo. So the
   dark theme lights a rim behind his silhouette instead -- without it his body
   merges into the plate and only the white face and the feet are left
   floating. Set on the chip so the SVG stays theme-agnostic. */
body.theme-dark .v2x.atd .atd-plat .atd-plat-ic{ --tux-rim:rgba(255,255,255,.58); }

@media (hover:hover) and (pointer:fine){
  /* No gradient fill. The plate brightens and takes the card tone in its ring
     instead, which keeps the hover legible without painting over the logo. */
  .v2x.atd .atd-plat.is-link:hover .atd-plat-ic.is-poly,
  .v2x.atd .atd-plat.is-link:hover .atd-plat-ic.is-mono,
  .v2x.atd .atd-plat.is-link:hover .atd-plat-ic.is-generic{
    background:#fff;
    box-shadow:inset 0 0 0 1px rgba(var(--tone-rgb,54,128,237),.42),
               0 3px 9px rgba(var(--tone-rgb,54,128,237),.20);
    transform:scale(1.06);
  }
  body.theme-dark .v2x.atd .atd-plat.is-link:hover .atd-plat-ic.is-poly,
  body.theme-dark .v2x.atd .atd-plat.is-link:hover .atd-plat-ic.is-mono,
  body.theme-dark .v2x.atd .atd-plat.is-link:hover .atd-plat-ic.is-generic{
    background:var(--dk-line-solid,#2C2C31);
    box-shadow:inset 0 0 0 1px rgba(var(--tone-rgb,54,128,237),.46),
               0 3px 9px rgba(0,0,0,.45);
  }
  /* A platform with no URL is a dead chip -- §SIDEBAR-FIX already strips its
     lift, and it must not gain one here either. */
  .v2x.atd .atd-plat:not(.is-link):hover .atd-plat-ic.is-poly,
  .v2x.atd .atd-plat:not(.is-link):hover .atd-plat-ic.is-mono,
  .v2x.atd .atd-plat:not(.is-link):hover .atd-plat-ic.is-generic{
    background:#F4F6FA;
    box-shadow:inset 0 0 0 1px rgba(15,23,42,.07);
    transform:none;
  }
  body.theme-dark .v2x.atd .atd-plat:not(.is-link):hover .atd-plat-ic.is-poly,
  body.theme-dark .v2x.atd .atd-plat:not(.is-link):hover .atd-plat-ic.is-mono,
  body.theme-dark .v2x.atd .atd-plat:not(.is-link):hover .atd-plat-ic.is-generic{
    background:var(--dk-surface-4,#24242A);
    box-shadow:inset 0 0 0 1px rgba(255,255,255,.10);
  }
}
@media (prefers-reduced-motion:reduce){
  .v2x.atd .atd-plat.is-link:hover .atd-plat-ic.is-poly,
  .v2x.atd .atd-plat.is-link:hover .atd-plat-ic.is-mono,
  .v2x.atd .atd-plat.is-link:hover .atd-plat-ic.is-generic{ transform:none; }
}
/* ═══════════════════════════════════════════════════════════════════════════
   §AIMLOGO — the model mark fills its plate                      (2026-08-25)
   ═══════════════════════════════════════════════════════════════════════════
   §AIM's plate is TINTED — `--t-bg`, the same tint the rank chip and the
   category pill wear — and the mark inside it sat at 74%, the inset the
   reference used back when the plate was a white chip. On a tinted tile that
   ratio leaves ~8px of colour on every side and the card reads as a small logo
   floating in a coloured box, which is the exact reading §TCLOGO removed from
   the directory cards and §SCLOGO from the homepage rails.

     60px plate -> 60px mark      (52px at the phone step, and it follows)

   `object-fit: contain` is untouched and is what makes 100% safe: a square
   mark fills the plate exactly, a wide wordmark fits to width and centres. The
   plate already carries `overflow: hidden`, so a square mark is clipped to its
   own 18px curve and reads as an app icon rather than a square with its
   corners sawn off.

   ── WHY THIS AND NOT `.atd-ctax-logo` ─────────────────────────────────────
   The CTA plate a few hundred lines up is WHITE in both themes, on purpose:
   brand marks are drawn for a light ground and a dark tile puts a near-black
   logo on a near-black plate. On a white plate the inset is not dead tint —
   it is the ring of white that makes a light-ground mark read as sitting ON
   the tile, which is why §ACDPLATE in public-ai-course-acd-styles.css opens
   that padding only on the ONE page whose plates carry a provider wordmark.
   A tinted plate has no such job for its margin. Tinted fills, white keeps its
   ring; that is the line, and it is the same one `.cmp-vs-tile` sits on.

   §AIM paints three pages — the AI Models band on a tool detail page, the
   Alternatives band on a model detail page, and the Models band on a company
   page — so this lands on all three at once. The lettered fallback is the
   plate's own `font-size` and is untouched. */
.v2x.atd .atd-aim-logo img{ width:100%; height:100%; }


/* ── §AIMLOGO-RING) The border survives a full-bleed logo ─────────────────
   The plate's edge is an INSET box-shadow, painted on its background and so
   below the image. At 74% that did not matter; at 100% an opaque mark covers
   it and the tile loses its border on exactly the cards where the tint no
   longer draws one.

   A pseudo redraws the same ring above the image. All three states are
   restated — light, dark and hover — because each is declared on the plate
   itself and none of them reaches through the logo now. `border-radius:
   inherit` keeps the ring on the plate's own curve including the 15px it takes
   at the phone step. Same shape as §TCLOGO-RING. */
.v2x.atd .atd-aim-logo{ position:relative; }

.v2x.atd .atd-aim-logo::after{
  content:""; position:absolute; inset:0; z-index:1;
  border-radius:inherit; pointer-events:none;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.5);
  transition:box-shadow .24s ease;
}

body.theme-dark .v2x.atd .atd-aim-logo::after{ box-shadow:inset 0 0 0 1px rgba(255,255,255,.06); }

@media (hover: hover) {
  .v2x.atd .atd-aim:hover .atd-aim-logo::after{ box-shadow:inset 0 0 0 1px rgba(var(--t-rgb), .55); }
}

/* ═══════════════════════════════════════════════════════════════════════════
   §CTAXFILL — the CTA plate's mark fills it                      (2026-08-25)
   ═══════════════════════════════════════════════════════════════════════════
   The last plate on the ATD detail pages still holding its mark off the edge.
   Here the inset is not a percentage on the image — that is already 100% — it
   is `padding: 9px` on the plate, so a 62px tile shows a 44px mark with 18px
   of dead white around it.

     62px plate -> 62px mark      (56px / 50px at the two steps below)

   §ACDPLATE in public-ai-course-acd-styles.css made exactly this change on
   2026-08-19, scoped to `/ai-courses/{slug}` alone, on the reasoning that only
   that page had switched its plates to a provider WORDMARK — which loses more
   than a square icon does to an inset, because it fits to WIDTH and then sits
   in a short band across the middle. This lifts that scope to every ATD page.
   The acd rules still out-rank these at (0,4,0) and are left in place: they
   also zero the padding for the LETTER fallback, which this does not.

   ── WHY A WHITE PLATE FILLS HERE AND `.dir-hh-tile` DOES NOT ──────────────
   The line everywhere else in this codebase is that a tinted plate fills and a
   white one keeps its ring, because on white the margin is doing a job: it
   separates a light-ground mark from the tile. This plate is white and still
   fills, and the difference is that it has a REAL BORDER — `1px solid
   rgba(255,255,255,.55)` — drawn outside the padding box, where no logo can
   reach it. The edge survives without the margin, so the margin is only
   costing size. The hero orbit tile has no such border and keeps its padding.

   That border is also why this block, like §CMPVS-FILL, needs no ring pseudo.

   ── SCOPED BY CONTENT, NOT BY PAGE ────────────────────────────────────────
   `:has(img)` is the plate carrying a real mark. Everything else keeps its
   9px: `.is-letter`, the monogram every blade prints when a row has no logo
   and the shape `/status` uses for a Font Awesome glyph; and the orphaned
   `.fqp-ctax-ic` SVG variant, which would be scaled past its 24px grid. A
   class hook would have to name each of those; this describes the case. */
.v2x.atd .atd-ctax-logo:has(img){ padding:0; overflow:hidden; }

/* ═══════════════════════════════════════════════════════════════════════════
   §HEROFILL — the hero mark fills its tile                       (2026-08-25)
   ═══════════════════════════════════════════════════════════════════════════
   The last plate in the family, and the biggest thing on the page:

     112px tile, padding 10.7%  ->  88px mark  (~24px of dead white)

   §CTAXFILL took the CTA plate 300px below this one to the edge, which left
   the hero as the ONE plate on a detail page still holding its mark off — the
   inconsistency landing on the largest element of the page. §ACDPLATE in
   public-ai-course-acd-styles.css made this exact change on 2026-08-19 for
   `/ai-courses/{slug}` alone; this lifts it to all 22 pages that draw an ATD
   hero, whether through `v2/public/atd/hero.blade.php` or their own copy
   (tool, company, aimodel, gpt).

   ── NO `overflow` AND NO RING, UNLIKE EVERY OTHER BLOCK IN THIS FAMILY ────
   `.atd-logo-tile` is the class on the `<img>` ITSELF, not on a wrapper. Two
   things follow. Its own `border-radius` clips the replaced content, so a
   square mark drawn edge-to-edge takes the tile's 24px curve without an
   `overflow: hidden` anywhere. And its edge is a REAL BORDER — `1px solid
   var(--line)` — drawn outside the padding box where the image cannot reach
   it, so the border survives a full-bleed logo and needs no ring pseudo. Same
   reasoning as §CTAXFILL, one element earlier in the cascade.

   The `inset 0 1px 0 #fff` in its box-shadow IS covered now. It was a white
   highlight on a white plate: invisible before, invisible after.

   `padding` is the only declaration that moves. `object-fit: contain` stays
   and is what makes this safe — a square mark fills the tile exactly, a wide
   wordmark fits to WIDTH and centres, which is the correct result for a
   wordmark and the case §ACDPLATE was written for. `.atd-logo-letter`, the
   monogram plate, is a different element on a gradient fill and is untouched.

   ── EXCEPT ON THE SPEAKER PAGE ───────────────────────────────────────────
   §SPKD in public-events-speakers.css turns this tile into a CIRCLE, because
   a person gets a headshot where a product gets a mark. A photograph is not a
   logo: `object-fit: contain` fits a portrait to height and leaves the plate
   showing down both sides, and a circle is the worst frame to do that in. No
   speaker carries a photo today — every one falls back to `.atd-logo-letter`
   — so this excludes a code path rather than a rendered page. If speaker
   photos ever want the full circle, the fix there is `object-fit: cover`, not
   this. Same carve-out §TCLOGO makes for `.tplx-lc-cover img`. */
.v2x.atd:not(.spkd) .atd-logo-tile{ padding:0; }

/* ═══════════════════════════════════════════════════════════════════════════
   §VSTILE-FILL — the Popular Comparisons mark fills its tile     (2026-08-25)
   ═══════════════════════════════════════════════════════════════════════════
   The §VSROW plate hid from the plate-fill sweep, and it is worth recording
   HOW. Every other kit in the family insets the mark by sizing the <img> down
   inside the plate — `width: 60%`, `74%`, `70%`. This one sizes the image to
   the full plate and then pads THE IMAGE:

     .atd-vs-tile img { width:100%; height:100%; padding: calc(var(--vs-tile) * .155) }

   So the image's BORDER box does fill the plate and the audit read it as 96%
   — a rounding artifact, not an inset — while the mark inside it was 15.5%
   short on every side. On a 52px tile that is a 36px mark with 8px of white
   around it. Measure the mark, not the box.

   It is also the worst-looking case in the set, because half the marks here
   ship their own opaque background: Claude's salmon square and Perplexity's
   black square rendered as a coloured rounded square floating inside a white
   rounded square. Two nested tiles where there should be one.

     46px tile -> 46px mark      base
     52px tile -> 52px mark      @container atdvs (min-width:330px)
     58px tile -> 58px mark      @container atdvs (min-width:510px)

   The padding was expressed against `--vs-tile` so it tracked all three
   container steps; zero tracks them just as well.

   ── NO RING NEEDED, ONE `overflow` DOES ──────────────────────────────────
   §VSROW note 3 gives this plate a REAL BORDER — `1px solid var(--line)`,
   restated for dark — drawn outside the padding box where the image cannot
   reach it. The edge survives a full-bleed mark on its own, exactly as it
   does for §CTAXFILL and §HEROFILL, so no ring pseudo.

   `overflow: hidden` is new. The image already carries `border-radius:
   inherit`, but it inherits the plate's OUTER radius while sitting inside the
   1px border, so at 100% its corner curve is a pixel proud of the plate's
   inner one. Clipping at the plate settles it.

   `object-fit: contain` is untouched, which is what §VSROW note 3 relies on:
   `cover` crops every non-square logo, and this set has several. And the
   `<x-lucide name="scale">` placeholder a tool with no logo falls back to
   stays at its 42% — that is a GLYPH standing in for a mark, the same
   carve-out §TCLOGO makes. This rule names `img` and reaches nothing else. */
.v2x.atd .atd-vs-tile{ overflow:hidden; }
.v2x.atd .atd-vs-tile img{ padding:0; }
