/* DISCOVER — the light side of ADA.
 *
 * The Virtual Lab is neon-on-black; DISCOVER is its inverse. That inversion is
 * deliberate but NOT literal: the Lab's accents are engineered to glow on a
 * dark field and collapse on white (--teal #34e8d0 measures 1.54:1 against
 * white, --purple #a78bfa measures 2.72:1 — both unreadable as text).
 *
 * So the same hues are kept and the lightness is moved instead. Contrast
 * ratios against #ffffff, all AA or better for their use:
 *   --purple  #6d28d9  7.10:1   primary, links, headings
 *   --teal    #0f766e  5.47:1   secondary text accents
 *   --text    #16121f  17.4:1   body
 *   --text-2  #56506b   7.62:1  supporting copy
 *   --text-3  #6f6885   5.26:1  meta / labels
 * The Lab's neon values survive only as decorative fills, borders and glows,
 * where contrast minimums do not apply.
 *
 * app.css is not reused: it pins html/body to overflow:hidden for the Lab's
 * fixed grid, which a scrolling page cannot use. */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
img { display: block; }
button { cursor: pointer; font-family: inherit; }

:root {
  --bg: #ffffff;
  --bg-tint: #faf8ff;
  --surface: #ffffff;
  --surface-2: #f6f3fd;
  --surface-3: #ece7f8;
  --border: #e7e2f2;
  --border-bright: #d3cae9;

  /* Readable primaries */
  --purple: #6d28d9;
  --purple-strong: #4c1d95;
  --purple-soft: #f4efff;
  --teal: #0f766e;
  --teal-soft: #e6f7f4;

  /* Lab neons — decoration only, never text */
  --neon-purple: #a78bfa;
  --neon-teal: #34e8d0;

  --gold: #7a5d09;
  --gold-soft: #fdf6e0;
  --gold-line: #e8c547;

  --text: #16121f;
  --text-2: #56506b;
  --text-3: #6f6885;

  --font-sans: 'IBM Plex Sans', system-ui, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, monospace;

  --maxw: 1180px;
  --shadow-sm: 0 1px 2px rgba(22, 18, 31, .05);
  --shadow-md: 0 6px 22px rgba(76, 29, 149, .09);
  --shadow-lg: 0 18px 48px rgba(76, 29, 149, .14);
}

html { scroll-behavior: smooth; background: var(--bg); }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  min-height: 100%;
}

a { color: inherit; }

/* ------------------------------------------------------------------ header */

.dv-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(255, 255, 255, .86);
  backdrop-filter: blur(14px) saturate(1.6);
  -webkit-backdrop-filter: blur(14px) saturate(1.6);
  border-bottom: 1px solid var(--border);
}

.dv-header-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 18px;
  height: 60px;
  display: flex;
  align-items: center;
  gap: 14px;
}

.dv-brand { display: flex; align-items: center; flex-shrink: 0; }
.dv-brand-logo { height: 26px; width: auto; }

/* Globe, top-right of a card. Quiet on purpose — it is a status, not a badge,
   and it sits opposite the verified seal without competing with it. */
/* Needs to out-specify `.dv-card > *`, which sets position:relative on every
   child and is declared later in this file. */
.dv-card > .dv-card-globe {
  position: absolute;
  top: 12px;
  right: 13px;
  z-index: 2;
  font-size: .82rem;
  line-height: 1;
  opacity: .38;
  cursor: help;
  transition: opacity .15s ease, transform .15s ease;
}
.dv-card:hover .dv-card-globe { opacity: .72; }
.dv-card-globe:hover { opacity: 1; transform: scale(1.12); }

/* Instagram's own gradient, so the mark is recognisable at a glance rather
   than being one more grey icon in a row. */
