/* Examples cluster — new-design page styles (docs/DESIGN_SYSTEM.md).
   Serves BOTH the listing (/examples, .ex) and the detail pages
   (/examples/<slug>, .exd): one design surface, one stylesheet, so shared
   values live once (the single-edit-point guarantee).
   Layout only: cards, filter chips, pagination, buttons, pills and the table
   are DS components; values come from theme.css tokens. */

.ex { padding-top: 124px; padding-bottom: 88px; }

/* ── Hero: left-aligned, on the full content width ──
   This was a centred 64ch column first. Capping the intro at 64ch inside a
   1136px box leaves ~490px unused, and centring only moves that space to
   both sides rather than removing it — the text reads as stranded in the
   middle of the band instead of anchored to it, which is worse than the
   flush-left version it replaced. Reverted: the masthead now runs the same
   width as the card grid beneath it, so the whole page shares one left edge
   and one right edge. */

.ex__h1 { margin-top: 20px; }

.ex__intro {
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.7;
  color: var(--body-foreground);
  margin: 24px 0 0;
  text-wrap: pretty;
}

/* ── Filter row: chips left, search right ── */

.ex__filters {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-top: 32px;
}

.ex__chips { display: flex; flex-wrap: wrap; gap: 8px; }

/* A <label>, not a div, so the whole pill focuses the field — the icon and the
   14px of padding used to be dead space that swallowed taps. */
.ex__search {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
  width: 240px;
  min-height: 38px;
  padding: 0 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  background: var(--card);
  cursor: text;
}

.ex__search-icon { width: 14px; height: 14px; flex: none; color: var(--muted-foreground); }

/* The input itself is field(bare=true) — the label above draws the border.
   align-self: stretch so every pixel of the pill is the input's own hit area
   rather than the label's. */
.ex__search-input {
  align-self: stretch;
  min-width: 0;
  font-size: 13.5px;
}

/* ── Results ── */

.ex__section { display: flex; flex-direction: column; gap: 26px; margin-top: 30px; }

.ex__count {
  font-family: var(--font-sans);
  font-size: 12.5px;
  color: var(--muted-foreground);
  margin: 0;
}

/* Four across, per the canvas. minmax(0,1fr) — bare 1fr lets a long
   unbroken query title set the page width (hard rule 6). */
.ex__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
}

.ex__empty { padding: 48px 0; text-align: center; }

.ex__empty p {
  font-family: var(--font-sans);
  font-size: 16px;
  color: var(--muted-foreground);
  margin: 0;
}

/* ── Responsive ── */

@media (max-width: 1100px) {
  .ex__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 860px) {
  .ex__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ex__filters { flex-direction: column; align-items: stretch; }
  .ex__search { width: 100%; }
}

/* 44px tap target (shipping checklist #13) — the pill was 38px, and only the
   inner 24px of it was the input.

   `any-pointer: coarse`, matching the DS tap block. The comment here already
   claimed to be "keyed on the POINTER like the DS tap block in ds.css" while
   actually using the COMPOUND `(hover: none) and (pointer: coarse)` — which
   ds.css spends a paragraph explaining is wrong for tap sizing: it asks
   whether the PRIMARY input is a finger, so an iPad with a Magic Keyboard
   and a Surface with a mouse both report `hover: hover` and kept the 38px
   pill while being touched. The compound form is right for the iOS
   zoom-on-focus workaround (now in ds.css — moved there from the deleted
   app.css/marketing.css in stage 5) and docs-ds.css's search-hint toggle,
   a second documented exception for its own reason. */
@media (any-pointer: coarse) {
  .ex__search { min-height: 44px; }
}

@media (max-width: 560px) {
  .ex { padding-top: 108px; }
  .ex__grid { grid-template-columns: minmax(0, 1fr); }
}


/* ═══ Detail page (/examples/<slug>) ═════════════════════════ */

.exd { padding-top: 124px; padding-bottom: 88px; }

/* ── Editorial split ─────────────────────────────────────────────
   This page uses `.ds-split` (ds.css). It briefly had its own `.exd__split`,
   added and then removed within this branch — it never shipped, so there is
   no drift here to record, only the modifier below. */

/* Grid items whose track is content-sized elsewhere; explicit min-width so a
   long unbroken title can never push a column past its share. */
.exd__hero-main { min-width: 0; }

/* The hero is the same idea with the columns swapped in weight: the document
   header is the body and the CTA is the second column, bottom-aligned so the
   button sits on the intro's last line rather than floating. `auto` rather
   than a fraction — the column is exactly as wide as the pill. */
