/* delist.ai — content pages, shared foundation.
   The tokens are the landing's Venice re-theme of Organic, copied verbatim: one
   palette sitewide, no content-page variant. What differs from the landing is
   only what has to — see the notes on the nav and the ground below.

   Load order on every content page:
     content-base.css  →  content-prose.css  →  content-blocks.css  →  page CSS

   ds-base.js is NOT in that chain any more. It injected Organic's styles.css, which
   is where this package silently got its element base layer and its button
   appearance from — neither is present on delist.ai, so a converted page was
   inheriting both from the OLD stylesheet. §20 of the matrix has the full account.
   The three sheets are now self-sufficient: fonts, tokens, element layer, all here. */

@import url('/fonts.css');

:root {
  /* — one namespace, and it is --color-*. Reversed from the last drop. —
     I had this backwards and the branch is right. My reasoning was that ~580
     references were being renamed --color-* → --ds-* on every drop, so moving
     three files beat moving 360 pages. The fact that argument missed: --ds-* is
     not a free namespace. site.css already owns it — --ds-paper, --ds-ink,
     --ds-indigo, --ds-cta, --ds-coral, --ds-r-*, --ds-container, --ds-t-* — and
     that is the stylesheet we are migrating OFF. Declaring --ds-bg / --ds-text /
     --ds-accent here put two different design systems in one namespace on any
     page that loads both, which is a collision, not a rename cost.
     README's "reference --ds-*, do not redeclare" was written about site.css's
     family and I read it as an instruction to extend it. It was not.
     One namespace, --color-*, no aliases, no duplicate declarations. */
  --color-bg: #efeee3;
  --color-text: #1d3b57;
  --font-heading: "Playfair Display", Georgia, serif;
  --font-body: "DM Sans", system-ui, sans-serif;
  --font-heading-weight: 500;
  --color-accent: #1f6bb5;
  --color-accent-100: #e3edf6;
  --color-accent-200: #c8dcee;
  --color-accent-300: #a2c4e1;
  --color-accent-400: #6fa3cf;
  --color-accent-500: #1f6bb5;
  --color-accent-600: #1a5d9f;
  --color-accent-700: #174f88;
  --color-accent-800: #123e6b;
  --color-accent-900: #0d2e50;
  --color-accent-2: #71875a;
  --color-accent-2-100: #ecefe4;
  --color-accent-2-200: #dde3cd;
  --color-accent-2-300: #c3cda9;
  --color-accent-2-400: #9cad7f;
  --color-accent-2-500: #71875a;
  --color-accent-2-600: #5f744b;
  --color-accent-2-700: #4d5e3d;
  --color-accent-2-800: #3e4c31;
  --color-accent-2-900: #2f3a26;
  --color-neutral-100: #fbfaf3;
  --color-neutral-200: #f2f1e7;
  --color-neutral-300: #e2e1d4;
  --color-neutral-400: #c3c5bc;
  --color-neutral-500: #9aa0a0;
  --color-neutral-600: #6f7b83;
  --color-neutral-700: #4d5f6e;
  --color-neutral-800: #33475a;
  --color-neutral-900: #1d3145;
  --color-surface: #fbfaf3;
  --color-divider: color-mix(in srgb, #1d3b57 18%, transparent);

  /* — the two rhythms —
     --leading is the marketing rhythm, unchanged from the landing: 28px, generous,
     built for sections that breathe. --read is the reading rhythm: 30px, the line
     box of 18px body copy. They are deliberately different numbers and they do NOT
     interleave — an article body never sits inside a marketing grid, and a
     marketing band never tries to align to a paragraph. Every content page uses
     --leading for its furniture (bands, cards, nav, footer) and --read for prose. */
  --leading: 28px;
  --half: 14px;
  --read: 30px;
  --edge: clamp(20px, 5vw, 72px);
  --measure: 68ch;
}

/* ═══════════════════════════════════════════════════════════════════════════
   THE ELEMENT BASE LAYER — everything :where(), so it is (0,0,0).
   ═══════════════════════════════════════════════════════════════════════════
   This package shipped no element layer, so a converted page was taking p, ul, ol,
   h2, a, img, tr, td, summary, strong and sup from the OLD stylesheet — 87 elements
   at its colours, 25 at its font family. That is the third instance of one mistake:
   the prototypes load Organic via ds-base.js, Organic styles bare elements, and I
   read a rendered prototype as evidence the package was complete. The buttons and
   the nav drawer were the first two.

   Every selector here is wrapped in :where() and therefore weighs nothing. That is
   not defensive habit — it is what makes this layer safe to add underneath ~340
   already-converted pages: no rule in any of the three sheets, and no page CSS,
   changes behaviour because of it. It only fills gaps. */
:where(*, *::before, *::after) { box-sizing: border-box; }
:where(h1, h2, h3, h4, h5, h6) { font-family: var(--font-heading);
  font-weight: var(--font-heading-weight); line-height: 1.14;
  letter-spacing: -0.012em; margin: 0 0 var(--half); text-wrap: balance; }
:where(h1) { font-size: 44px; }
:where(h2) { font-size: 31px; }
:where(h3) { font-size: 22px; }
:where(h4) { font-size: 18px; }
:where(h5, h6) { font-size: 15px; }
:where(p) { margin: 0 0 var(--half); }
:where(ul, ol) { margin: 0 0 var(--half); padding-left: 24px; }
:where(li) { margin-bottom: 4px; }
:where(a) { color: var(--color-accent-700); text-underline-offset: 3px; }
:where(a:hover) { color: var(--color-accent-800); }
:where(strong, b) { font-weight: 700; }
:where(em, i) { font-style: italic; }
:where(small) { font-size: 87.5%; }
:where(sup, sub) { font-size: 72%; line-height: 0; }
:where(img, svg, video) { display: block; max-width: 100%; }
:where(figure, blockquote) { margin: 0; }
:where(hr) { height: 1px; border: 0; background: var(--color-divider); margin: var(--leading) 0; }
:where(table) { border-collapse: collapse; width: 100%; }
:where(th) { text-align: left; font-weight: 700; }
:where(th, td) { padding: 10px 14px; vertical-align: top; }
:where(code, pre, kbd, samp) { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 0.92em; }
:where(pre) { overflow-x: auto; margin: 0 0 var(--half); }
:where(summary) { cursor: pointer; }
:where(button, input, select, textarea) { font: inherit; color: inherit; }
:where(fieldset) { margin: 0; padding: 0; border: 0; }
:where(legend) { padding: 0; }
:where(:focus-visible) { outline: 2px solid var(--color-accent); outline-offset: 2px; }
::selection { background: color-mix(in srgb, var(--color-accent) 26%, transparent); }

html { scroll-behavior: smooth; overflow-x: clip; scroll-padding-top: 92px; }
/* ── Reduced motion: the strong form, as chat-funnel.css already uses. ──
   The README said "there is no animation on any content page, so this is free" and
   that is not true: the nav runs 450ms flex-grow and max-width transitions when the
   scan field takes focus, .btn transitions four properties, and the footer's column
   arrow animates translate. So the rule is not free and it is not optional.
   Duration rather than `none`, so anything relying on a transitionend still fires. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}
body { margin: 0; position: relative; overflow-x: clip; text-wrap: pretty;
  font-family: var(--font-body); color: var(--color-text);
  background: var(--color-bg);
  /* clears the fixed pill nav; the landing hides its nav behind a hero and does
     not need this */
  padding-top: 86px; }