.dv-social--instagram .dv-glyph { color: #E1306C; }
.dv-social--instagram:hover {
  border-color: rgba(225, 48, 108, .45);
  background: rgba(225, 48, 108, .07);
}
.dv-social--tiktok .dv-glyph { color: #010101; }
.dv-social--tiktok:hover {
  border-color: rgba(37, 244, 238, .55);
  background: rgba(37, 244, 238, .09);
}

/* The placeholder slot: present, obviously inactive, not clickable. */
.dv-social.is-empty {
  opacity: .34;
  cursor: default;
  pointer-events: none;
  border-style: dashed;
}
.dv-social.is-empty .dv-glyph { color: var(--text-3); }

/* Mark in front of a category name. */
.dv-filter-mark { margin-right: 6px; font-size: .95em; line-height: 1; }

/* Header CTA. Outlined rather than filled, because the active tab in the mode
   switch beside it is already a solid purple pill and two of those next to
   each other read as one confused control. margin-left:auto does the job the
   old flex spacer did. --purple on white is 7.10:1. */
.dv-signup {
  margin-left: auto;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  padding: 9px 16px;
  border-radius: 999px;
  border: 1px solid var(--purple);
  background: var(--surface);
  color: var(--purple);
  font-size: .78rem;
  font-weight: 700;
  white-space: nowrap;
  text-decoration: none;
  transition: background .15s ease, color .15s ease, box-shadow .15s ease;
}
.dv-signup:hover,
.dv-signup:focus-visible {
  background: var(--purple);
  color: #fff;
  box-shadow: 0 6px 18px rgba(109, 40, 217, .22);
}
.dv-signup:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; }

/* Mode switch — the counterpart of .mode-switch in app.css. Same control and
   same class names, inverted surface, so the two halves of ADA read as one
   product rather than two sites. */
.mode-switch {
  display: flex;
  gap: 3px;
  padding: 3px;
  border-radius: 999px;
  border: 1px solid var(--border-bright);
  background: var(--surface-2);
  flex-shrink: 0;
  box-shadow: inset 0 1px 2px rgba(22, 18, 31, .05);
}

.mode-tab {
  display: flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-mono);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 9px 16px;
  border-radius: 999px;
  color: var(--text-3);
  white-space: nowrap;
  transition: color .18s, background .18s, box-shadow .18s;
}
.mode-tab-icon { width: 15px; height: auto; flex-shrink: 0; }

a.mode-tab:hover { color: var(--text); background: var(--surface-3); }

.mode-tab.is-active {
  background: linear-gradient(135deg, var(--purple) 0%, var(--purple-strong) 100%);
  color: #ffffff;
  box-shadow: 0 2px 8px rgba(76, 29, 149, .3);
}

/* The Lab is the dark side — preview it with an inked chip on hover, the
   mirror of how the Lab's switch previews purple. */
a.mode-tab[href*="lab"]:hover {
  background: #14111d;
  color: var(--neon-teal);
  box-shadow: 0 2px 10px rgba(20, 17, 29, .3);
}

.mode-tab:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; }
a.mode-tab[href*="lab"]:focus-visible { outline-color: #14111d; }

/* -------------------------------------------------------------------- hero */

.dv-hero {
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--border);
  background:
    radial-gradient(ellipse 120% 90% at 50% 0%, #f3ecff 0%, #fbf9ff 46%, #ffffff 100%);
}

/* Neon reused as a wash rather than as ink. */
.dv-hero-glow {
  position: absolute;
  top: -55%;
  left: 50%;
  transform: translateX(-50%);
  width: min(820px, 135vw);
  height: min(820px, 135vw);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(167, 139, 250, .22) 0%, rgba(52, 232, 208, .07) 45%, transparent 70%);
  pointer-events: none;
}

.dv-hero-scan {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    0deg, transparent, transparent 3px,
    rgba(109, 40, 217, .018) 3px, rgba(109, 40, 217, .018) 4px
  );
  pointer-events: none;
}

.dv-hero-inner {
  position: relative;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 74px 18px 60px;
  text-align: center;
}

.dv-hero-eyebrow {
  font-family: var(--font-mono);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: var(--purple);
  margin-bottom: 16px;
}