.exd__split--hero {
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 24px 48px;
  align-items: end;
  margin-top: 20px;
}

/* The modifier has to re-state the collapse, keyed to the SAME 1080px as
   `.ds-split` in ds.css. A media query does not raise specificity, so
   `.exd__split--hero` (0,1,0, in a stylesheet that loads after ds.css) beats
   `.ds-split` inside its collapse query on source order alone — the hero
   would have stayed two columns all the way down to 375px while every other
   split collapsed. Any `.ds-split` modifier that sets
   `grid-template-columns` owes itself this rule. */
@media (max-width: 1080px) {
  .exd__split--hero {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
    align-items: start;
  }
}

/* ── Hero ── */

.exd__breadcrumb {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-sans);
  font-size: 12.5px;
  color: var(--muted-foreground);
}

.exd__breadcrumb a { color: var(--muted-foreground); text-decoration: none; }

.exd__breadcrumb a:hover { color: var(--foreground); }

.exd__breadcrumb [aria-current] { color: var(--foreground); }

.exd__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 20px;
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--muted-foreground);
}

/* The meta row is the first thing in the hero's text column, so it carries no
   top margin of its own — `.exd__split--hero` owns the gap under the
   breadcrumb. */
.exd__meta:first-child { margin-top: 0; }

.exd__h1 { margin-top: 18px; max-width: 30ch; }

.exd__intro {
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.7;
  color: var(--body-foreground);
  margin: 18px 0 0;
  max-width: 76ch;
  text-wrap: pretty;
}

/* Inside the hero split the CTA is the right-hand column and needs no top
   margin; below 1080px the split collapses and it becomes a stacked block
   again (see the responsive section). */
.exd__cta { margin-top: 0; justify-content: flex-end; }

/* ── Results ── */

.exd__results { margin-top: 44px; }

.exd__results-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 14px;
}

.exd__table-shell {
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  background: var(--card);
  overflow: hidden;
}

/* The DS table macro brings .ds-table-wrap; inside the shell it must not
   draw a second border or corner. */
.exd__table-shell .ds-table-wrap { border: 0; border-radius: 0; background: transparent; }

.exd__table { font-family: var(--font-sans); width: 100%; }

/* Basecoat's .table sets nowrap on cells; a 250-char description then makes
   the row ~1900px and the whole table scrolls sideways. Descriptions must
   WRAP — fixed layout + these column widths (the legacy page's proportions)
   keep every row inside the shell.

   `table-layout` belongs on the <table>, which is why the macro is called with
   table_cls: `.exd__table` is the WRAPPER div, and a table-only property set
   there is silently inert. Under fixed layout the percentage widths below are
   authoritative, so no single long token can redistribute the columns. */
.exd__table-el { table-layout: fixed; width: 100%; }

.exd__table th { white-space: nowrap; }

.exd__table td { white-space: normal; vertical-align: top; }

.exd__table th:nth-child(1), .exd__table td:nth-child(1) { width: 18%; }
.exd__table th:nth-child(2), .exd__table td:nth-child(2) { width: 16%; }
.exd__table th:nth-child(3), .exd__table td:nth-child(3) { width: 44%; }
.exd__table th:nth-child(4), .exd__table td:nth-child(4) { width: 22%; }

/* Long domains shouldn't blow their column. */
.exd__table td:nth-child(2) { overflow-wrap: anywhere; }

.exd__company { font-size: 13.5px; font-weight: 500; color: var(--foreground); }

.exd__domain {
  font-size: 12.5px;
  color: var(--foreground);
  text-decoration: underline;
  text-decoration-color: var(--border);
  text-underline-offset: 2px;
}

.exd__domain:hover { text-decoration-color: var(--foreground); }

.exd__desc { font-size: 12.5px; line-height: 1.6; color: var(--body-foreground); }

.exd__row--faded { opacity: 0.5; }

/* Empty / error cell */
.exd__state { padding: 40px 20px; text-align: center; }

.exd__state-title { font-family: var(--font-sans); font-size: 14px; font-weight: 600; color: var(--foreground); margin: 0; }

.exd__state-sub { font-family: var(--font-sans); font-size: 13px; color: var(--muted-foreground); margin: 6px 0 0; }

/* Skeleton bars while the htmx fragment loads. The treatment (and its
   reduced-motion guard) is the DS `.ds-skeleton`; only the bar geometry is
   this page's. */