.btn { font-family: var(--font-body); font-weight: 600;
  transition: background 0.35s ease, color 0.35s ease, box-shadow 0.35s ease, border-color 0.35s ease;
  min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }
/* ── The 44px floor is UNCONDITIONAL, not a mobile rule. ──
   It used to live only in @media (max-width: 900px), so above the breakpoint .btn
   fell back to the design system's padding and resolved to 36px — the scan button
   in the nav measured 30px. 900px is not a touch boundary: an iPad in landscape is
   1024px and was getting the small targets. One number, every width.
   The design system's .btn is 36px and its ghost variant 23px; raised here rather
   than in the design system so the component is not forked. */
.nav .btn-ghost { min-height: 44px; padding-inline: 14px; }
.nav-scan input { min-height: 44px; }

/* — no photographic backdrop on content pages —
   The landing's full-bleed watercolor is ~300KB and is justified by one page that
   exists to set a mood. Three hundred search entry points cannot carry it: it is
   the single largest thing on the page and it is decoration. The ground is the
   same cream, the sheet is the same ivory, the type and color are identical —
   what is missing is a photograph nobody scrolled here to see. Budget below. */

/* [hidden] must actually hide.
   The UA stylesheet's [hidden] { display: none } is (0,1,0) and loses to any class
   that declares display — so .hubsearch { display: grid } left a search field
   visible and typeable with JS off, doing nothing, which is the exact failure the
   progressive design exists to avoid. This is a trap for every future component
   with both a display declaration and an initial hidden state, so it is fixed once
   here rather than per component. Author rules that need to override it must say
   so explicitly. */