.dv-hero-title {
  font-size: clamp(2.7rem, 9vw, 4.6rem);
  font-weight: 700;
  letter-spacing: .06em;
  line-height: 1.04;
  margin-bottom: 20px;
  background: linear-gradient(135deg, #16121f 0%, #4c1d95 58%, #6d28d9 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
/* Gradient text disappears in forced-colors mode; give it a solid fallback. */
@media (forced-colors: active) {
  .dv-hero-title { color: CanvasText; background: none; }
}

.dv-hero-sub {
  max-width: 620px;
  margin: 0 auto 26px;
  color: var(--text-2);
  font-size: 1.02rem;
}

.dv-hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
}

/* -------------------------------------------------------------------- body */

.dv-main { display: flex; flex-direction: column; }
.dv-hero   { order: 1; }
.dv-body   { order: 2; }
.dv-outro  { order: 3; }
.dv-labcta { order: 4; }

.dv-body { max-width: var(--maxw); margin: 0 auto; padding: 30px 18px 20px; width: 100%; }

/* ------------------------------------------------------------- kind tabs */
/* The primary axis: what a listing IS. Sits above search because choosing
   "Firmware" reframes everything below it. */

.dv-kinds {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  margin-bottom: 16px;
  border-radius: 12px;
  border: 1px solid var(--border-bright);
  background: var(--surface-2);
  box-shadow: inset 0 1px 2px rgba(22, 18, 31, .05);
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.dv-kinds::-webkit-scrollbar { display: none; }

.dv-kind {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-shrink: 0;
  font-family: var(--font-sans);
  font-size: .9rem;
  font-weight: 600;
  padding: 9px 18px;
  border-radius: 9px;
  border: none;
  background: transparent;
  color: var(--text-2);
  white-space: nowrap;
  transition: color .16s, background .16s, box-shadow .16s;
}
.dv-kind:hover { color: var(--text); background: rgba(255, 255, 255, .7); }

.dv-kind.is-active {
  background: var(--surface);
  color: var(--purple);
  box-shadow: 0 1px 3px rgba(22, 18, 31, .12);
}

.dv-kind-count {
  font-family: var(--font-mono);
  font-size: .66rem;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 20px;
  background: var(--surface-3);
  color: var(--text-3);
}
.dv-kind.is-active .dv-kind-count { background: var(--purple-soft); color: var(--purple); }

/* Nothing to show under the current category — dim it rather than hide it, so
   the shape of the index stays visible. */
.dv-kind.is-empty { opacity: .45; }
.dv-kind.is-empty:hover { opacity: .7; }

.dv-toolbar { margin-bottom: 14px; }

.dv-search-wrap { position: relative; flex: 1; min-width: 220px; }

.dv-search-icon {
  position: absolute;
  left: 14px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-3);
  font-size: 1.05rem;
  pointer-events: none;
}

.dv-search {
  width: 100%;
  padding: 12px 14px 12px 38px;
  border-radius: 10px;
  border: 1px solid var(--border-bright);
  background: var(--surface);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: .94rem;
  box-shadow: var(--shadow-sm);
  transition: border-color .18s, box-shadow .18s;
}
.dv-search::placeholder { color: var(--text-3); }
.dv-search:focus {
  outline: none;
  border-color: var(--purple);
  box-shadow: 0 0 0 3px rgba(109, 40, 217, .14);
}

.dv-count {
  font-family: var(--font-mono);
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-3);
  white-space: nowrap;
}

/* ----------------------------------------------------------------- filters */

.dv-filters { margin-bottom: 28px; }

.dv-filter-row {
  display: flex;
  gap: 7px;
  overflow-x: auto;
  padding-bottom: 8px;
  scrollbar-width: thin;
  scrollbar-color: var(--border-bright) transparent;
  -webkit-overflow-scrolling: touch;
}
.dv-filter-row::-webkit-scrollbar { height: 4px; }
.dv-filter-row::-webkit-scrollbar-thumb { background: var(--border-bright); border-radius: 4px; }

.dv-filter-row--sub { margin-top: 4px; }

.dv-filter {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 8px 15px;
  border-radius: 20px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-2);
  white-space: nowrap;
  transition: border-color .16s, color .16s, background .16s, box-shadow .16s;
}
.dv-filter:hover {
  border-color: var(--border-bright);
  color: var(--text);
  background: var(--surface-2);
}
.dv-filter.is-active {
  border-color: var(--purple);
  background: var(--purple);
  color: #ffffff;
  box-shadow: 0 2px 8px rgba(76, 29, 149, .24);
}


.dv-filter-count {
  font-size: .9em;
  opacity: .65;
  margin-left: 7px;
  font-variant-numeric: tabular-nums;
}