.exd__skeleton { height: 10px; border-radius: var(--radius-full); }

.exd__skeleton--name { width: 72%; }
.exd__skeleton--domain { width: 60%; }
.exd__skeleton--desc { width: 94%; }
.exd__skeleton--desc-short { width: 66%; margin-top: 6px; }
.exd__skeleton--hq { width: 54%; }

/* ── Lock band (anonymous visitors) ── */

.exd__lock {
  padding: 26px 24px;
  border-top: 1px solid var(--border);
  background: var(--muted);
  text-align: center;
}

.exd__lock-icon { width: 18px; height: 18px; color: var(--muted-foreground); }

.exd__lock-copy {
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 500;
  color: var(--foreground);
  margin: 10px 0 16px;
}

/* ── Signup band ── */

.exd__signup {
  margin-top: 44px;
  padding: 44px 32px;
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  background: var(--muted);
  text-align: center;
}

.exd__signup-h { margin: 12px auto 0; max-width: 30ch; }

.exd__signup-sub {
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.65;
  color: var(--body-foreground);
  margin: 14px auto 0;
  max-width: 56ch;
  text-wrap: pretty;
}

/* ── Related searches ── */

.exd__related { margin-top: 44px; }

.exd__related-head { display: flex; align-items: center; gap: 14px; }

.exd__rule { flex: 1; height: 1px; background: var(--border); }

.exd__related-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
  margin-top: 20px;
}

/* ── SEO prose ── */

.exd__seo {
  margin-top: 44px;
  padding-top: 30px;
  border-top: 1px solid var(--border);
  display: grid;
  gap: 30px;
}

.exd__seo-h {
  font-family: var(--font-sans);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--foreground);
  margin: 0;
}

/* Full content width under its heading. These were briefly a `.ds-split`;
   the rail was 35% full ("Why this is useful" is 143px of 410px), so the
   block bought an empty column at the cost of a narrower paragraph. */
.exd__seo-body {
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.7;
  color: var(--body-foreground);
  margin: 8px 0 0;
  text-wrap: pretty;
}

/* ── Detail responsive ── */

@media (max-width: 900px) {
  .exd__related-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Both splits collapse together at 860 — the width where the 0.62fr column
   stops holding a heading on one or two lines and the CTA column starts
   squeezing the h1. The stacked spacing each element had before the split
   comes back here, so a phone renders exactly what it used to. */
/* 1080px, matching `.exd__split--hero`'s own collapse above — NOT 860.
   Keyed at 860 this opened a 220px dead band: across 861-1080px the hero was
   already one column with `gap: 0` while the CTA still had `margin-top: 0`
   and `justify-content: flex-end`, so the pill sat jammed against the
   intro's last line and right-aligned to nothing. Measured at 900/950/1000px
   before the fix: gap 0px, pill at x=868 while the intro ended at x=799.
   Second instance of this exact mistake in this branch — the first was
   `.alt__body` in alternatives-ds.css. If the split's collapse point moves,
   both follow it. */
@media (max-width: 1080px) {
  .exd__cta { margin-top: 26px; justify-content: flex-start; }
}

/* LAYOUT, at 640 — the width where a 4-column table genuinely stops fitting.
   NOT re-keyed to 768 with the type floor: this block is the whole phone
   treatment (card stack, single-column related grid, stacked results bar), and
   moving it to 768 handed a small laptop window and iPad portrait the phone
   layout. The 641-768 band gets the real table, which measures 619px inside a
   619px wrapper at 700px. Type floors go at 768; layout goes where the layout
   breaks. */
@media (max-width: 640px) {
  .exd { padding-top: 108px; }
  .exd__related-grid { grid-template-columns: minmax(0, 1fr); }
  .exd__signup { padding: 32px 20px; }
  .exd__results-bar { flex-direction: column; align-items: flex-start; gap: 10px; }

  /* A 4-column data table cannot fit 375px, and per hard rule 6 an
     inner-scrolling wrapper is NOT enough for a table that is visible at
     load — mobile Chrome counts its full box into the root scroll area and
     pans the whole page. So each row becomes a stacked card and the column
     header comes from the cell's data-label.

     Overriding `display` off table/table-row/table-cell drops the implicit
     table roles in every engine, so the macro is called with stack_roles to
     state them explicitly — otherwise a screen-reader user loses row/column
     navigation exactly where the layout is hardest to follow. */
  .exd__table-el { display: block; min-width: 0; table-layout: auto; }

  .exd__table th:nth-child(n), .exd__table td:nth-child(n) { width: auto; }

  /* Visually hidden, NOT display:none. The header row has to stay in the
     accessibility tree or the columnheader-to-cell association goes with it,
     leaving the ::before labels — which are generated content, and NVDA on
     Firefox has never reliably exposed those — as the only column cue. */
  .exd__table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }

  .exd__table tbody { display: block; }

  .exd__table tbody tr {
    display: block;
    padding: 14px 16px;
    border-bottom: 1px solid var(--border);
  }

  .exd__table tbody td {
    display: grid;
    grid-template-columns: 84px minmax(0, 1fr);
    gap: 12px;
    align-items: baseline;
    padding: 4px 0;
    border: 0;
    font-size: 12.5px;
  }

  .exd__table tbody td::before {
    content: attr(data-label);
    font-family: var(--font-sans);
    font-size: 12px;
    color: var(--muted-foreground);
  }

  /* The empty/error cell spans the card, so it gets no label column. */
  .exd__table tbody td.exd__state { display: block; }

  .exd__table tbody td.exd__state::before { content: none; }
}