[hidden] { display: none !important; }

a { color: var(--color-accent-700); text-decoration: underline;
  text-decoration-color: color-mix(in srgb, currentColor 32%, transparent);
  text-underline-offset: 2px; transition: color 0.2s ease, text-decoration-color 0.2s ease; }
a:hover { color: var(--color-accent-800); text-decoration-color: currentColor; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; border-radius: 4px; }

/* — the sheet —
   Same ivory card the landing uses, so a visitor arriving from search and a
   visitor arriving from the home page are demonstrably on one site. */
.sheet { background: var(--color-surface); border-radius: 40px;
  width: min(1400px, calc(100% - 28px)); margin: 0 auto 18px; box-sizing: border-box;
  padding: calc(1.5 * var(--leading)) clamp(20px, 5vw, 80px) calc(2.5 * var(--leading));
  box-shadow: 0 1px 2px rgba(29, 59, 87, 0.05); }

/* — the pill nav, sitewide —
   Identical component to the landing's. One difference, and it is structural
   rather than stylistic: the landing's nav starts hidden and slides in once you
   scroll past the hero, because it would otherwise sit on top of the hero it is
   introducing. A content page has no hero to clear, and a nav that appears only
   after scrolling is a nav a search visitor cannot find. So on content pages it
   is present from load — same pill, same contents, no JS. */
.nav { position: fixed; top: 14px; left: 50%; transform: translate(-50%, 0); z-index: 50;
  display: flex; align-items: center;
  width: min(1060px, calc(100% - 2 * var(--edge))); box-sizing: border-box;
  border-radius: 999px; background: var(--color-bg);
  box-shadow: 0 6px 20px rgba(29, 59, 87, 0.10);
  /* 4px, not 10px: the controls inside are now 44px, so the pill would grow to
     72px on the old padding. At 4px it lands at ~60px — within 2px of what it
     was — and body { padding-top } below still clears it. */
  padding: 4px 14px 4px 26px; }
.nav .nav-brand { margin-right: 10px; display: flex; align-items: center; font-weight: 600;
  min-height: 44px; padding: 9px 4px; }
.nav .nav-brand img { height: 22px; width: auto; display: block; }
.nav .nav-scan { margin-right: auto; align-self: center; }
/* nav links are standalone actions, so they take the 44px floor like every other
   control in the pill. Without this they were their 25px line box: the pill is
   62px tall and both were centred in it, so this changes no rendered layout. */
.nav a { white-space: nowrap; font-size: 16px; text-decoration: none;
  min-height: 44px; display: inline-flex; align-items: center; }
/* :not(.btn) on the colour, and this is a real bug the branch found.
   .nav a is (0,1,1) and .btn-ghost is (0,1,0), so a ghost button that is an
   <a> lost its accent and rendered as body ink. It stayed invisible because
   features-page.html used <button> for "Sign in" while the live nav uses
   <a href="/app/home"> — and the anchor is the correct element: a control that
   navigates is a link. So the sheet was wrong, not the markup.
   The exclusion goes on the three colour declarations only. Everything above
   still applies to a .btn in the nav, and should. */
.nav a:not(.btn) { color: var(--color-text); }
.nav a:not(.btn):hover { color: var(--color-accent-700); }
.nav a:not(.btn)[aria-current="page"] { color: var(--color-accent-700); font-weight: 600; }
.nav-scan { display: flex; align-items: center; gap: 6px; min-width: 0; box-sizing: border-box;
  background: var(--color-surface); border-radius: 999px; padding: 4px 4px 4px 16px;
  border: 1px solid color-mix(in srgb, var(--color-text) 12%, transparent);
  flex: 0.0001 1 210px;
  transition: flex-grow 0.45s cubic-bezier(0.22, 0.8, 0.24, 1), background 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease; }
.nav-scan input { border: 0; background: transparent; outline: none; flex: 1; min-width: 0;
  padding: 6px 0; font: 15px var(--font-body); color: var(--color-text); }