/* Sub-filters read as a quieter tier so the hierarchy is obvious at a glance. */
.dv-filter-row--sub .dv-filter.is-active {
  border-color: rgba(15, 118, 110, .4);
  background: var(--teal-soft);
  color: var(--teal);
  box-shadow: none;
}

/* ------------------------------------------------------------------- cards */

.dv-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 18px;
}

.dv-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 13px;
  min-height: 232px;
  padding: 22px;
  border-radius: 16px;
  border: 1px solid var(--border);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  transition: border-color .2s, transform .2s, box-shadow .2s;
}

/* Most listings are a handle, two chips and one link, which left a hole in
   the lower half of every card. This fills it with the same diagonal the
   landing page splits on, so the empty space becomes a motif rather than a
   gap. Purely decorative and behind the content. */
.dv-card::after {
  content: "";
  position: absolute;
  right: -30px;
  bottom: -30px;
  width: 170px;
  height: 170px;
  background: linear-gradient(135deg, transparent 48%, var(--purple-soft) 48%);
  opacity: .85;
  pointer-events: none;
  transition: transform .35s cubic-bezier(.22, 1, .36, 1), opacity .3s;
}
.dv-card:hover::after { transform: translate(-8px, -8px); opacity: 1; }
.dv-card > * { position: relative; z-index: 1; }

/* A large, very faint monogram sitting under the diagonal — the card carries
   the listing's own mark instead of blank white. */
.dv-card-namelink {
  color: inherit;
  text-decoration: none;
}
.dv-card-namelink:hover { color: var(--purple); text-decoration: underline; text-underline-offset: 3px; }
.dv-card-namelink:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; border-radius: 3px; }

/* Quiet by design: the shareable page matters to the person listed, not to
   the hundred visitors scanning past them. */
.dv-card-share {
  position: absolute;
  right: 18px;
  bottom: 18px;
  z-index: 2;
  font-family: var(--font-mono);
  font-size: .62rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--text-3);
  opacity: 0;
  transition: opacity .18s, color .18s;
}
.dv-card:hover .dv-card-share,
.dv-card-share:focus-visible { opacity: 1; }
.dv-card-share:hover { color: var(--purple); }
.dv-card-share:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; border-radius: 3px; }

.dv-card-mark {
  position: absolute;
  right: 16px;
  bottom: 8px;
  z-index: 0;
  font-family: var(--font-mono);
  font-size: 3.4rem;
  font-weight: 700;
  letter-spacing: -.04em;
  line-height: 1;
  color: var(--purple);
  opacity: .13;
  pointer-events: none;
  user-select: none;
}

.dv-card:hover {
  border-color: var(--border-bright);
  transform: translateY(-4px);
  box-shadow: var(--shadow-md);
}

.dv-card.is-featured { border-color: var(--gold-line); }
.dv-card.is-featured::after {
  background: linear-gradient(135deg, transparent 48%, var(--gold-soft) 48%);
}
.dv-card.is-featured .dv-card-namelink {
  color: inherit;
  text-decoration: none;
}
.dv-card-namelink:hover { color: var(--purple); text-decoration: underline; text-underline-offset: 3px; }
.dv-card-namelink:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; border-radius: 3px; }

/* Quiet by design: the shareable page matters to the person listed, not to
   the hundred visitors scanning past them. */
.dv-card-share {
  position: absolute;
  right: 18px;
  bottom: 18px;
  z-index: 2;
  font-family: var(--font-mono);
  font-size: .62rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--text-3);
  opacity: 0;
  transition: opacity .18s, color .18s;
}
.dv-card:hover .dv-card-share,
.dv-card-share:focus-visible { opacity: 1; }
.dv-card-share:hover { color: var(--purple); }
.dv-card-share:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; border-radius: 3px; }

.dv-card-mark { color: var(--gold-line); opacity: .3; }
.dv-card.is-featured:hover { box-shadow: 0 18px 40px rgba(232, 197, 71, .26); }

.dv-card-head { display: flex; align-items: center; gap: 13px; }

/* Monogram avatar — remote profile images are blocked by img-src 'self',
   and hot-linking someone's photo without asking would be rude anyway. */