/* ── Withheld funding record (auto_funded "similar to X" pages) ──
   The redaction bars are EMPTY spans with fixed widths, never blurred real
   text: a blur is defeated by view-source and would leak funding numbers to
   crawlers (docs/BUSINESS_CONTEXT.md, "Funding record surfaced as a WITHHELD
   teaser"). Widths approximate each real value's footprint so the record
   reads as withheld rather than as a loading skeleton. */

.exd__funding {
  margin-top: 44px;
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  background: var(--card);
  padding: 26px 28px;
}

.exd__funding__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
}

.exd__funding__eyebrow { margin: 0; }

.exd__funding__title {
  font-family: var(--font-sans);
  font-size: 21px;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--foreground);
  margin: 10px 0 0;
}

.exd__funding__subtitle {
  font-family: var(--font-sans);
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--muted-foreground);
  margin: 8px 0 0;
  max-width: 60ch;
}

.exd__funding__actions {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 12px;
  flex: none;
}

.exd__funding__marker {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-sans);
  font-size: 11.5px;
  color: var(--muted-foreground);
  white-space: nowrap;
}

.exd__funding__marker::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: var(--radius-full);
  background: var(--accent);
}

.exd__funding__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  margin: 24px 0 0;
}

.exd__funding__cell { background: var(--card); padding: 16px 18px; }

.exd__funding__label {
  font-family: var(--font-sans);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-foreground);
}

.exd__funding__value {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  margin: 12px 0 0;
  min-height: 12px;
}

.exd__funding__redaction {
  display: block;
  height: 11px;
  border-radius: var(--radius-full);
  background: var(--muted-deep);
}

@media (max-width: 900px) {
  .exd__funding__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Type floor at 768 (the band the checklist specifies, matching ds.css). */
@media (max-width: 768px) {
  .exd__funding__marker { font-size: 12px; }
}

/* LAYOUT stays at 640, where it was. Splitting these apart because moving the
   floor to 768 moved the layout with it: a mixed block re-keyed wholesale gave
   641-768 the phone treatment, which is a visual change to a signed-off page
   from a change whose scope was the type floor. Type and layout answer
   different questions and get different breakpoints. */
@media (max-width: 640px) {
  .exd__funding { padding: 22px 20px; }
  .exd__funding__head { flex-direction: column; }
  .exd__funding__actions { flex-direction: row; align-items: center; }
}

/* ── 44px tap targets for this page's OWN controls ───────────────────────
   ds.css's `any-pointer: coarse` block only reaches `.ds-*` selectors, so a
   page-local control matches nothing in it. The breadcrumb link is a real
   standalone navigation target (its `nav` holds nothing but links, so the
   WCAG 2.5.5 inline-text exemption does not apply) and sits at 18px. Same
   pointer key and reasoning as ds.css — read the long comment there before
   changing the query. */
@media (any-pointer: coarse) {
  .exd__breadcrumb a { display: inline-flex; align-items: center; min-height: 44px; }

  /* The company domain in each results row. Below 640px the table becomes a
     card stack, and the link is then the whole content of its own cell — so
     it is a standalone target at 18px, not a link inside a sentence, and the
     WCAG 2.5.5 inline exemption does not cover it. Ten of them stack down
     the page, which is where a reader is most likely to hit the wrong one. */
  .exd__domain { display: inline-flex; align-items: center; min-height: 44px; }
}