.nav-scan input::placeholder { color: color-mix(in srgb, var(--color-text) 72%, transparent); }
/* 44px square, per the unconditional floor at the top of this file. Was 30px:
   the primary scan control on every page was the smallest target on it. */
.nav-scan .btn-icon { width: 44px; height: 44px; padding: 0; flex: none; }
.nav .btn-ghost { font-size: 16px; font-weight: 500; white-space: nowrap; }
.nav a, .nav .btn-ghost { max-width: 170px; overflow: hidden;
  transition: opacity 0.25s ease, max-width 0.45s cubic-bezier(0.22, 0.8, 0.24, 1), padding 0.45s ease; }
.nav:has(.nav-scan input:focus) .nav-scan { flex-grow: 1; box-shadow: 0 1px 2px rgba(29, 59, 87, 0.05);
  border-color: color-mix(in srgb, var(--color-text) 22%, transparent); }
.nav:has(.nav-scan input:focus) a,
.nav:has(.nav-scan input:focus) .btn-ghost { opacity: 0; max-width: 0; padding-inline: 0; pointer-events: none; }

/* — the footer: the locked 20-link structure, verbatim from the landing — */
.qfooter { background: var(--color-bg); border-radius: 40px;
  width: min(1400px, calc(100% - 28px)); margin: 18px auto;
  padding: calc(1.5 * var(--leading)) clamp(24px, 6vw, 96px) 0; box-sizing: border-box; }
.qcols { display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 0.9fr) minmax(0, 1fr) minmax(0, 1.25fr) minmax(0, 0.9fr);
  gap: var(--leading) clamp(20px, 3vw, 44px); padding-bottom: calc(1.5 * var(--leading));
  border-bottom: 1px solid color-mix(in srgb, var(--color-text) 14%, transparent); }
/* The logo is 20px tall and the anchor shrink-wrapped it — a 20px target, on every
   page, and the first thing in the footer. The link stays inline-flex so it does
   not stretch across the column; the padding is what makes the box. */
.qbrand a { display: inline-flex; align-items: center; box-sizing: border-box;
  min-height: 44px; padding: 12px 10px; margin: -12px -10px 0;
  border-radius: 12px; }
.qbrand a:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.qbrand a:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.qbrand img { height: 20px; width: auto; display: block; }
/* 14px. This is a sentence -- "Erases you from data brokers, AI services and
   the rest of the web" -- in the injected footer, so it is on every one of the
   354 pages, and it was the only prose on the system under the reading floor. */
.qbrand p { font-size: 14px; line-height: 1.55; margin: var(--half) 0 0; max-width: 24ch;
  color: color-mix(in srgb, var(--color-text) 72%, transparent); }
.qcol h4 { font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; font-weight: 700;
  margin: 4px 0 var(--half); }
.qcol h4 a { display: inline-flex; align-items: center; gap: 5px; text-decoration: none;
  color: color-mix(in srgb, var(--color-text) 72%, transparent); transition: color 0.2s ease;
  min-height: 44px; }
.qcol h4 a::after { content: "\2192"; font-size: 11px; opacity: 0;
  translate: -4px 0; transition: opacity 0.2s ease, translate 0.2s ease; }
.qcol h4 a:hover { color: var(--color-accent-700); }
.qcol h4 a:hover::after { opacity: 1; translate: 0 0; }
/* gap 2px, not 10px: the 44px rows below carry their own separation — same
   construction as .linkgrid. At 10px the footer grew by half its height. */