/* Circular, like a profile picture, with a silhouette instead of a photo.
   Remote images are blocked by img-src 'self' and hot-linking someone's
   picture without asking would be rude anyway.

   Grey by default and on purpose: 104 differently coloured avatars competed
   with the purple category chips, which are the thing actually worth reading.
   A listing that sets `avatar_hue` opts into colour; everything else stays
   quiet. */
.dv-avatar {
  flex-shrink: 0;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  overflow: hidden;
  background: #e6e3ee;
  box-shadow: inset 0 0 0 1px rgba(22, 18, 31, .06);
}

.dv-avatar-figure {
  width: 82%;
  height: 82%;
  display: block;
  fill: #b3aec2;
}

/* Only when a hue has been chosen deliberately. */
.dv-avatar--tinted {
  background: linear-gradient(150deg,
    hsl(var(--dv-hue) 62% 62%) 0%,
    hsl(var(--dv-hue) 58% 48%) 100%);
  box-shadow: inset 0 0 0 1px hsl(var(--dv-hue) 45% 42% / .35);
}
.dv-avatar--tinted .dv-avatar-figure { fill: #ffffff; opacity: .94; }
/* The vendor mark is a storefront rather than a person, and sits centred. */
.dv-card--vendor .dv-avatar { align-items: center; }
.dv-card--vendor .dv-avatar-figure { width: 62%; height: 62%; }

.dv-card-ident { min-width: 0; flex: 1; }
/* Handles are short, but project and vendor names ("Universal Radio Hacker",
   "Great Scott Gadgets") are not — wrap to two lines rather than truncating
   the thing the card exists to name. */
.dv-card-name {
  font-size: 1.18rem;
  font-weight: 600;
  line-height: 1.25;
  color: var(--text);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}


.dv-card-cat {
  font-family: var(--font-mono);
  font-size: .64rem;
  font-weight: 600;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-top: 3px;
}

.dv-card-tagline { font-size: .9rem; font-weight: 600; color: var(--purple); }
.dv-card-bio { font-size: .92rem; color: var(--text-2); line-height: 1.55; }

.dv-card-flags { display: flex; flex-wrap: wrap; gap: 6px; }

.dv-badge {
  font-family: var(--font-mono);
  font-size: .57rem;
  font-weight: 700;
  letter-spacing: .12em;
  padding: 4px 9px;
  border-radius: 5px;
}
.dv-badge--featured { background: var(--gold-soft); border: 1px solid var(--gold-line); color: var(--gold); }

/* A vendor is an organisation, not a person — squarer avatar, purple accent. */
.dv-card--vendor .dv-avatar { border-radius: 14px; }
.dv-card--vendor .dv-card-cat { color: var(--purple); }

/* Category chips — what a creator makes content about. Each of the ten
   categories owns a hue so the grid is scannable before it is read. Every
   pairing below was measured against its own tint at AA or better. */
.dv-specialties {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.dv-specialty {
  font-family: var(--font-mono);
  font-size: .65rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  padding: 6px 10px;
  border-radius: 7px;
  background: var(--purple-soft);
  border: 1px solid rgba(109, 40, 217, .2);
  color: var(--purple);
}

/* Verification seal — the familiar scalloped platform badge, in ADA purple.
   Sits inline inside .dv-card-name so it trails the last word like a glyph. */
/* Top-right of the card, where a badge is expected. */
.dv-verified-wrap {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 2;
  line-height: 0;
}

.dv-verified { width: 22px; height: 22px; display: block; }

/* The rounded stroke join is what turns a 12-point star into soft lobes. */
.dv-verified-seal {
  fill: var(--purple);
  stroke: var(--purple);
  stroke-width: 2.4;
  stroke-linejoin: round;
}

.dv-verified-tick {
  fill: none;
  stroke: #ffffff;
  stroke-width: 2.3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.dv-card-links {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: auto;
  padding-top: 8px;
  max-width: 78%;
}

.dv-social {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  font-family: var(--font-mono);
  font-size: .74rem;
  font-weight: 600;
  letter-spacing: .02em;
  text-decoration: none;
  padding: 8px 12px;
  border-radius: 9px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-2);
  transition: border-color .16s, color .16s, background .16s, transform .16s;
}
.dv-social:hover { transform: translateY(-1px); }

.dv-glyph { width: 17px; height: 17px; flex-shrink: 0; display: block; }
.dv-glyph-stroke { fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.dv-glyph-fill { fill: currentColor; }

.dv-social-handle { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Each platform lights up in its own colour on hover, so the row of links is
   recognisable at a glance rather than a run of identical grey pills. */
.dv-social--instagram:hover { border-color: #c13584; color: #c13584; background: #fdf2f8; }
.dv-social--tiktok:hover    { border-color: #16121f; color: #16121f; background: #f4f4f6; }
.dv-social--youtube:hover   { border-color: #c81e1e; color: #c81e1e; background: #fef2f2; }
.dv-social--github:hover    { border-color: #24292f; color: #24292f; background: #f3f4f6; }
.dv-social--web:hover       { border-color: var(--purple); color: var(--purple); background: var(--purple-soft); }
.dv-social:hover {
  border-color: var(--purple);
  color: var(--purple);
  background: var(--purple-soft);
}
.dv-social:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; }

/* ------------------------------------------------------- status and empty */

.dv-status {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 48px 18px;
  font-family: var(--font-mono);
  font-size: .76rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-3);
}
.dv-status[hidden] { display: none; }
.dv-status.is-error { color: #a1341c; }

.dv-spinner {
  width: 13px;
  height: 13px;
  border-radius: 50%;
  border: 2px solid var(--surface-3);
  border-top-color: var(--purple);
  animation: dv-spin .75s linear infinite;
}
@keyframes dv-spin { to { transform: rotate(360deg); } }

.dv-empty { padding: 56px 18px; text-align: center; }
.dv-empty[hidden] { display: none; }
.dv-empty-title { font-size: 1.08rem; font-weight: 600; color: var(--text); margin-bottom: 6px; }
.dv-empty-sub { font-size: .9rem; color: var(--text-3); }

/* ------------------------------------------------------------------- outro */

.dv-outro { max-width: var(--maxw); margin: 0 auto; padding: 28px 18px 34px; }

.dv-outro-card {
  padding: 40px 28px;
  border-radius: 20px;
  border: 1px solid var(--border);
  background:
    radial-gradient(ellipse 90% 130% at 100% 0%, rgba(167, 139, 250, .17) 0%, transparent 62%),
    radial-gradient(ellipse 80% 120% at 0% 100%, rgba(52, 232, 208, .12) 0%, transparent 60%),
    var(--bg-tint);
  text-align: center;
}

.dv-outro-title { font-size: 1.42rem; font-weight: 700; color: var(--text); margin-bottom: 10px; }
.dv-outro-sub { max-width: 520px; margin: 0 auto 24px; font-size: .94rem; color: var(--text-2); }
.dv-outro-actions { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }

.dv-btn {
  font-family: var(--font-mono);
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 13px 24px;
  border-radius: 10px;
  transition: transform .15s, box-shadow .18s, border-color .18s, color .18s, background .18s;
}
.dv-btn:active { transform: translateY(1px); }
.dv-btn:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; }

.dv-btn--primary {
  background: linear-gradient(135deg, var(--purple) 0%, var(--purple-strong) 100%);
  color: #ffffff;
  border: none;
  box-shadow: 0 6px 18px rgba(76, 29, 149, .28);
}
.dv-btn--primary:hover { box-shadow: 0 10px 26px rgba(76, 29, 149, .38); }

.dv-btn--ghost {
  background: var(--surface);
  border: 1px solid var(--border-bright);
  color: var(--text-2);
}
.dv-btn--ghost:hover { border-color: var(--purple); color: var(--purple); background: var(--purple-soft); }

/* Vendors ask on the same footing as creators, so the second action is a
   peer of the first rather than a faint afterthought. */
.dv-btn--outline {
  background: var(--surface);
  border: 1px solid var(--purple);
  color: var(--purple);
}
.dv-btn--outline:hover { background: var(--purple-soft); box-shadow: 0 4px 14px rgba(76, 29, 149, .16); }

.dv-outro-note {
  max-width: 560px;
  margin: 0 auto;
  font-size: .82rem;
  line-height: 1.6;
  color: var(--text-3);
}
.dv-outro-note a { color: var(--purple); text-decoration: underline; text-underline-offset: 2px; }
.dv-outro-note a:hover { color: var(--purple-strong); }

/* The Lab hand-off always sits last, even when the join block moves up. */
.dv-labcta {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 18px 56px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
}

/* ------------------------------------------------------------------ footer */

.dv-footer { border-top: 1px solid var(--border); background: var(--bg-tint); }

.dv-footer-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 24px 18px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}

.dv-footer-note {
  flex-basis: 100%;
  max-width: 620px;
  font-size: .76rem;
  line-height: 1.6;
  color: var(--text-3);
}

.dv-footer-brand {
  font-family: var(--font-mono);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-3);
}

.dv-footer-links { display: flex; gap: 18px; }

.dv-footer-links a {
  font-size: .83rem;
  color: var(--text-2);
  text-decoration: none;
  transition: color .16s;
}
.dv-footer-links a:hover { color: var(--purple); text-decoration: underline; text-underline-offset: 3px; }
.dv-footer-links a:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; }

/* ------------------------------------------------------------------ mobile */

@media (max-width: 720px) {
  .dv-header-inner { height: 58px; padding: 0 14px; gap: 10px; }
  .dv-signup { padding: 8px 13px; font-size: .72rem; }
  .dv-signup-more { display: none; }
  .dv-brand-logo { height: 22px; }
  .mode-tab { font-size: .62rem; padding: 12px; gap: 6px; letter-spacing: .05em; min-height: 40px; justify-content: center; }
  .dv-signup { min-height: 40px; }
  .mode-tab-icon { width: 13px; }
}

/* Below this the logo and a full-width switch stop coexisting on one line, so
   the switch takes the row and the wordmark drops to its icon. */
@media (max-width: 460px) {
  .dv-header-inner { gap: 8px; }
  .mode-switch { flex: 1; }
  .mode-tab { flex: 1; justify-content: center; padding: 8px 6px; }
  .dv-brand-logo { height: 20px; }
}

@media (max-width: 640px) {
  /* On a phone the invitation comes before the list. Scrolling past a hundred
     names to reach "you belong here" gets the order exactly backwards. */
  .dv-outro { order: 2; padding: 22px 16px 4px; }
  .dv-body  { order: 3; }
  .dv-labcta { padding: 0 16px 44px; }

  .dv-hero-inner { padding: 50px 16px 44px; }
  .dv-body { padding: 28px 16px 16px; }
  .dv-grid { grid-template-columns: 1fr; }
  .dv-count { width: 100%; }
  .dv-outro-card { padding: 30px 20px; }
  .dv-footer-inner { flex-direction: column; text-align: center; }

  /* Bleed the scrolling rows to the screen edge so they read as swipeable. */
  .dv-filter-row,
  .dv-kinds {
    margin-left: -16px;
    margin-right: -16px;
    padding-left: 16px;
    padding-right: 16px;
  }
  .dv-kind { font-size: .86rem; padding: 8px 13px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

.dv-filter:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; }


/* ---------------------------------------------------------------------------
   Shareable listing page  —  /discover/<slug>/
   Generated as static HTML by tools/build_discover_pages.py, because link
   previews are read from the server's HTML and never run JavaScript.
   --------------------------------------------------------------------------- */

.dvp-main {
  max-width: 620px;
  margin: 0 auto;
  padding: 56px 18px 72px;
}

/* The only route back used to be a text link buried mid-sentence in the card
   footer, which reads as a citation rather than as navigation. */
.dvp-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 18px;
  padding: 7px 14px 7px 10px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface);
  font-size: .85rem;
  font-weight: 600;
  color: var(--text-2);
  text-decoration: none;
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.dvp-back:hover,
.dvp-back:focus-visible {
  color: var(--purple);
  border-color: var(--purple);
  background: var(--purple-soft);
}
.dvp-back-arrow {
  width: 16px;
  height: 16px;
  transition: transform .15s ease;
}
.dvp-back:hover .dvp-back-arrow { transform: translateX(-2px); }

.dvp-card {
  position: relative;
  overflow: hidden;
  padding: 40px 32px 34px;
  border-radius: 20px;
  border: 1px solid var(--border);
  background: var(--surface);
  box-shadow: var(--shadow-md);
  text-align: center;
}

/* Same diagonal as the directory cards, so a shared page is recognisably
   part of the same product. */
.dvp-card::after {
  content: "";
  position: absolute;
  right: -40px;
  bottom: -40px;
  width: 230px;
  height: 230px;
  background: linear-gradient(135deg, transparent 48%, var(--purple-soft) 48%);
  pointer-events: none;
}
.dvp-card > * { position: relative; z-index: 1; }

.dvp-avatar {
  width: 96px;
  height: 96px;
  margin: 0 auto 20px;
  border-radius: 50%;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  overflow: hidden;
  background: #e6e3ee;
  box-shadow: inset 0 0 0 1px rgba(22, 18, 31, .06);
}

.dvp-name {
  font-size: clamp(1.5rem, 5vw, 2rem);
  font-weight: 700;
  color: var(--text);
  overflow-wrap: anywhere;
  margin-bottom: 6px;
}

.dvp-verified {
  font-family: var(--font-mono);
  font-size: .66rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--purple);
  margin-bottom: 4px;
}

.dvp-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: center;
  margin: 16px 0 4px;
}

.dvp-chip {
  font-family: var(--font-mono);
  font-size: .65rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  padding: 6px 11px;
  border-radius: 7px;
  background: var(--purple-soft);
  border: 1px solid rgba(109, 40, 217, .2);
  color: var(--purple);
}

.dvp-blurb {
  margin: 16px auto 0;
  max-width: 44ch;
  color: var(--text-2);
  font-size: .95rem;
}

.dvp-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  margin-top: 24px;
}

.dvp-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: .76rem;
  font-weight: 600;
  text-decoration: none;
  padding: 10px 14px;
  border-radius: 9px;
  border: 1px solid var(--border-bright);
  background: var(--surface);
  color: var(--text-2);
  transition: border-color .16s, color .16s, background .16s, transform .16s;
}
.dvp-link:hover {
  border-color: var(--purple);
  color: var(--purple);
  background: var(--purple-soft);
  transform: translateY(-1px);
}
.dvp-link:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; }

.dvp-link-glyph { width: 16px; height: 16px; flex-shrink: 0; }
/* The platform is named, not just drawn: two handles that happen to match
   were indistinguishable when only the handle was shown. */
.dvp-link-platform { font-weight: 700; }
.dvp-link-platform::after { content: ":"; }
.dvp-link-handle { color: var(--text-3); }
.dvp-link:hover .dvp-link-handle { color: inherit; }

/* Deliberately quieter than the social links above it. The person's own
   accounts are the point of the page; sharing is a convenience, and a filled
   purple button made it read as the thing being asked of you. */
.dvp-share {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  margin: 18px auto 0;
  padding: 8px 15px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-3);
  font-family: inherit;
  font-size: .78rem;
  font-weight: 600;
  cursor: pointer;
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.dvp-share:hover,
.dvp-share:focus-visible {
  color: var(--purple);
  border-color: var(--purple);
  background: var(--purple-soft);
}
.dvp-share:focus-visible { outline: 2px solid var(--purple); outline-offset: 2px; }
.dvp-share-icon { flex-shrink: 0; width: 15px; height: 15px; }

/* Confirmation must not resize the control, or it shifts under the finger
   that just pressed it. */
.dvp-share.is-done { color: #0f766e; border-color: #0f766e; background: rgba(15,118,110,.07); }

.dvp-foot {
  margin-top: 28px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
  font-size: .84rem;
  color: var(--text-3);
}
.dvp-foot a { color: var(--purple); text-decoration: underline; text-underline-offset: 3px; }

.dvp-note {
  margin-top: 22px;
  text-align: center;
  font-size: .76rem;
  line-height: 1.6;
  color: var(--text-3);
}
.dvp-note a { color: var(--purple); text-decoration: underline; text-underline-offset: 2px; }

@media (max-width: 560px) {
  .dvp-main { padding: 34px 16px 56px; }
  .dvp-card { padding: 32px 22px 26px; }
  .dvp-avatar { width: 84px; height: 84px; }
}