.qcol ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.qcol a { font-size: 14px; color: var(--color-text); text-decoration: none; }
.qcol li a { display: flex; align-items: center; min-height: 44px; line-height: 1.45; text-wrap: pretty; }
.qcol a:hover { color: var(--color-accent-700); }
.qbar { display: flex; align-items: center; justify-content: space-between; gap: var(--half);
  padding: var(--half) 0 var(--leading); font-size: 13px; color: #24231f; }
.qbar .legal { display: flex; gap: 18px; }
/* the separator, in the sheet instead of the DOM. chrome.js injects
   <span class="sep">·</span> between the two legal links; a separator between two
   links is presentation, and in the DOM it is also announced — a screen reader
   reads "middle dot" between Privacy and Terms.
   Both selectors ship on purpose, so there is no ordering constraint between this
   rule and the markup change: the second matches today's shape (two single-item
   lists, .legal a flex row over them), the first matches the tidier one list with
   two items. Delete the span whenever suits; if you also collapse to one <ul>,
   .legal ul below is already the flex row that shape needs. */
.qbar .legal ul { display: flex; gap: 18px; margin: 0; padding: 0; list-style: none; }
.qbar .legal li + li::before,
.qbar .legal ul ~ ul > li::before { content: "\00B7"; display: inline-block;
  padding-right: 18px; user-select: none;
  color: color-mix(in srgb, var(--color-text) 45%, transparent); }
/* min-height: "Privacy" and "Terms" are each the whole content of their own element
   inside span.legal, so neither is a link inside a sentence. */
.qbar a { color: inherit; text-decoration: underline; text-underline-offset: 2px;
  text-decoration-color: color-mix(in srgb, currentColor 35%, transparent);
  min-height: 44px; display: inline-flex; align-items: center; }
.qbar a:hover { text-decoration-color: currentColor; }

@media (max-width: 900px) {
  body { padding-top: 78px; }
  /* the 44px floor is unconditional now — see the top of this file */
  .sheet, .qfooter { border-radius: 28px; }
  .nav { padding: 4px 10px 4px 18px; }
  /* 16px, so iOS does not zoom the page when the field takes focus */
  .nav-scan input { font-size: 16px; }
  .qcols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .qbrand { grid-column: 1 / -1; }
}
/* the scan pill leaves the nav at 860, not 640: between those widths the four
   links were being clipped by their own max-width rather than wrapping */
@media (max-width: 860px) { .nav-scan { display: none; } }
@media (max-width: 560px) {
  .qcols { grid-template-columns: 1fr; gap: calc(1.5 * var(--leading)); }
  /* the 44px rows are unconditional now — see the end of this file */
  .qbar { flex-direction: column; align-items: flex-start; gap: 8px; }
}
/* The 480px rule that hid .nav a is GONE — it is the live defect the mobile nav
   spec replaces (nav-mobile.html). It hid every link with nothing behind it, so
   Pricing and About were unreachable from the homepage on a phone. The drawer now
   collapses .nav-links instead, and every link stays in the DOM at every width. */

/* ─────────────────────────────────────────────────────────────────
   DESIGN-SYSTEM CONTRAST OVERRIDES

   The bound design system's styles.css carries five muted TEXT styles below this
   spec's 4.5:1 floor, and every page here loads it: figcaption and .text-muted at
   ink 55% (~3.1:1), .card-meta at 50% (~2.7:1), .table th at 60% (~3.5:1),
   .field > label at 70% (4.62:1 — passes, aligned for one muted value).

   Overridden here rather than edited there: we do not own that stylesheet, and
   forking it for five declarations is worse than shadowing them. Same selectors, so
   source order decides and this file loads after the bundle. If the design system
   ever takes the sweep itself, delete this block rather than leaving both.

   .input:hover's 45% is a BORDER, not text — deliberately not touched.
   ───────────────────────────────────────────────────────────────── */
figcaption { color: color-mix(in srgb, var(--color-text) 72%, transparent); }
.text-muted { color: color-mix(in srgb, var(--color-text) 72%, transparent); }
.card-meta { color: color-mix(in srgb, var(--color-text) 72%, transparent); }
.table th { color: color-mix(in srgb, var(--color-text) 72%, transparent); }
.field > label { color: color-mix(in srgb, var(--color-text) 72%, transparent); }

/* Footer and breadcrumb links — standalone actions, not inline prose: each link is
   the entire content of its own <li>. These kept the mobile-only pattern (a
   padding-block: 11px inside @media (max-width: 560px), which reached only 42px
   anyway) while .btn and the nav moved to an unconditional floor.

   .crumbs a needs the display change: min-height does nothing on display: inline.

   The list gap drops to 2px because the 44px rows now carry their own separation —
   The list gap and the row heights are folded into the .qcol rules above rather than
   appended here: two rules for one selector in one file, resolved only by source
   order, is the failure §16 tells the team to assert against. */
.crumbs a { min-height: 44px; display: inline-flex; align-items: center; }
/* On the ROW, not the link. Every trail ends in a non-link aria-current crumb, and
   .crumbs ol is a flex row at align-items: normal — so the linked crumbs centred
   their text in a 44px box while the bare-text <li> stretched and top-aligned its
   22px line box, 11px higher. Centring the row fixes both without giving the
   non-interactive crumb a hit-area rule it should not need. */
.crumbs ol { align-items: center; }

/* The breadcrumb separator lives HERE, unscoped — not in content-prose.css.
   It was .prose .crumbs li + li::before, and every structured archetype (hub,
   use-case, comparison, utility, tool, error, industries, directory, features)
   places .crumbs as a sibling of the content rather than inside .prose, so the rule
   never matched and those trails rendered as loose words with a flex gap.

   This matters for the migration: the matrix retires `sep` (498 uses) and
   `uc-breadcrumb-sep` (156) in favour of this pseudo-element. Had it stayed
   .prose-scoped, that rewrite would have deleted 654 authored separators and
   replaced them with a rule that fires on prose pages only.

   The two .prose .crumbs li::before rules stay where they are — they exist to beat
   the generic .prose ul/ol > li::before markers at (0,1,3), and the .prose-scoped
   separator still wins inside the reading column. */
/* No opacity. At 0.6 against an already-72% colour the glyph landed at 2.32:1 —
   the same value as the accent-2-400 numerals corrected for failing, and §13 gives
   decorative type no exemption. It inherits the crumb colour at 4.88:1. */
.crumbs li + li::before { content: "\203A"; margin-right: 10px; }

/* ── .qcol h5 — the sub-level inside a footer column ──────────────────────────

   THE MATRIX SPEC FOR THIS WAS WRONG AND IS CORRECTED HERE. §15 asked for 11px
   uppercase at ink 50% against h4's 70%, differentiating the two levels by
   lightness. Both numbers fail: 50% measures 2.74:1 and 70% 4.62:1 against a floor
   of 72% / 4.88:1, and the whole system was swept off those steps for that reason.

   It also breaks the rule the sweep established — never carry meaning with
   lightness. A reader who cannot see a 20% alpha difference gets no hierarchy at
   all, and a reader who can is reading a level that fails AA.

   So the two levels are distinguished by CASE and WEIGHT, both of which survive at
   the same ink: h4 is 11px uppercase 700 with tracking, h5 is 13px sentence case
   600 with none. That reads as subordinate at a glance and at any contrast.
   The margin-top from the matrix is kept — it is the one part that was right. */
.qcol h5 { font-size: 13px; line-height: var(--half); font-weight: 600;
  letter-spacing: 0; text-transform: none;
  color: color-mix(in srgb, var(--color-text) 72%, transparent);
  margin: var(--half) 0 4px; }

/* ── .foothubs — the internal-linking row beneath the columns ─────────────────

   The matrix retired `foot-hubs` with "columns sit directly in .qcols". That was
   right about the class and wrong about the element: it is a <nav> landmark with
   its own aria-label, carrying a link to every hub on the site, and folding it into
   a column grid would merge a navigation landmark into a layout grid and change
   what a screen reader announces.

   So it survives as its own block. Full width beneath .qcols, above .qbar. A wrap
   row rather than a grid, because the link count changes as hubs are added and a
   grid would leave holes. 44px rows per the floor.

   KEEP the <nav> and KEEP the aria-label. The class changes; the element does not. */
.foothubs { padding: calc(1.25 * var(--leading)) 0;
  border-bottom: 1px solid color-mix(in srgb, var(--color-text) 14%, transparent); }
.foothubs h4 { font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  font-weight: 700; margin: 0 0 var(--half);
  color: color-mix(in srgb, var(--color-text) 72%, transparent); }
.foothubs ul { list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 2px clamp(16px, 2.5vw, 32px); }
.foothubs a { display: inline-flex; align-items: center; min-height: 44px;
  font-size: 14.5px; text-decoration: none; color: var(--color-text);
  transition: color 0.2s ease; }
.foothubs a:hover { color: var(--color-accent-700); text-decoration: underline;
  text-underline-offset: 3px; }


/* ═══════════════════════════════════════════════════════════════════════════
   THE BUTTON LAYER — inlined, not inherited.
   ═══════════════════════════════════════════════════════════════════════════
   Everything above this point PATCHES .btn — font, weight, transition, the 44px
   floor — and left the appearance to the Organic stylesheet: padding, fill,
   border, radius. ds-base.js injects that stylesheet into the prototypes, which
   is why they look right. It is not injected on delist.ai, where the target is
   site.css appended. So on a converted page .btn-primary named a fill nothing
   painted, and the primary CTA rendered as bare text at the correct weight.

   Loading Organic on 716 pages is not the fix. It also declares .card, .table,
   .input, .field, .nav and .radio, all of which the old tier declares too, at
   specificities that were never reconciled — that is a second migration, not a
   prerequisite for this one. The rules below are lifted from the Organic source
   verbatim, with its --space-* resolved to the literals they compute to (the
   package does not redeclare that scale, so a var() reference here would
   collapse to zero padding). Computed output is identical to the prototypes. */
.btn { box-sizing: border-box; gap: 6px; cursor: pointer; text-decoration: none;
  font-size: 14px; line-height: 1.2; color: var(--color-text);
  background: transparent; border: 1px solid transparent;
  padding: 8.8px 15.84px; border-radius: 999px; }
/* flex: none alongside display: block. Found by the round-19 clause the moment
   it was added: .btn is inline-flex with a 6px gap, and its labels wrap on a
   phone -- "Remove my information from these 20 sites" is a button. A flex icon
   on a wrapping line is a squashed icon. Same defect .flag had, two components
   over. */
.btn svg { display: block; flex: none; }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
/* 5.29:1 on the accent — neutral-100 rather than Organic's --color-bg, which is
   the cream ground and measures 4.75:1. Both pass; the ivory is the surface tone
   the rest of this package puts on filled grounds. */
.btn-primary { background: var(--color-accent); color: var(--color-neutral-100); }
.btn-primary:hover { background: var(--color-accent-600); }
.btn-primary:active { background: var(--color-accent-700); }
/* .btn-soft is the delist-native name for this and appears on 8 page families
   with no rule of its own. Same appearance, one declaration — the two names
   should collapse to .btn-secondary in a later pass, not diverge now. */
.btn-secondary, .btn-soft { border-color: var(--color-divider);
  background: var(--color-surface); }
.btn-secondary:hover, .btn-soft:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.btn-secondary:active, .btn-soft:active { background: color-mix(in srgb, var(--color-text) 14%, transparent); }
.btn-ghost { color: var(--color-accent-700); padding-inline: 4.4px; }
.btn-ghost:hover { background: color-mix(in srgb, var(--color-accent) 10%, transparent); }
.btn-ghost:active { background: color-mix(in srgb, var(--color-accent) 18%, transparent); }
/* 44px, not Organic's 36px — the unconditional floor at the top of this file.
   .nav-scan .btn-icon already said this; a .btn-icon outside the nav had nothing. */
.btn-icon { width: 44px; height: 44px; padding: 0; }
.btn-block { width: 100%; margin-top: 8.8px; }
.btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* ═══════════════════════════════════════════════════════════════════════════
   THE NAV LINK WRAPPER AND ITS DRAWER — from nav-mobile.html, verbatim.
   ═══════════════════════════════════════════════════════════════════════════
   .nav-links is on 342 pages after the rename and had no rule in any shipped
   sheet; the only occurrence of the name was a comment describing what the
   drawer collapses. The drawer rules themselves lived in nav-mobile.html, which
   is a prototype and ships nothing. Both halves land here.

   .navmenu-btn and its glyph come with it. The script injects that button on
   every page — unstyled, it is a 0×0 unlabelled control sitting in the pill. */
.nav-links { display: flex; align-items: center; gap: 22px; min-width: 0; }
.navmenu-btn { display: none; }
.nav .navmenu-btn { width: 44px; height: 44px; padding: 0; flex: none;
  align-items: center; justify-content: center; margin-left: 4px;
  background: none; border: 0; border-radius: 999px; cursor: pointer;
  color: var(--color-text); }
.nav .navmenu-btn:hover { background: var(--color-accent-100); }
.nav .navmenu-btn:active { background: var(--color-accent-200); }
.nav .navmenu-btn svg { display: block; flex: none; }
.navmenu-btn .bar { transform-origin: 12px 12px;
  transition: transform 0.28s cubic-bezier(0.22, 0.8, 0.24, 1), opacity 0.18s ease; }
.navmenu-btn[aria-expanded="true"] .bar-a { transform: translateY(3.5px) rotate(45deg); }
.navmenu-btn[aria-expanded="true"] .bar-b { transform: translateY(-3.5px) rotate(-45deg); }

@media (max-width: 860px) {
  .nav { flex-wrap: wrap; row-gap: 0; }
  .nav .navmenu-btn { display: inline-flex; }
  .nav .nav-brand { margin-right: auto; }
  /* display:none, not height/opacity — a panel that is visually hidden but still
     focusable is a tab-order trap on every page. */
  .nav[data-menu="closed"] .nav-links { display: none; }
  /* open: the pill becomes a card. 999px is a bar radius, not a panel radius. */
  .nav[data-menu="open"], .nav:not([data-menu]) { border-radius: 28px; padding-bottom: 8px; }
  .nav[data-menu="open"] .nav-links, .nav:not([data-menu]) .nav-links {
    display: grid; gap: 0; width: 100%; order: 9; margin-top: 8px; padding-top: 4px;
    border-top: 1px solid color-mix(in srgb, var(--color-text) 12%, transparent); }
  .nav[data-menu="open"] .nav-links > a, .nav:not([data-menu]) .nav-links > a {
    display: flex; align-items: center; min-height: 48px; max-width: none;
    padding: 0 8px; font-size: 17px; }
  .nav[data-menu="open"] .nav-links > a[aria-current="page"],
  .nav:not([data-menu]) .nav-links > a[aria-current="page"] {
    color: var(--color-accent-700); font-weight: 600; }
  /* the scan pill returns inside the panel — today it vanishes below 860 and the
     page's primary action leaves the nav with it */
  .nav[data-menu="open"] .nav-scan { display: flex; order: 8; width: 100%; flex: none; margin-top: 10px; }
  .nav[data-menu="open"] .nav-scan input { min-height: 44px; }
  .nav[data-menu="open"] .nav-scan .btn-icon { width: 44px; height: 44px; }
  /* sign in stays on the bar, never in the drawer */
  .nav .btn-ghost { order: 2; min-height: 44px; }
  .nav .navmenu-btn { order: 3; }
}
/* The .nav:not([data-menu]) half of the pairs above is the JS-off case: no button
   was injected, so the links render stacked and stay reachable. A taller nav is
   the correct failure. */

/* .qcol h5 sits directly under the h4 when it is the column's first label. */
.qcol h5:first-of-type { margin-top: 0; }


/* ═══════════════════════════════════════════════════════════════════════════
   THE 44px FLOOR ON <summary>, AND THE SEPARATOR — round 7
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── summary ──────────────────────────────────────────────────────────────────
   Ask 4. The floor was written as unconditional and then attached to
   .faq-item > summary, so it held on the one disclosure that had a component and
   nowhere else — a bare <summary> measured 21px. A disclosure trigger is always a
   tap target, so the floor belongs on the element, not on the component.
   padding-block rather than a bare min-height: min-height on a list-item leaves
   21px of text pinned to the top of a 44px box, which passes the measurement and
   still looks like a mistake. display stays list-item so the native triangle —
   the whole affordance for a summary with no component — survives.
   .faq-item > summary and .disclose > summary both outrank this and keep their
   own padding; this is the floor for everything that is neither. */
summary { min-height: 44px; box-sizing: border-box; padding-block: 12px; }

/* ── .sr-only ────────────────────────────────────────────────────────────────
   Was a local block in tool-ccpa-letter.html, which is the same defect as .flagrow
   being authored inline: a utility a page cannot render correctly without, present
   in the one place someone wrote it and absent everywhere else. Any page with a
   label that must be announced and not seen needs it, and getting it wrong makes
   content silently visible rather than silently hidden.
   clip-path, not clip: clip is deprecated, and clip-path does not create a
   containing block that traps a focusable descendant off-screen. */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

/* ── .sep ─────────────────────────────────────────────────────────────────────
   The middot chrome.js injects between the two legal links. Styled rather than
   left to inherit, because "it reads either way" is only true at the ink the
   surrounding text happens to have. It is a separator, so it is not a link and
   not text: lighter ink, its own space, and unselectable so copying the footer
   does not carry it.
   It should also stop being in the DOM — see the reply; a separator between two
   links is presentation and belongs in a ::before on the second link. This rule
   is what makes the markup correct in the meantime, and it stays harmless after. */
.sep { display: inline-block; padding: 0 8px; user-select: none;
  color: color-mix(in srgb, var(--color-text) 45%, transparent); }
