MoonshotAI Kimi K3.1 Pro – Society

via Moonshot AI · Generated

  • AIMAC Debt 5.14
  • Cost $0.52
  • Total Violations 27
  • HTML Size 126 KB
  • Em Dashes 13

Screenshot

View MoonshotAI Kimi K3.1 Pro Society page View Live Page

Accessibility Issues Found

27 Serious

  • color-contrast serious 27 instances

    Elements must meet minimum color contrast ratio thresholds

    Example HTML <span class="brand-tagline">Many voices. One shared future.</span>

Artifacts

View Generated HTML
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="description" content="Civic Thread Alliance brings neighbors, cultural organizations, and local advocates together to build inclusive communities and lasting policy change.">
  <meta name="theme-color" content="#173b35">
  <meta property="og:type" content="website">
  <meta property="og:title" content="Civic Thread Alliance | Many voices. One shared future.">
  <meta property="og:description" content="Join a people-powered alliance turning lived experience into inclusive neighborhoods, stronger communities, and lasting public policy.">
  <meta property="og:image" content="https://picsum.photos/seed/civic-assembly/1200/630">
  <title>Civic Thread Alliance | Many voices. One shared future.</title>

  <link rel="icon" href="https://placehold.co/64x64/173b35/f7f3eb?text=CT&font=montserrat">
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&amp;family=Fraunces:opsz,wght@9..144,500;9..144,600;9..144,700&amp;display=swap" rel="stylesheet">

  <script>document.documentElement.classList.add('js');</script>

  <style>
    :root {
      --ink: #173b35;
      --ink-deep: #0c2925;
      --paper: #f7f3eb;
      --white: #fffdf8;
      --sage: #e4ebe0;
      --sage-deep: #c7d7c3;
      --coral: #e97556;
      --sun: #f3bf57;
      --muted: #65736d;
      --line: rgba(23, 59, 53, 0.16);
      --shadow: 0 22px 60px rgba(20, 48, 42, 0.12);
      --font-body: "DM Sans", Arial, sans-serif;
      --font-display: "Fraunces", Georgia, serif;
      --radius: 18px;
      --container: 1240px;
    }

    *,
    *::before,
    *::after {
      box-sizing: border-box;
    }

    html {
      scroll-behavior: smooth;
      scroll-padding-top: 104px;
    }

    body {
      margin: 0;
      overflow-x: clip;
      background: var(--paper);
      color: var(--ink);
      font-family: var(--font-body);
      font-size: 16px;
      line-height: 1.65;
      -webkit-font-smoothing: antialiased;
    }

    body.dialog-open {
      overflow: hidden;
    }

    ::selection {
      background: var(--sun);
      color: var(--ink-deep);
    }

    img {
      display: block;
      max-width: 100%;
    }

    a {
      color: inherit;
    }

    button,
    input,
    select {
      font: inherit;
    }

    button,
    summary,
    a {
      -webkit-tap-highlight-color: transparent;
    }

    button {
      color: inherit;
    }

    h1,
    h2,
    h3,
    h4,
    p,
    blockquote {
      margin-top: 0;
    }

    h1,
    h2,
    h3,
    h4 {
      font-family: var(--font-display);
      font-weight: 600;
      line-height: 1.08;
      letter-spacing: -0.032em;
      text-wrap: balance;
    }

    h2 {
      margin-bottom: 24px;
      font-size: clamp(2.5rem, 4.6vw, 4.35rem);
    }

    h3 {
      font-size: clamp(1.5rem, 2.4vw, 2.15rem);
    }

    p:last-child {
      margin-bottom: 0;
    }

    :focus-visible {
      outline: 3px solid var(--coral);
      outline-offset: 4px;
    }

    .container {
      width: min(var(--container), calc(100% - 48px));
      margin-inline: auto;
    }

    .section {
      padding: 112px 0;
    }

    .sr-only {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip: rect(0, 0, 0, 0);
      white-space: nowrap;
      border: 0;
    }

    .skip-link {
      position: fixed;
      top: 12px;
      left: 12px;
      z-index: 1000;
      padding: 12px 18px;
      background: var(--sun);
      color: var(--ink-deep);
      font-weight: 700;
      text-decoration: none;
      transform: translateY(-160%);
      transition: transform 180ms ease;
    }

    .skip-link:focus {
      transform: translateY(0);
    }

    .eyebrow {
      display: inline-flex;
      align-items: center;
      gap: 10px;
      margin-bottom: 18px;
      color: var(--ink);
      font-size: 0.75rem;
      font-weight: 700;
      letter-spacing: 0.15em;
      line-height: 1.4;
      text-transform: uppercase;
    }

    .eyebrow::before {
      width: 28px;
      height: 2px;
      background: var(--coral);
      content: "";
    }

    .section--dark .eyebrow {
      color: var(--sun);
    }

    .section--dark .eyebrow::before {
      background: var(--sun);
    }

    .button {
      display: inline-flex;
      min-height: 50px;
      align-items: center;
      justify-content: center;
      gap: 10px;
      padding: 13px 23px;
      border: 1.5px solid transparent;
      border-radius: 999px;
      background: var(--ink);
      color: var(--white);
      cursor: pointer;
      font-size: 0.92rem;
      font-weight: 700;
      line-height: 1.2;
      text-align: center;
      text-decoration: none;
      transition: background 180ms ease, color 180ms ease, border-color 180ms ease, transform 180ms ease;
    }

    .button:hover {
      background: var(--coral);
      color: var(--ink-deep);
      transform: translateY(-2px);
    }

    .button--accent {
      background: var(--sun);
      color: var(--ink-deep);
    }

    .button--accent:hover {
      background: var(--white);
    }

    .button--outline {
      border-color: var(--ink);
      background: transparent;
      color: var(--ink);
    }

    .button--outline:hover {
      background: var(--ink);
      color: var(--white);
    }

    .button--light {
      border-color: rgba(255, 255, 255, 0.42);
      background: transparent;
      color: var(--white);
    }

    .button--light:hover {
      border-color: var(--sun);
      background: var(--sun);
      color: var(--ink-deep);
    }

    .text-link {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      padding: 0;
      border: 0;
      border-bottom: 1px solid currentColor;
      background: transparent;
      color: var(--ink);
      cursor: pointer;
      font-size: 0.9rem;
      font-weight: 700;
      line-height: 1.8;
      text-decoration: none;
      transition: color 180ms ease, gap 180ms ease;
    }

    .text-link::after {
      content: "→";
      font-size: 1.05rem;
    }

    .text-link:hover {
      gap: 13px;
      color: var(--coral);
    }

    .icon {
      width: 24px;
      height: 24px;
      flex: 0 0 auto;
      fill: none;
      stroke: currentColor;
      stroke-linecap: round;
      stroke-linejoin: round;
      stroke-width: 1.8;
    }

    /* Announcement and navigation */
    .announcement {
      background: var(--ink-deep);
      color: var(--white);
      font-size: 0.8rem;
    }

    .announcement-inner {
      display: flex;
      min-height: 38px;
      align-items: center;
      justify-content: center;
      gap: 14px;
      padding-block: 7px;
      text-align: center;
    }

    .announcement-label {
      color: var(--sun);
      font-weight: 700;
      letter-spacing: 0.09em;
      text-transform: uppercase;
    }

    .announcement a {
      color: var(--white);
      font-weight: 700;
      text-underline-offset: 3px;
    }

    .site-header {
      position: sticky;
      top: 0;
      z-index: 50;
      border-bottom: 1px solid var(--line);
      background: rgba(247, 243, 235, 0.94);
      backdrop-filter: blur(16px);
      transition: box-shadow 180ms ease;
    }

    .site-header.is-scrolled {
      box-shadow: 0 10px 30px rgba(12, 41, 37, 0.08);
    }

    .header-inner {
      display: flex;
      min-height: 84px;
      align-items: center;
      gap: 28px;
    }

    .brand {
      display: inline-flex;
      flex: 0 0 auto;
      align-items: center;
      gap: 12px;
      text-decoration: none;
    }

    .brand-logo {
      width: 48px;
      height: 48px;
      border-radius: 50%;
    }

    .brand-copy {
      display: grid;
      gap: 1px;
    }

    .brand-name {
      font-family: var(--font-display);
      font-size: 1.2rem;
      font-weight: 700;
      letter-spacing: -0.025em;
      line-height: 1.15;
    }

    .brand-tagline {
      color: var(--muted);
      font-size: 0.62rem;
      font-weight: 700;
      letter-spacing: 0.07em;
      text-transform: uppercase;
    }

    .primary-nav {
      display: flex;
      align-items: center;
      gap: clamp(13px, 1.55vw, 24px);
      margin-left: auto;
    }

    .nav-link {
      position: relative;
      padding: 10px 0;
      font-size: 0.84rem;
      font-weight: 600;
      text-decoration: none;
      white-space: nowrap;
    }

    .nav-link:not(.nav-link--join)::after {
      position: absolute;
      right: 0;
      bottom: 5px;
      left: 0;
      height: 2px;
      background: var(--coral);
      content: "";
      transform: scaleX(0);
      transform-origin: right;
      transition: transform 180ms ease;
    }

    .nav-link:not(.nav-link--join):hover::after {
      transform: scaleX(1);
      transform-origin: left;
    }

    .nav-link--join {
      padding: 11px 19px;
      border-radius: 999px;
      background: var(--sun);
      color: var(--ink-deep);
      font-weight: 700;
      transition: background 180ms ease, transform 180ms ease;
    }

    .nav-link--join:hover {
      background: var(--coral);
      transform: translateY(-1px);
    }

    .menu-toggle {
      display: none;
      width: 46px;
      height: 46px;
      margin-left: auto;
      padding: 0;
      border: 1px solid var(--line);
      border-radius: 50%;
      background: transparent;
      cursor: pointer;
    }

    .menu-toggle span:not(.sr-only) {
      display: block;
      width: 20px;
      height: 2px;
      margin: 5px auto;
      background: var(--ink);
      transition: transform 180ms ease, opacity 180ms ease;
    }

    .menu-toggle[aria-expanded="true"] span:nth-child(2) {
      transform: translateY(3.5px) rotate(45deg);
    }

    .menu-toggle[aria-expanded="true"] span:nth-child(3) {
      opacity: 0;
    }

    .menu-toggle[aria-expanded="true"] span:nth-child(4) {
      transform: translateY(-3.5px) rotate(-45deg);
    }

    /* Hero */
    .hero {
      position: relative;
      overflow: hidden;
      padding-top: 62px;
    }

    .hero::before {
      position: absolute;
      top: -160px;
      left: -200px;
      width: 600px;
      height: 600px;
      border-radius: 50%;
      background: radial-gradient(circle, rgba(243, 191, 87, 0.18), transparent 68%);
      content: "";
      pointer-events: none;
    }

    .hero-grid {
      display: grid;
      grid-template-columns: minmax(0, 1.03fr) minmax(400px, 0.97fr);
      align-items: center;
      gap: clamp(40px, 6vw, 82px);
    }

    .hero-copy {
      position: relative;
      z-index: 2;
      padding: 30px 0 74px;
    }

    .hero h1 {
      max-width: 690px;
      margin-bottom: 28px;
      font-size: clamp(3.65rem, 6.2vw, 6.15rem);
      line-height: 0.98;
    }

    .hero h1 em {
      display: block;
      color: var(--coral);
      font-weight: 500;
    }

    .hero-lede {
      max-width: 620px;
      margin-bottom: 18px;
      color: #425b55;
      font-size: 1.08rem;
    }

    .hero-subline {
      max-width: 570px;
      margin-bottom: 30px;
      color: var(--muted);
      font-size: 0.94rem;
    }

    .hero-actions {
      display: flex;
      flex-wrap: wrap;
      gap: 12px;
      margin-bottom: 32px;
    }

    .member-proof {
      display: flex;
      align-items: center;
      gap: 14px;
      color: var(--muted);
      font-size: 0.79rem;
    }

    .member-proof strong {
      color: var(--ink);
    }

    .mini-avatars {
      display: flex;
      padding-left: 8px;
    }

    .mini-avatars img {
      width: 36px;
      height: 36px;
      margin-left: -8px;
      border: 3px solid var(--paper);
      border-radius: 50%;
      object-fit: cover;
    }

    .hero-visual {
      position: relative;
      padding: 0 0 68px 24px;
    }

    .hero-visual::before {
      position: absolute;
      top: 24px;
      right: -22px;
      bottom: 44px;
      left: 0;
      border-radius: 280px 280px 24px 24px;
      background: var(--sun);
      content: "";
      transform: rotate(2deg);
    }

    .hero-photo {
      position: relative;
      z-index: 1;
      width: 100%;
      height: 610px;
      border-radius: 280px 280px 24px 24px;
      object-fit: cover;
    }

    .hero-quote {
      position: absolute;
      z-index: 3;
      bottom: 104px;
      left: -24px;
      width: min(280px, 58%);
      padding: 22px 24px;
      border-left: 4px solid var(--coral);
      background: var(--white);
      box-shadow: var(--shadow);
      transform: rotate(-2deg);
    }

    .hero-quote blockquote {
      margin-bottom: 10px;
      font-family: var(--font-display);
      font-size: 1.14rem;
      line-height: 1.35;
    }

    .hero-quote cite {
      color: var(--muted);
      font-size: 0.72rem;
      font-style: normal;
      font-weight: 600;
    }

    .hero-badge {
      position: absolute;
      z-index: 2;
      top: 105px;
      right: -30px;
      display: grid;
      width: 122px;
      height: 122px;
      place-content: center;
      border: 6px solid var(--paper);
      border-radius: 50%;
      background: var(--coral);
      color: var(--ink-deep);
      font-size: 0.66rem;
      font-weight: 700;
      letter-spacing: 0.11em;
      line-height: 1.55;
      text-align: center;
      text-transform: uppercase;
      transform: rotate(8deg);
    }

    .impact-strip {
      border-top: 1px solid var(--line);
      border-bottom: 1px solid var(--line);
      background: var(--white);
    }

    .impact-grid {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
    }

    .impact-stat {
      padding: 28px 28px 27px;
      border-left: 1px solid var(--line);
    }

    .impact-stat:first-child {
      border-left: 0;
    }

    .impact-stat strong {
      display: block;
      margin-bottom: 2px;
      font-family: var(--font-display);
      font-size: clamp(2rem, 3vw, 2.85rem);
      line-height: 1.1;
    }

    .impact-stat span {
      color: var(--muted);
      font-size: 0.75rem;
      font-weight: 600;
    }

    /* Work */
    .section-heading {
      display: grid;
      grid-template-columns: minmax(180px, 0.55fr) minmax(0, 1.45fr);
      gap: 48px;
      align-items: start;
    }

    .section-heading h2 {
      max-width: 830px;
    }

    .section-intro {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 32px;
      max-width: 910px;
      margin: 12px 0 0 auto;
      color: #4e625d;
    }

    .pillar-grid {
      display: grid;
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 22px;
      margin-top: 60px;
    }

    .pillar {
      display: flex;
      min-height: 100%;
      flex-direction: column;
      padding: 30px;
      border: 1px solid var(--line);
      border-top: 4px solid var(--ink);
      background: var(--white);
      transition: transform 200ms ease, box-shadow 200ms ease;
    }

    .pillar:nth-child(2) {
      border-top-color: var(--coral);
    }

    .pillar:nth-child(3) {
      border-top-color: var(--sun);
    }

    .pillar:hover {
      box-shadow: 0 18px 40px rgba(23, 59, 53, 0.08);
      transform: translateY(-5px);
    }

    .pillar-top {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-bottom: 30px;
    }

    .pillar-icon {
      display: grid;
      width: 56px;
      height: 56px;
      place-items: center;
      border-radius: 50%;
      background: var(--sage);
    }

    .pillar:nth-child(2) .pillar-icon {
      background: #f8ded4;
    }

    .pillar:nth-child(3) .pillar-icon {
      background: #f9e8bd;
    }

    .pillar-number {
      color: var(--muted);
      font-family: var(--font-display);
      font-size: 1rem;
    }

    .pillar h3 {
      margin-bottom: 16px;
      font-size: 1.75rem;
    }

    .pillar p {
      margin-bottom: 20px;
      color: #51645f;
      font-size: 0.94rem;
    }

    .pillar .text-link {
      align-self: flex-start;
      margin-top: auto;
    }

    /* Campaigns */
    .section--sage {
      background: var(--sage);
    }

    .campaign-heading {
      display: flex;
      align-items: end;
      justify-content: space-between;
      gap: 40px;
      margin-bottom: 50px;
    }

    .campaign-heading h2 {
      max-width: 760px;
      margin-bottom: 0;
    }

    .campaign-heading p {
      max-width: 390px;
      margin-bottom: 4px;
      color: #4c615b;
    }

    .campaign-layout {
      display: grid;
      grid-template-columns: minmax(0, 1.45fr) minmax(320px, 0.75fr);
      align-items: start;
      gap: 28px;
    }

    .campaign-main {
      display: grid;
      gap: 24px;
    }

    .campaign-feature {
      display: grid;
      grid-template-columns: minmax(0, 0.94fr) minmax(0, 1.06fr);
      overflow: hidden;
      border: 1px solid var(--line);
      background: var(--white);
    }

    .campaign-feature-image {
      width: 100%;
      height: 100%;
      min-height: 480px;
      object-fit: cover;
    }

    .campaign-feature-content {
      padding: clamp(26px, 3vw, 38px);
    }

    .tag {
      display: inline-block;
      margin-bottom: 16px;
      color: var(--coral);
      font-size: 0.68rem;
      font-weight: 700;
      letter-spacing: 0.12em;
      text-transform: uppercase;
    }

    .campaign-feature h3 {
      margin-bottom: 18px;
      font-size: clamp(2rem, 3.4vw, 3rem);
    }

    .campaign-feature p {
      color: #50635e;
      font-size: 0.9rem;
    }

    .campaign-progress {
      margin: 24px 0;
      padding: 18px 0;
      border-top: 1px solid var(--line);
      border-bottom: 1px solid var(--line);
    }

    .progress-label {
      display: flex;
      justify-content: space-between;
      gap: 16px;
      margin-bottom: 9px;
      font-size: 0.73rem;
      font-weight: 700;
    }

    .progress-track {
      height: 7px;
      overflow: hidden;
      border-radius: 99px;
      background: #dfe6dd;
    }

    .progress-track span {
      display: block;
      width: 68%;
      height: 100%;
      border-radius: inherit;
      background: var(--coral);
    }

    .campaign-milestone {
      margin-bottom: 22px;
      color: var(--muted);
      font-size: 0.75rem;
    }

    .campaign-milestone strong {
      color: var(--ink);
    }

    .campaign-buttons {
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
    }

    .campaign-buttons .button {
      min-height: 44px;
      padding: 11px 17px;
      font-size: 0.79rem;
    }

    .campaign-card-grid {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 24px;
    }

    .campaign-card {
      padding: 28px;
      border-top: 4px solid var(--coral);
      background: var(--white);
    }

    .campaign-card:last-child {
      border-top-color: var(--sun);
    }

    .campaign-card h3 {
      margin-bottom: 14px;
      font-size: 1.65rem;
    }

    .campaign-card p {
      min-height: 116px;
      margin-bottom: 18px;
      color: #52645f;
      font-size: 0.88rem;
    }

    .campaign-card-meta {
      display: block;
      margin-bottom: 20px;
      color: var(--muted);
      font-size: 0.72rem;
      font-weight: 600;
    }

    .action-desk {
      position: sticky;
      top: 108px;
      padding: 30px;
      border-radius: var(--radius);
      background: var(--ink);
      color: var(--white);
      box-shadow: 0 22px 50px rgba(12, 41, 37, 0.15);
    }

    .action-desk .eyebrow {
      margin-bottom: 12px;
      color: var(--sun);
      font-size: 0.65rem;
    }

    .action-desk .eyebrow::before {
      background: var(--sun);
    }

    .action-desk h3 {
      margin-bottom: 14px;
      font-size: 2rem;
    }

    .action-intro {
      color: rgba(255, 255, 255, 0.72);
      font-size: 0.83rem;
    }

    .action-progress {
      display: flex;
      align-items: center;
      gap: 18px;
      margin: 25px 0 12px;
      padding: 20px 0;
      border-top: 1px solid rgba(255, 255, 255, 0.17);
      border-bottom: 1px solid rgba(255, 255, 255, 0.17);
    }

    .progress-ring {
      --progress: 0;
      position: relative;
      display: grid;
      width: 76px;
      height: 76px;
      flex: 0 0 auto;
      place-items: center;
      border-radius: 50%;
      background: conic-gradient(var(--sun) calc(var(--progress) * 1%), rgba(255, 255, 255, 0.14) 0);
    }

    .progress-ring::before {
      position: absolute;
      width: 60px;
      height: 60px;
      border-radius: 50%;
      background: var(--ink);
      content: "";
    }

    .progress-ring span {
      position: relative;
      z-index: 1;
      font-family: var(--font-display);
      font-size: 1.05rem;
      font-weight: 600;
    }

    .action-progress-copy strong {
      display: block;
      margin-bottom: 4px;
      font-size: 0.83rem;
    }

    .action-progress-copy p {
      color: rgba(255, 255, 255, 0.66);
      font-size: 0.72rem;
      line-height: 1.5;
    }

    .action-list {
      display: grid;
    }

    .action-item {
      display: grid;
      grid-template-columns: 24px minmax(0, 1fr);
      gap: 12px;
      padding: 20px 0;
      border-bottom: 1px solid rgba(255, 255, 255, 0.14);
      transition: opacity 180ms ease;
    }

    .action-item.is-complete {
      opacity: 0.6;
    }

    .action-item.is-complete h4 {
      text-decoration: line-through;
      text-decoration-thickness: 1px;
    }

    .action-check {
      display: grid;
      width: 21px;
      height: 21px;
      margin: 2px 0 0;
      appearance: none;
      place-content: center;
      border: 1.5px solid rgba(255, 255, 255, 0.65);
      border-radius: 5px;
      background: transparent;
      cursor: pointer;
    }

    .action-check::before {
      width: 9px;
      height: 5px;
      border-bottom: 2px solid var(--ink-deep);
      border-left: 2px solid var(--ink-deep);
      content: "";
      transform: rotate(-45deg) scale(0);
      transition: transform 120ms ease;
    }

    .action-check:checked {
      border-color: var(--sun);
      background: var(--sun);
    }

    .action-check:checked::before {
      transform: rotate(-45deg) scale(1);
    }

    .action-item h4 {
      margin-bottom: 6px;
      font-family: var(--font-body);
      font-size: 0.92rem;
      font-weight: 700;
      letter-spacing: 0;
      line-height: 1.35;
    }

    .action-item h4 label {
      cursor: pointer;
    }

    .action-item p {
      margin-bottom: 12px;
      color: rgba(255, 255, 255, 0.62);
      font-size: 0.74rem;
      line-height: 1.55;
    }

    .action-buttons {
      display: flex;
      flex-wrap: wrap;
      gap: 8px 14px;
    }

    .action-link {
      display: inline-flex;
      align-items: center;
      gap: 5px;
      padding: 0;
      border: 0;
      border-bottom: 1px solid rgba(243, 191, 87, 0.65);
      background: transparent;
      color: var(--sun);
      cursor: pointer;
      font-size: 0.71rem;
      font-weight: 700;
      line-height: 1.8;
      text-decoration: none;
    }

    .action-link:hover {
      border-color: var(--white);
      color: var(--white);
    }

    .action-footer {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 16px;
      padding-top: 18px;
    }

    .action-privacy {
      max-width: 210px;
      color: rgba(255, 255, 255, 0.48);
      font-size: 0.65rem;
      line-height: 1.45;
    }

    .reset-actions {
      padding: 0;
      border: 0;
      border-bottom: 1px solid currentColor;
      background: transparent;
      color: rgba(255, 255, 255, 0.68);
      cursor: pointer;
      font-size: 0.68rem;
    }

    /* Stories */
    .stories-heading {
      max-width: 900px;
    }

    .stories-heading > p {
      max-width: 690px;
      color: #50635e;
    }

    .stories-grid {
      display: grid;
      grid-template-columns: minmax(0, 1.35fr) minmax(300px, 0.65fr);
      gap: 26px;
      margin-top: 52px;
    }

    .story-main {
      overflow: hidden;
      background: var(--white);
    }

    .story-main-image {
      width: 100%;
      height: 390px;
      object-fit: cover;
    }

    .story-main-content {
      padding: clamp(28px, 4vw, 44px);
    }

    .story-main h3 {
      margin-bottom: 20px;
      font-size: clamp(2rem, 3.5vw, 3.25rem);
    }

    .story-main p {
      color: #4e625c;
    }

    .story-quote {
      margin: 26px 0;
      padding: 20px 0 20px 24px;
      border-left: 3px solid var(--coral);
      color: var(--ink);
      font-family: var(--font-display);
      font-size: 1.35rem;
      line-height: 1.4;
    }

    .story-quote cite {
      display: block;
      margin-top: 10px;
      color: var(--muted);
      font-family: var(--font-body);
      font-size: 0.7rem;
      font-style: normal;
      font-weight: 600;
      letter-spacing: 0.04em;
    }

    .story-side {
      display: grid;
      gap: 26px;
    }

    .story-mini {
      display: flex;
      flex-direction: column;
      border: 1px solid var(--line);
      background: var(--white);
    }

    .story-mini img {
      width: 100%;
      height: 180px;
      object-fit: cover;
    }

    .story-mini-content {
      display: flex;
      flex: 1;
      flex-direction: column;
      padding: 25px;
    }

    .story-mini h3 {
      margin-bottom: 12px;
      font-size: 1.55rem;
    }

    .story-mini p {
      margin-bottom: 18px;
      color: #52655f;
      font-size: 0.83rem;
    }

    .story-mini .text-link {
      align-self: flex-start;
      margin-top: auto;
      font-size: 0.77rem;
    }

    .testimonial-heading {
      margin: 72px 0 28px;
      font-family: var(--font-body);
      font-size: 0.74rem;
      font-weight: 700;
      letter-spacing: 0.13em;
      text-transform: uppercase;
    }

    .testimonial-grid {
      display: grid;
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 24px;
    }

    .testimonial {
      padding: 28px 0 0;
      border-top: 2px solid var(--ink);
    }

    .testimonial:nth-child(2) {
      border-color: var(--coral);
    }

    .testimonial:nth-child(3) {
      border-color: var(--sun);
    }

    .testimonial blockquote {
      min-height: 135px;
      margin-bottom: 24px;
      font-family: var(--font-display);
      font-size: 1.27rem;
      line-height: 1.45;
    }

    .testimonial-person {
      display: flex;
      align-items: center;
      gap: 12px;
    }

    .testimonial-person img {
      width: 48px;
      height: 48px;
      border-radius: 50%;
      object-fit: cover;
    }

    .testimonial-person strong,
    .testimonial-person span {
      display: block;
    }

    .testimonial-person strong {
      font-size: 0.82rem;
    }

    .testimonial-person span {
      color: var(--muted);
      font-size: 0.7rem;
    }

    /* Policy */
    .section--dark {
      background: var(--ink);
      color: var(--white);
    }

    .section--dark h2,
    .section--dark h3 {
      color: var(--white);
    }

    .policy-layout {
      display: grid;
      grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
      gap: clamp(48px, 7vw, 90px);
      align-items: start;
    }

    .policy-copy > p {
      color: rgba(255, 255, 255, 0.72);
    }

    .policy-photo-wrap {
      position: relative;
      margin-top: 34px;
    }

    .policy-photo {
      width: 100%;
      height: 340px;
      border-radius: 12px;
      object-fit: cover;
    }

    .policy-photo-note {
      position: absolute;
      right: -18px;
      bottom: -20px;
      max-width: 220px;
      padding: 20px;
      background: var(--sun);
      color: var(--ink-deep);
      font-family: var(--font-display);
      font-size: 1.05rem;
      line-height: 1.35;
      transform: rotate(2deg);
    }

    .policy-timeline h3 {
      margin-bottom: 24px;
      font-size: 2rem;
    }

    .timeline-item {
      display: grid;
      grid-template-columns: 72px minmax(0, 1fr);
      gap: 22px;
      padding: 26px 0;
      border-top: 1px solid rgba(255, 255, 255, 0.18);
    }

    .timeline-item:last-of-type {
      border-bottom: 1px solid rgba(255, 255, 255, 0.18);
    }

    .timeline-year {
      color: var(--sun);
      font-family: var(--font-display);
      font-size: 1.3rem;
    }

    .timeline-item h4 {
      margin-bottom: 9px;
      color: var(--white);
      font-size: 1.35rem;
    }

    .timeline-item p {
      color: rgba(255, 255, 255, 0.65);
      font-size: 0.85rem;
    }

    .methodology {
      margin-top: 24px;
    }

    .methodology summary {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      color: var(--sun);
      cursor: pointer;
      font-size: 0.8rem;
      font-weight: 700;
      list-style: none;
    }

    .methodology summary::-webkit-details-marker {
      display: none;
    }

    .methodology summary::after {
      content: "+";
      font-size: 1.2rem;
    }

    .methodology[open] summary::after {
      content: "−";
    }

    .methodology p {
      margin-top: 16px;
      padding: 18px;
      border-left: 2px solid var(--sun);
      background: rgba(255, 255, 255, 0.05);
      color: rgba(255, 255, 255, 0.67);
      font-size: 0.78rem;
    }

    .policy-metrics {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      margin-top: 78px;
      border-top: 1px solid rgba(255, 255, 255, 0.2);
      border-bottom: 1px solid rgba(255, 255, 255, 0.2);
    }

    .policy-metric {
      padding: 28px;
      border-left: 1px solid rgba(255, 255, 255, 0.2);
    }

    .policy-metric:first-child {
      border-left: 0;
    }

    .policy-metric strong {
      display: block;
      color: var(--sun);
      font-family: var(--font-display);
      font-size: 2.75rem;
      line-height: 1.1;
    }

    .policy-metric span {
      color: rgba(255, 255, 255, 0.65);
      font-size: 0.74rem;
    }

    .policy-cta {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 30px;
      margin-top: 34px;
    }

    .policy-cta p {
      max-width: 610px;
      color: rgba(255, 255, 255, 0.66);
      font-size: 0.86rem;
    }

    /* News and events */
    .news-header {
      display: flex;
      align-items: end;
      justify-content: space-between;
      gap: 40px;
      margin-bottom: 48px;
    }

    .news-header h2 {
      margin-bottom: 0;
    }

    .news-header p {
      max-width: 430px;
      margin-bottom: 4px;
      color: var(--muted);
    }

    .news-layout {
      display: grid;
      grid-template-columns: minmax(0, 1fr) 310px;
      align-items: start;
      gap: 28px;
    }

    .news-grid {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 24px;
    }

    .news-card {
      display: flex;
      min-width: 0;
      flex-direction: column;
      overflow: hidden;
      border: 1px solid var(--line);
      background: var(--white);
    }

    .news-card--lead {
      display: grid;
      grid-column: 1 / -1;
      grid-template-columns: 1fr 1fr;
    }

    .news-card-image {
      width: 100%;
      height: 220px;
      object-fit: cover;
    }

    .news-card--lead .news-card-image {
      height: 100%;
      min-height: 360px;
    }

    .news-card-content {
      display: flex;
      flex: 1;
      flex-direction: column;
      padding: 26px;
    }

    .news-meta {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
      margin-bottom: 16px;
      color: var(--muted);
      font-size: 0.66rem;
      font-weight: 700;
      letter-spacing: 0.06em;
      text-transform: uppercase;
    }

    .news-meta span:first-child {
      color: var(--coral);
    }

    .news-card h3 {
      margin-bottom: 13px;
      font-size: 1.65rem;
    }

    .news-card--lead h3 {
      font-size: 2.1rem;
    }

    .news-card p {
      margin-bottom: 22px;
      color: #52655f;
      font-size: 0.83rem;
    }

    .news-card .text-link {
      align-self: flex-start;
      margin-top: auto;
      font-size: 0.78rem;
    }

    .events-panel {
      padding: 28px;
      background: var(--sun);
      color: var(--ink-deep);
    }

    .events-panel h3 {
      margin-bottom: 12px;
      font-size: 2rem;
    }

    .events-panel > p {
      margin-bottom: 24px;
      font-size: 0.8rem;
    }

    .event-item {
      display: grid;
      grid-template-columns: 50px minmax(0, 1fr);
      gap: 14px;
      padding: 20px 0;
      border-top: 1px solid rgba(12, 41, 37, 0.22);
    }

    .event-date {
      display: grid;
      height: 58px;
      place-content: center;
      background: var(--white);
      line-height: 1.1;
      text-align: center;
    }

    .event-month {
      font-size: 0.57rem;
      font-weight: 700;
      letter-spacing: 0.09em;
    }

    .event-day {
      font-family: var(--font-display);
      font-size: 1.45rem;
    }

    .event-details h4 {
      margin-bottom: 4px;
      font-family: var(--font-body);
      font-size: 0.84rem;
      font-weight: 700;
      letter-spacing: 0;
      line-height: 1.35;
    }

    .event-details p {
      margin-bottom: 8px;
      font-size: 0.68rem;
      line-height: 1.45;
    }

    .event-details a {
      font-size: 0.7rem;
      font-weight: 700;
      text-underline-offset: 3px;
    }

    /* About */
    .section--about {
      background: var(--white);
    }

    .about-grid {
      display: grid;
      grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
      gap: clamp(50px, 8vw, 100px);
    }

    .about-statement p {
      color: #4f635d;
    }

    .about-statement .lead {
      color: var(--ink);
      font-family: var(--font-display);
      font-size: 1.32rem;
      line-height: 1.45;
    }

    .about-statement .button {
      margin-top: 16px;
    }

    .principles {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 32px 26px;
      padding-top: 10px;
    }

    .principle {
      padding-top: 18px;
      border-top: 2px solid var(--ink);
    }

    .principle:nth-child(2),
    .principle:nth-child(3) {
      border-color: var(--coral);
    }

    .principle-number {
      display: block;
      margin-bottom: 16px;
      color: var(--muted);
      font-size: 0.7rem;
      font-weight: 700;
    }

    .principle h3 {
      margin-bottom: 10px;
      font-size: 1.4rem;
    }

    .principle p {
      color: var(--muted);
      font-size: 0.81rem;
    }

    .partner-band {
      display: flex;
      align-items: center;
      gap: 28px;
      margin-top: 72px;
      padding: 28px 0;
      border-top: 1px solid var(--line);
      border-bottom: 1px solid var(--line);
    }

    .partner-label {
      max-width: 115px;
      flex: 0 0 auto;
      color: var(--muted);
      font-size: 0.66rem;
      font-weight: 700;
      letter-spacing: 0.08em;
      line-height: 1.45;
      text-transform: uppercase;
    }

    .partner-list {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 16px 28px;
      margin: 0;
      padding: 0;
      list-style: none;
    }

    .partner-list li {
      font-family: var(--font-display);
      font-size: 1.02rem;
      font-weight: 600;
      line-height: 1.25;
    }

    /* FAQ */
    .faq-layout {
      display: grid;
      grid-template-columns: minmax(240px, 0.65fr) minmax(0, 1.35fr);
      gap: clamp(45px, 8vw, 100px);
    }

    .faq-intro p {
      max-width: 350px;
      color: var(--muted);
    }

    .faq-list {
      border-bottom: 1px solid var(--line);
    }

    .faq-item {
      border-top: 1px solid var(--line);
    }

    .faq-item summary {
      position: relative;
      padding: 25px 52px 25px 0;
      cursor: pointer;
      font-family: var(--font-display);
      font-size: 1.35rem;
      font-weight: 600;
      line-height: 1.3;
      list-style: none;
    }

    .faq-item summary::-webkit-details-marker {
      display: none;
    }

    .faq-item summary::after {
      position: absolute;
      top: 24px;
      right: 4px;
      display: grid;
      width: 30px;
      height: 30px;
      place-items: center;
      border: 1px solid var(--line);
      border-radius: 50%;
      content: "+";
      font-family: var(--font-body);
      font-size: 1.15rem;
      font-weight: 400;
      transition: transform 180ms ease, background 180ms ease;
    }

    .faq-item[open] summary::after {
      background: var(--sun);
      transform: rotate(45deg);
    }

    .faq-answer {
      max-width: 690px;
      padding: 0 48px 26px 0;
      color: #50635e;
      font-size: 0.9rem;
    }

    /* Join */
    .join-section {
      padding: 0 0 112px;
    }

    .join-panel {
      display: grid;
      grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
      overflow: hidden;
      border-radius: 26px;
      background: var(--sun);
      box-shadow: 0 20px 60px rgba(23, 59, 53, 0.09);
    }

    .join-copy {
      padding: clamp(36px, 5vw, 62px);
    }

    .join-copy h2 {
      font-size: clamp(2.7rem, 4.5vw, 4.3rem);
    }

    .join-copy p {
      max-width: 510px;
      font-size: 0.91rem;
    }

    .join-benefits {
      display: grid;
      gap: 12px;
      margin: 28px 0 0;
      padding: 0;
      list-style: none;
    }

    .join-benefits li {
      display: flex;
      align-items: flex-start;
      gap: 10px;
      font-size: 0.82rem;
      font-weight: 600;
    }

    .join-benefits li::before {
      display: grid;
      width: 20px;
      height: 20px;
      flex: 0 0 auto;
      place-items: center;
      border: 1px solid var(--ink-deep);
      border-radius: 50%;
      content: "✓";
      font-size: 0.68rem;
    }

    .join-form-wrap {
      padding: clamp(32px, 4.5vw, 52px);
      background: var(--white);
    }

    .join-form-wrap h3 {
      margin-bottom: 8px;
      font-size: 1.8rem;
    }

    .join-form-wrap > p,
    .form-intro {
      margin-bottom: 26px;
      color: var(--muted);
      font-size: 0.8rem;
    }

    .form-row {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 16px;
    }

    .form-field {
      margin-bottom: 17px;
    }

    .form-field label {
      display: block;
      margin-bottom: 6px;
      font-size: 0.72rem;
      font-weight: 700;
    }

    .form-field input,
    .form-field select {
      width: 100%;
      min-height: 48px;
      padding: 11px 13px;
      border: 1px solid rgba(23, 59, 53, 0.25);
      border-radius: 8px;
      background: var(--white);
      color: var(--ink);
      font-size: 0.86rem;
      transition: border-color 180ms ease, box-shadow 180ms ease;
    }

    .form-field input:focus,
    .form-field select:focus {
      border-color: var(--ink);
      box-shadow: 0 0 0 3px rgba(243, 191, 87, 0.35);
      outline: none;
    }

    .form-field input::placeholder {
      color: #8b958f;
    }

    .consent-field {
      display: grid;
      grid-template-columns: 18px minmax(0, 1fr);
      gap: 10px;
      align-items: start;
      margin: 3px 0 20px;
    }

    .consent-field input {
      width: 17px;
      height: 17px;
      margin: 3px 0 0;
      accent-color: var(--ink);
    }

    .consent-field label {
      color: var(--muted);
      font-size: 0.69rem;
      line-height: 1.5;
    }

    .consent-field a,
    .form-privacy a {
      text-underline-offset: 2px;
    }

    .join-submit {
      width: 100%;
    }

    .form-privacy {
      margin: 13px 0 0;
      color: var(--muted);
      font-size: 0.65rem;
      text-align: center;
    }

    .join-success {
      padding: 34px 28px;
      border: 1px solid var(--line);
      background: var(--sage);
      text-align: center;
    }

    .join-success[hidden] {
      display: none;
    }

    .success-mark {
      display: grid;
      width: 58px;
      height: 58px;
      margin: 0 auto 20px;
      place-items: center;
      border-radius: 50%;
      background: var(--ink);
      color: var(--white);
      font-size: 1.4rem;
    }

    .join-success h3 {
      margin-bottom: 12px;
    }

    .join-success p {
      color: #4d615b;
      font-size: 0.85rem;
    }

    .join-success .text-link {
      margin-top: 20px;
    }

    /* Footer */
    .site-footer {
      padding: 72px 0 26px;
      background: var(--ink-deep);
      color: var(--white);
    }

    .footer-grid {
      display: grid;
      grid-template-columns: 1.35fr 0.65fr 0.65fr 1fr;
      gap: 50px;
    }

    .footer-brand .brand-name {
      color: var(--white);
    }

    .footer-brand .brand-tagline {
      color: rgba(255, 255, 255, 0.55);
    }

    .footer-brand > p {
      max-width: 320px;
      margin: 24px 0;
      color: rgba(255, 255, 255, 0.58);
      font-size: 0.8rem;
    }

    .social-links {
      display: flex;
      gap: 10px;
    }

    .social-links a {
      display: grid;
      width: 38px;
      height: 38px;
      place-items: center;
      border: 1px solid rgba(255, 255, 255, 0.23);
      border-radius: 50%;
      color: rgba(255, 255, 255, 0.78);
      transition: background 180ms ease, color 180ms ease;
    }

    .social-links a:hover {
      background: var(--sun);
      color: var(--ink-deep);
    }

    .social-links .icon {
      width: 17px;
      height: 17px;
    }

    .footer-column h2 {
      margin-bottom: 20px;
      color: var(--sun);
      font-family: var(--font-body);
      font-size: 0.68rem;
      font-weight: 700;
      letter-spacing: 0.12em;
      text-transform: uppercase;
    }

    .footer-links {
      display: grid;
      gap: 11px;
      margin: 0;
      padding: 0;
      list-style: none;
    }

    .footer-links a {
      color: rgba(255, 255, 255, 0.68);
      font-size: 0.78rem;
      text-decoration: none;
    }

    .footer-links a:hover {
      color: var(--sun);
      text-decoration: underline;
      text-underline-offset: 3px;
    }

    .footer-contact {
      color: rgba(255, 255, 255, 0.66);
      font-size: 0.78rem;
      font-style: normal;
    }

    .footer-contact p {
      margin-bottom: 14px;
    }

    .footer-contact a {
      color: var(--white);
      text-underline-offset: 3px;
    }

    .footer-bottom {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 24px;
      margin-top: 58px;
      padding-top: 24px;
      border-top: 1px solid rgba(255, 255, 255, 0.15);
      color: rgba(255, 255, 255, 0.45);
      font-size: 0.66rem;
    }

    .footer-bottom p {
      margin: 0;
    }

    .legal-links {
      display: flex;
      flex-wrap: wrap;
      gap: 18px;
    }

    .legal-links a {
      color: rgba(255, 255, 255, 0.65);
      text-decoration: none;
    }

    .legal-links a:hover {
      color: var(--sun);
    }

    /* Dialogs and notifications */
    dialog {
      width: min(720px, calc(100% - 32px));
      max-height: 88vh;
      padding: 0;
      overflow: hidden;
      border: 0;
      border-radius: 20px;
      background: var(--white);
      color: var(--ink);
      box-shadow: 0 30px 100px rgba(4, 24, 20, 0.35);
    }

    dialog::backdrop {
      background: rgba(6, 29, 25, 0.74);
      backdrop-filter: blur(5px);
    }

    dialog[open] {
      animation: dialog-in 220ms ease both;
    }

    .dialog-shell {
      position: relative;
      max-height: 88vh;
      padding: clamp(28px, 5vw, 48px);
      overflow-y: auto;
    }

    .dialog-close {
      position: absolute;
      top: 18px;
      right: 18px;
      display: grid;
      width: 38px;
      height: 38px;
      padding: 0;
      place-items: center;
      border: 1px solid var(--line);
      border-radius: 50%;
      background: var(--paper);
      cursor: pointer;
      font-size: 1.25rem;
      line-height: 1;
    }

    .dialog-close:hover {
      background: var(--sun);
    }

    .dialog-content {
      padding-right: 12px;
    }

    .dialog-content h2 {
      max-width: 590px;
      margin-bottom: 20px;
      padding-right: 24px;
      font-size: clamp(2rem, 5vw, 3.1rem);
    }

    .dialog-content h3 {
      margin: 28px 0 12px;
      font-size: 1.35rem;
    }

    .dialog-content p,
    .dialog-content li {
      color: #4c615b;
      font-size: 0.9rem;
    }

    .dialog-content ul,
    .dialog-content ol {
      padding-left: 22px;
    }

    .dialog-content li {
      margin-bottom: 10px;
    }

    .dialog-meta {
      display: block;
      margin-bottom: 16px;
      color: var(--coral);
      font-size: 0.68rem;
      font-weight: 700;
      letter-spacing: 0.1em;
      text-transform: uppercase;
    }

    .dialog-callout {
      margin: 24px 0;
      padding: 20px;
      border-left: 3px solid var(--coral);
      background: var(--paper);
      font-family: var(--font-display);
      font-size: 1.15rem;
      line-height: 1.45;
    }

    .dialog-actions {
      display: flex;
      flex-wrap: wrap;
      gap: 12px;
      margin-top: 28px;
    }

    .toast {
      position: fixed;
      z-index: 200;
      right: 24px;
      bottom: 24px;
      max-width: min(390px, calc(100% - 32px));
      padding: 15px 20px;
      border-left: 4px solid var(--sun);
      border-radius: 8px;
      background: var(--ink-deep);
      color: var(--white);
      box-shadow: var(--shadow);
      font-size: 0.8rem;
      opacity: 0;
      pointer-events: none;
      transform: translateY(18px);
      transition: opacity 180ms ease, transform 180ms ease;
    }

    .toast.is-visible {
      opacity: 1;
      transform: translateY(0);
    }

    .js .reveal {
      opacity: 0;
      transform: translateY(24px);
      transition: opacity 650ms ease, transform 650ms ease;
      transition-delay: var(--delay, 0ms);
    }

    .js .reveal.is-visible {
      opacity: 1;
      transform: translateY(0);
    }

    @keyframes dialog-in {
      from {
        opacity: 0;
        transform: translateY(16px) scale(0.985);
      }
      to {
        opacity: 1;
        transform: translateY(0) scale(1);
      }
    }

    /* Responsive */
    @media (max-width: 1160px) {
      .brand-tagline {
        display: none;
      }

      .campaign-layout {
        grid-template-columns: 1fr;
      }

      .action-desk {
        position: static;
      }

      .action-list {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        column-gap: 32px;
      }

      .news-layout {
        grid-template-columns: 1fr;
      }

      .events-panel {
        display: grid;
        grid-template-columns: 0.7fr 1.3fr;
        gap: 0 30px;
      }

      .events-panel .event-list {
        grid-column: 2;
        grid-row: 1 / span 3;
      }
    }

    @media (max-width: 1000px) {
      .menu-toggle {
        display: block;
      }

      .primary-nav {
        position: absolute;
        top: 100%;
        right: 0;
        left: 0;
        display: grid;
        gap: 2px;
        margin: 0;
        padding: 18px 24px 24px;
        border-bottom: 1px solid var(--line);
        background: var(--paper);
        box-shadow: 0 18px 30px rgba(12, 41, 37, 0.1);
        opacity: 0;
        pointer-events: none;
        transform: translateY(-8px);
        transition: opacity 180ms ease, transform 180ms ease;
        visibility: hidden;
      }

      .primary-nav.is-open {
        opacity: 1;
        pointer-events: auto;
        transform: translateY(0);
        visibility: visible;
      }

      .nav-link {
        padding: 12px 4px;
        font-size: 0.94rem;
      }

      .nav-link--join {
        margin-top: 8px;
        padding: 13px 20px;
        text-align: center;
      }

      .hero-grid {
        grid-template-columns: 1fr;
      }

      .hero-copy {
        max-width: 780px;
        padding-bottom: 10px;
      }

      .hero h1 {
        max-width: 790px;
      }

      .hero-visual {
        width: min(680px, 92%);
        margin: 0 auto;
      }

      .hero-photo {
        height: 620px;
      }

      .stories-grid {
        grid-template-columns: 1fr;
      }

      .story-side {
        grid-template-columns: repeat(2, minmax(0, 1fr));
      }

      .policy-layout {
        grid-template-columns: 1fr;
      }

      .policy-copy {
        max-width: 760px;
      }

      .policy-photo {
        height: 430px;
      }

      .about-grid {
        grid-template-columns: 1fr;
      }

      .about-statement {
        max-width: 780px;
      }

      .footer-grid {
        grid-template-columns: 1.2fr 0.8fr 0.8fr;
      }

      .footer-column:last-child {
        grid-column: 1 / -1;
      }
    }

    @media (max-width: 800px) {
      .section {
        padding: 84px 0;
      }

      .section-heading,
      .faq-layout {
        grid-template-columns: 1fr;
        gap: 12px;
      }

      .section-intro {
        margin-top: 0;
      }

      .campaign-heading,
      .news-header {
        display: block;
      }

      .campaign-heading h2,
      .news-header h2 {
        margin-bottom: 20px;
      }

      .campaign-heading p,
      .news-header p {
        max-width: 650px;
      }

      .pillar-grid {
        grid-template-columns: 1fr;
      }

      .pillar {
        min-height: 0;
      }

      .campaign-feature {
        grid-template-columns: 1fr;
      }

      .campaign-feature-image {
        height: 330px;
        min-height: 0;
      }

      .campaign-card p {
        min-height: 0;
      }

      .testimonial-grid {
        grid-template-columns: 1fr;
        gap: 34px;
      }

      .testimonial blockquote {
        min-height: 0;
      }

      .policy-metrics {
        margin-top: 62px;
      }

      .policy-cta {
        align-items: flex-start;
        flex-direction: column;
      }

      .news-card--lead {
        grid-template-columns: 1fr;
      }

      .news-card--lead .news-card-image {
        height: 320px;
        min-height: 0;
      }

      .events-panel {
        display: block;
      }

      .partner-band {
        align-items: flex-start;
        flex-direction: column;
      }

      .partner-label {
        max-width: none;
      }

      .join-panel {
        grid-template-columns: 1fr;
      }

      .join-section {
        padding-bottom: 84px;
      }
    }

    @media (max-width: 640px) {
      .container {
        width: min(var(--container), calc(100% - 32px));
      }

      .announcement-inner {
        justify-content: flex-start;
        text-align: left;
      }

      .announcement-label {
        display: none;
      }

      .announcement-detail {
        display: none;
      }

      .header-inner {
        min-height: 74px;
      }

      .brand-logo {
        width: 43px;
        height: 43px;
      }

      .brand-name {
        font-size: 1.02rem;
      }

      .hero {
        padding-top: 42px;
      }

      .hero-copy {
        padding-top: 10px;
      }

      .hero h1 {
        font-size: clamp(3.25rem, 16vw, 4.6rem);
      }

      .hero-actions {
        align-items: stretch;
        flex-direction: column;
      }

      .hero-actions .button {
        width: 100%;
      }

      .hero-visual {
        width: 96%;
        padding-left: 8px;
      }

      .hero-photo {
        height: 480px;
      }

      .hero-badge {
        top: 80px;
        right: -20px;
        width: 102px;
        height: 102px;
        font-size: 0.57rem;
      }

      .hero-quote {
        bottom: 94px;
        left: -8px;
        width: 68%;
        padding: 17px;
      }

      .hero-quote blockquote {
        font-size: 0.98rem;
      }

      .impact-grid {
        grid-template-columns: repeat(2, 1fr);
      }

      .impact-stat {
        padding: 22px 16px;
        border-bottom: 1px solid var(--line);
      }

      .impact-stat:nth-child(odd) {
        border-left: 0;
      }

      .impact-stat:nth-child(n+3) {
        border-bottom: 0;
      }

      .section-intro {
        grid-template-columns: 1fr;
        gap: 0;
      }

      .pillar-grid {
        margin-top: 40px;
      }

      .campaign-card-grid,
      .story-side,
      .news-grid,
      .principles {
        grid-template-columns: 1fr;
      }

      .action-desk {
        padding: 25px 21px;
      }

      .action-list {
        grid-template-columns: 1fr;
      }

      .story-main-image {
        height: 280px;
      }

      .policy-photo {
        height: 300px;
      }

      .policy-photo-note {
        right: -5px;
        max-width: 190px;
      }

      .timeline-item {
        grid-template-columns: 55px minmax(0, 1fr);
        gap: 14px;
      }

      .policy-metrics {
        grid-template-columns: 1fr;
      }

      .policy-metric {
        padding: 20px 0;
        border-bottom: 1px solid rgba(255, 255, 255, 0.17);
        border-left: 0;
      }

      .policy-metric:last-child {
        border-bottom: 0;
      }

      .form-row {
        grid-template-columns: 1fr;
        gap: 0;
      }

      .faq-item summary {
        font-size: 1.2rem;
      }

      .footer-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 40px 24px;
      }

      .footer-brand,
      .footer-column:last-child {
        grid-column: 1 / -1;
      }

      .footer-bottom {
        align-items: flex-start;
        flex-direction: column;
      }

      .toast {
        right: 16px;
        bottom: 16px;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      html {
        scroll-behavior: auto;
      }

      *,
      *::before,
      *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        scroll-behavior: auto !important;
        transition-duration: 0.01ms !important;
      }

      .js .reveal {
        opacity: 1;
        transform: none;
      }
    }
  </style>

  <script type="application/ld+json">
    {
      "@context": "https://schema.org",
      "@type": "NGO",
      "name": "Civic Thread Alliance",
      "slogan": "Many voices. One shared future.",
      "description": "A community-led alliance advancing inclusion, civic participation, cultural connection, and equitable public policy.",
      "email": "hello@civicthreadalliance.org",
      "telephone": "+1-401-555-0148",
      "address": {
        "@type": "PostalAddress",
        "streetAddress": "14 Commons Way, Suite 300",
        "addressLocality": "Providence",
        "addressRegion": "RI",
        "postalCode": "02903",
        "addressCountry": "US"
      }
    }
  </script>
</head>

<body>
  <a class="skip-link" href="#main-content">Skip to main content</a>

  <div class="announcement">
    <div class="container announcement-inner">
      <span class="announcement-label">Campaign update</span>
      <span class="announcement-detail">Safe Routes for All cleared committee—next stop: the full council.</span>
      <a href="#campaigns">Follow what happens next <span aria-hidden="true">→</span></a>
    </div>
  </div>

  <header class="site-header" id="site-header">
    <div class="container header-inner">
      <a class="brand" href="#top" aria-label="Civic Thread Alliance home">
        <img class="brand-logo" src="https://placehold.co/56x56/173b35/f7f3eb?text=CT&font=montserrat" width="48" height="48" alt="Civic Thread Alliance CT logo">
        <span class="brand-copy">
          <span class="brand-name">Civic Thread Alliance</span>
          <span class="brand-tagline">Many voices. One shared future.</span>
        </span>
      </a>

      <button class="menu-toggle" type="button" aria-expanded="false" aria-controls="primary-navigation">
        <span class="sr-only">Open navigation menu</span>
        <span aria-hidden="true"></span>
        <span aria-hidden="true"></span>
        <span aria-hidden="true"></span>
      </button>

      <nav class="primary-nav" id="primary-navigation" aria-label="Primary navigation">
        <a class="nav-link" href="#work">Our Work</a>
        <a class="nav-link" href="#stories">Stories</a>
        <a class="nav-link" href="#campaigns">Campaigns</a>
        <a class="nav-link" href="#policy">Policy Impact</a>
        <a class="nav-link" href="#news">News</a>
        <a class="nav-link" href="#about">About</a>
        <a class="nav-link nav-link--join" href="#join">Join</a>
      </nav>
    </div>
  </header>

  <main id="main-content">
    <section class="hero" id="top" aria-labelledby="hero-title">
      <div class="container hero-grid">
        <div class="hero-copy">
          <span class="eyebrow">Community-led · Nonpartisan · Since 2016</span>
          <h1 id="hero-title">A fairer future is <em>woven together.</em></h1>
          <p class="hero-lede">
            Civic Thread Alliance brings neighbors, cultural organizations, and local advocates together to make public life more inclusive, accountable, and humane. From tenant meetings to policy tables, we help people turn lived experience into lasting change.
          </p>
          <p class="hero-subline">
            You do not need a title, a policy degree, or a lifetime of free time. You need a place to begin—and people who will stand beside you.
          </p>
          <div class="hero-actions">
            <a class="button button--accent" href="#join">Join the movement <span aria-hidden="true">→</span></a>
            <a class="button button--outline" href="#campaigns">Explore this year’s campaigns</a>
          </div>
          <div class="member-proof">
            <div class="mini-avatars" aria-hidden="true">
              <img src="https://i.pravatar.cc/72?u=civic-hero-nia" width="36" height="36" alt="">
              <img src="https://i.pravatar.cc/72?u=civic-hero-dev" width="36" height="36" alt="">
              <img src="https://i.pravatar.cc/72?u=civic-hero-mateo" width="36" height="36" alt="">
            </div>
            <span><strong>18,600+ members</strong><br>showing up in 42 communities</span>
          </div>
        </div>

        <div class="hero-visual">
          <img class="hero-photo" src="https://picsum.photos/seed/civic-assembly/1000/1200" width="1000" height="1200" alt="Neighbors gathering for a community assembly" fetchpriority="high">
          <div class="hero-badge" aria-hidden="true">People<br>powered<br>since 2016</div>
          <div class="hero-quote">
            <blockquote>“We stopped waiting to be invited. Now we help set the agenda.”</blockquote>
            <cite>— Nia Roberts, Southside chapter organizer</cite>
          </div>
        </div>
      </div>

      <div class="impact-strip" aria-label="Organization impact at a glance">
        <div class="container impact-grid">
          <div class="impact-stat">
            <strong>42</strong>
            <span>resident-led local chapters</span>
          </div>
          <div class="impact-stat">
            <strong>18.6k</strong>
            <span>active members and volunteers</span>
          </div>
          <div class="impact-stat">
            <strong>11</strong>
            <span>community-backed policy wins</span>
          </div>
          <div class="impact-stat">
            <strong>$14.8m</strong>
            <span>public investment unlocked</span>
          </div>
        </div>
      </div>
    </section>

    <section class="section" id="work" aria-labelledby="work-title">
      <div class="container">
        <div class="section-heading reveal">
          <span class="eyebrow">Where we focus</span>
          <div>
            <h2 id="work-title">We make belonging a public practice.</h2>
            <div class="section-intro">
              <p>
                We pair grassroots organizing with cultural connection and practical policy expertise. A campaign can begin over a shared meal, grow through listening sessions, and result in a budget line that outlasts the news cycle.
              </p>
              <p>
                Local chapters set their own priorities through annual assemblies. Our regional teams then provide research, training, accessibility support, and coalition-building tools so good ideas can travel without losing their community roots.
              </p>
            </div>
          </div>
        </div>

        <div class="pillar-grid">
          <article class="pillar reveal" style="--delay: 60ms">
            <div class="pillar-top">
              <span class="pillar-icon" aria-hidden="true">
                <svg class="icon" viewBox="0 0 24 24">
                  <path d="M12 21s-7-4.4-7-11a4 4 0 0 1 7-2.6A4 4 0 0 1 19 10c0 6.6-7 11-7 11Z"></path>
                  <path d="M8.5 13.5c1.8 1 5.2 1 7 0"></path>
                </svg>
              </span>
              <span class="pillar-number">01</span>
            </div>
            <h3>Belonging by design</h3>
            <p>
              Inclusion is more than an open door. We support multilingual cultural programming, disability-led accessibility audits, intergenerational story circles, and neighborhood welcome projects that help people feel seen before asking them to speak.
            </p>
            <a class="text-link" href="#stories">Meet the people behind the work</a>
          </article>

          <article class="pillar reveal" style="--delay: 120ms">
            <div class="pillar-top">
              <span class="pillar-icon" aria-hidden="true">
                <svg class="icon" viewBox="0 0 24 24">
                  <path d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8ZM16 11a3 3 0 1 0 0-6"></path>
                  <path d="M2 21v-2a6 6 0 0 1 12 0v2M15 15a5 5 0 0 1 7 4.6V21"></path>
                </svg>
              </span>
              <span class="pillar-number">02</span>
            </div>
            <h3>Power with, not for</h3>
            <p>
              Our organizing fellowships teach meeting facilitation, public narrative, voter education, and ethical coalition building. Stipends, child care, and remote participation ensure that leadership is not limited to people with the most free time.
            </p>
            <a class="text-link" href="#about">See how shared leadership works</a>
          </article>

          <article class="pillar reveal" style="--delay: 180ms">
            <div class="pillar-top">
              <span class="pillar-icon" aria-hidden="true">
                <svg class="icon" viewBox="0 0 24 24">
                  <path d="M4 21V10l8-6 8 6v11"></path>
                  <path d="M9 21v-6h6v6M2 21h20"></path>
                </svg>
              </span>
              <span class="pillar-number">03</span>
            </div>
            <h3>Policy people can feel</h3>
            <p>
              We translate resident priorities into practical housing, transit, language-access, and public-space proposals. After a vote, we stay to track implementation—because a press release is not a bus shelter, an interpreter, or a kept promise.
            </p>
            <a class="text-link" href="#policy">Explore our policy impact</a>
          </article>
        </div>
      </div>
    </section>

    <section class="section section--sage" id="campaigns" aria-labelledby="campaigns-title">
      <div class="container">
        <div class="campaign-heading reveal">
          <div>
            <span class="eyebrow">Campaign updates</span>
            <h2 id="campaigns-title">Three campaigns. One shared agenda.</h2>
          </div>
          <p>
            Our current campaigns were chosen by local assemblies and shaped with the people most directly affected. Every action below has a clear purpose, a named decision-maker, and a next step.
          </p>
        </div>

        <div class="campaign-layout">
          <div class="campaign-main">
            <article class="campaign-feature reveal">
              <img class="campaign-feature-image" src="https://picsum.photos/seed/housing-neighbors/900/760" width="900" height="760" loading="lazy" decoding="async" alt="Residents gathered outside a neighborhood housing building">
              <div class="campaign-feature-content">
                <span class="tag">Housing justice · Lead campaign</span>
                <h3>Home Is Here</h3>
                <p>
                  A neighborhood should not become unaffordable to the people who made it worth loving. Home Is Here is a resident-led campaign to prevent displacement before the eviction notice, speculative purchase, or sudden rent hike.
                </p>
                <p>
                  Together with 23 tenant associations and housing partners, we are urging the city to capitalize a $12 million Community Land Trust Acquisition Fund, guarantee legal counsel for tenants, and require meaningful resident consultation on publicly subsidized developments.
                </p>

                <div class="campaign-progress">
                  <div class="progress-label">
                    <span>3,412 of 5,000 neighbor endorsements</span>
                    <span>68%</span>
                  </div>
                  <div class="progress-track" role="progressbar" aria-label="Campaign endorsement goal" aria-valuemin="0" aria-valuemax="100" aria-valuenow="68">
                    <span></span>
                  </div>
                </div>

                <p class="campaign-milestone"><strong>Next milestone:</strong> Housing budget hearing · Public comment opens soon</p>
                <div class="campaign-buttons">
                  <a class="button button--accent" href="#action-desk">Stand with us</a>
                  <button class="button button--outline" type="button" data-open-dialog="brief-dialog">Read the 2-minute brief</button>
                </div>
              </div>
            </article>

            <div class="campaign-card-grid">
              <article class="campaign-card reveal">
                <span class="tag">Mobility · Accessibility</span>
                <h3>Safe Routes for All</h3>
                <p>
                  Riders, students, older adults, and disabled neighbors are auditing high-injury corridors together. The awareness campaign pairs their findings with a practical standard for lighting, curb access, bus stops, and safe routes to school.
                </p>
                <span class="campaign-card-meta">31 corridors mapped · Council vote pending</span>
                <a class="text-link" href="#stories">Meet the rider coalition</a>
              </article>

              <article class="campaign-card reveal" style="--delay: 80ms">
                <span class="tag">Culture · Public investment</span>
                <h3>Culture Is Common Ground</h3>
                <p>
                  Small cultural organizations often anchor belonging with the fewest resources. This campaign seeks simplified community grants, affordable rehearsal space, and multilingual promotion so local culture can thrive beyond a single festival weekend.
                </p>
                <span class="campaign-card-meta">11 cultural partners · 6 neighborhood hubs</span>
                <a class="text-link" href="#news">Read the latest field notes</a>
              </article>
            </div>
          </div>

          <aside class="action-desk reveal" id="action-desk" aria-labelledby="action-title">
            <span class="eyebrow">Interactive action tracker</span>
            <h3 id="action-title">Your 20-minute action plan</h3>
            <p class="action-intro">
              Start where you are. Complete one action or all four, then check it off. Your progress is saved on this device—no account needed.
            </p>

            <div class="action-progress">
              <div class="progress-ring" id="progress-ring" aria-hidden="true">
                <span id="action-count">0/4</span>
              </div>
              <div class="action-progress-copy">
                <strong id="action-progress-label">0 of 4 actions complete</strong>
                <p id="action-message" aria-live="polite">Four small steps. Start with whichever feels easiest.</p>
              </div>
            </div>

            <div class="action-list">
              <div class="action-item">
                <input class="action-check" type="checkbox" id="action-brief" data-action-id="brief" aria-label="Mark Know the ask complete">
                <div>
                  <h4><label for="action-brief">Know the ask</label></h4>
                  <p>Get the context, funding request, and tenant protections in plain language.</p>
                  <div class="action-buttons">
                    <button class="action-link" type="button" data-open-dialog="brief-dialog">Read the brief <span aria-hidden="true">↗</span></button>
                  </div>
                </div>
              </div>

              <div class="action-item">
                <input class="action-check" type="checkbox" id="action-call" data-action-id="call" aria-label="Mark Make the one-minute call complete">
                <div>
                  <h4><label for="action-call">Make the one-minute call</label></h4>
                  <p>Use our adaptable script to ask your local representative to back the fund.</p>
                  <div class="action-buttons">
                    <button class="action-link" type="button" id="copy-script">Copy call script</button>
                    <a class="action-link" href="https://www.usa.gov/elected-officials" target="_blank" rel="noopener noreferrer">Find officials <span aria-hidden="true">↗</span></a>
                  </div>
                </div>
              </div>

              <div class="action-item">
                <input class="action-check" type="checkbox" id="action-attend" data-action-id="attend" aria-label="Mark Show up with neighbors complete">
                <div>
                  <h4><label for="action-attend">Show up with neighbors</label></h4>
                  <p id="assembly-date">Next monthly Community Action Assembly · 6:30 PM · Hybrid</p>
                  <div class="action-buttons">
                    <button class="action-link" type="button" id="add-calendar">Add to calendar <span aria-hidden="true">↓</span></button>
                  </div>
                </div>
              </div>

              <div class="action-item">
                <input class="action-check" type="checkbox" id="action-share" data-action-id="share" aria-label="Mark Grow the circle complete">
                <div>
                  <h4><label for="action-share">Grow the circle</label></h4>
                  <p>Invite one neighbor who cares about stable homes to learn about the campaign.</p>
                  <div class="action-buttons">
                    <button class="action-link" type="button" id="share-campaign">Share campaign <span aria-hidden="true">↗</span></button>
                  </div>
                </div>
              </div>
            </div>

            <div class="action-footer">
              <span class="action-privacy">Your checklist stays in this browser. We never see or sell your action data.</span>
              <button class="reset-actions" type="button" id="reset-actions">Reset progress</button>
            </div>
          </aside>
        </div>
      </div>
    </section>

    <section class="section" id="stories" aria-labelledby="stories-title">
      <div class="container">
        <div class="stories-heading reveal">
          <span class="eyebrow">Community stories</span>
          <h2 id="stories-title">The people are not the footnotes. They are the story.</h2>
          <p>
            Our community storytellers document the knowledge behind every campaign: what residents noticed, what they tried, and what changed. Stories are published with consent, compensated when produced for us, and always connected to a practical way forward.
          </p>
        </div>

        <div class="stories-grid">
          <article class="story-main reveal">
            <img class="story-main-image" src="https://picsum.photos/seed/route-eight-riders/1000/720" width="1000" height="720" loading="lazy" decoding="async" alt="Community members documenting their daily transit journeys">
            <div class="story-main-content">
              <span class="tag">Transit justice · Eastside</span>
              <h3>The night-shift riders who redrew Route 8</h3>
              <p>
                When the last bus was moved thirty minutes earlier, night-shift workers were told the change would affect only a handful of trips. Riders knew better. For three months, they documented missed connections, long walks home, inaccessible stops, and shifts cut short—turning private frustration into a public record.
              </p>
              <p>
                Their map, built in three languages from 186 rider interviews, brought transit planners to the same table. The resulting pilot restores two late trips, improves lighting at five stops, and creates a permanent rider review group with paid seats for shift workers.
              </p>
              <blockquote class="story-quote">
                “The data mattered. But being believed when we told our own stories—that changed the room.”
                <cite>Amara Okafor · Certified nursing assistant and rider organizer</cite>
              </blockquote>
              <a class="text-link" href="mailto:stories@civicthreadalliance.org?subject=I%20want%20to%20share%20my%20community%20story">Share your community story</a>
            </div>
          </article>

          <div class="story-side">
            <article class="story-mini reveal" style="--delay: 80ms">
              <img src="https://picsum.photos/seed/language-library/640/480" width="640" height="480" loading="lazy" decoding="async" alt="A welcoming neighborhood library and cultural space">
              <div class="story-mini-content">
                <span class="tag">Language access</span>
                <h3>A welcome in twelve languages</h3>
                <p>
                  A library card can be a first step into civic life. West End volunteers redesigned orientation sessions with local interpreters, then created a multilingual welcome series covering schools, tenant resources, public meetings, and arts programs.
                </p>
                <a class="text-link" href="#policy">See the language-access impact</a>
              </div>
            </article>

            <article class="story-mini reveal" style="--delay: 140ms">
              <img src="https://picsum.photos/seed/community-garden/640/480" width="640" height="480" loading="lazy" decoding="async" alt="A shared green space cared for by local residents">
              <div class="story-mini-content">
                <span class="tag">Community ownership</span>
                <h3>A vacant lot becomes a shared future</h3>
                <p>
                  What began as a seasonal garden became a resident-led land trust. Neighbors now hold a ninety-nine-year lease for growing space, affordable artist studios, and six permanently affordable homes planned with future residents.
                </p>
                <a class="text-link" href="#campaigns">Support community ownership</a>
              </div>
            </article>
          </div>
        </div>

        <h3 class="testimonial-heading">In their own words</h3>
        <div class="testimonial-grid">
          <article class="testimonial reveal">
            <blockquote>“I came for one meeting and found a place where my experience counted as expertise.”</blockquote>
            <div class="testimonial-person">
              <img src="https://i.pravatar.cc/96?u=civic-testimonial-nia" width="48" height="48" loading="lazy" alt="Portrait of Nia Roberts">
              <div>
                <strong>Nia Roberts</strong>
                <span>Tenant leader · Southside</span>
              </div>
            </div>
          </article>

          <article class="testimonial reveal" style="--delay: 80ms">
            <blockquote>“Civic Thread never asked our small organization to shrink its mission to fit the coalition.”</blockquote>
            <div class="testimonial-person">
              <img src="https://i.pravatar.cc/96?u=civic-testimonial-dev" width="48" height="48" loading="lazy" alt="Portrait of Dev Shah">
              <div>
                <strong>Dev Shah</strong>
                <span>Director · Mesa Cultural Arts</span>
              </div>
            </div>
          </article>

          <article class="testimonial reveal" style="--delay: 140ms">
            <blockquote>“My first public comment lasted ninety seconds. For the first time, I felt the city was listening.”</blockquote>
            <div class="testimonial-person">
              <img src="https://i.pravatar.cc/96?u=civic-testimonial-mateo" width="48" height="48" loading="lazy" alt="Portrait of Mateo Reyes">
              <div>
                <strong>Mateo Reyes</strong>
                <span>New member · Riverbend</span>
              </div>
            </div>
          </article>
        </div>
      </div>
    </section>

    <section class="section section--dark" id="policy" aria-labelledby="policy-title">
      <div class="container">
        <div class="policy-layout">
          <div class="policy-copy reveal">
            <span class="eyebrow">Policy impact</span>
            <h2 id="policy-title">Good policy is only the beginning.</h2>
            <p>
              Awareness can open a door; implementation decides who gets to walk through it. After every win, member-led policy teams track funding, delivery timelines, language access, and the public agencies responsible for each promise.
            </p>
            <p>
              We publish what changed, what stalled, and who was at the table. That transparency helps residents hold institutions accountable—and helps our coalition learn when a strategy needs to change.
            </p>
            <div class="policy-photo-wrap">
              <img class="policy-photo" src="https://picsum.photos/seed/public-policy/1000/720" width="1000" height="720" loading="lazy" decoding="async" alt="Residents participating in a public policy meeting">
              <div class="policy-photo-note">Accountability is a public practice.</div>
            </div>
          </div>

          <div class="policy-timeline reveal" style="--delay: 100ms">
            <h3>What changed because people showed up</h3>

            <article class="timeline-item">
              <span class="timeline-year">2022</span>
              <div>
                <h4>Language Access Ordinance</h4>
                <p>
                  Interpretation is now required at major public hearings, with translated meeting notices in nine languages. Community reviewers continue to score agency compliance twice a year.
                </p>
              </div>
            </article>

            <article class="timeline-item">
              <span class="timeline-year">2023</span>
              <div>
                <h4>People’s Budget Pilot</h4>
                <p>
                  More than 4,100 residents directed $2.4 million toward bus shelters, youth programs, lighting, and neighborhood food access. Outreach shifts and paper ballots helped include residents often left out of digital-only voting.
                </p>
              </div>
            </article>

            <article class="timeline-item">
              <span class="timeline-year">2024</span>
              <div>
                <h4>Safe Streets Standard</h4>
                <p>
                  Disability advocates, students, and transit riders helped establish a new repair standard for high-injury corridors. Thirty-one locations moved into the city’s funded capital plan with public delivery dates.
                </p>
              </div>
            </article>

            <details class="methodology">
              <summary>How we measure impact</summary>
              <p>
                Policy wins include ordinances, formal program standards, or dedicated public budget lines adopted since 2016 where a Civic Thread chapter or formal coalition had a documented role. Public investment figures represent multi-year government commitments—not revenue to our organization. We count outcomes once and publish corrections when implementation scopes change.
              </p>
            </details>
          </div>
        </div>

        <div class="policy-metrics reveal" aria-label="Policy impact metrics">
          <div class="policy-metric">
            <strong>11</strong>
            <span>policy and budget wins since 2016</span>
          </div>
          <div class="policy-metric">
            <strong>$14.8m</strong>
            <span>multi-year public investment committed</span>
          </div>
          <div class="policy-metric">
            <strong>9</strong>
            <span>languages used across civic materials</span>
          </div>
        </div>

        <div class="policy-cta reveal">
          <p>
            Are you part of a neighborhood association, cultural organization, union local, or grassroots group? We share facilitation tools, research templates, and implementation trackers with aligned partners.
          </p>
          <a class="button button--light" href="mailto:partnerships@civicthreadalliance.org?subject=Coalition%20partnership%20inquiry">Build a coalition with us</a>
        </div>
      </div>
    </section>

    <section class="section" id="news" aria-labelledby="news-title">
      <div class="container">
        <div class="news-header reveal">
          <div>
            <span class="eyebrow">News &amp; updates</span>
            <h2 id="news-title">Notes from the movement.</h2>
          </div>
          <p>
            Practical lessons, campaign reporting, and honest reflections from our organizers and partners. No victory laps without the messy middle.
          </p>
        </div>

        <div class="news-layout">
          <div class="news-grid">
            <article class="news-card news-card--lead reveal">
              <img class="news-card-image" src="https://picsum.photos/seed/listening-sessions/900/700" width="900" height="700" loading="lazy" decoding="async" alt="A community listening session around a shared table">
              <div class="news-card-content">
                <div class="news-meta"><span>Field note</span><time datetime="2025-06-12">June 12</time><span>6 min read</span></div>
                <h3>What 317 listening sessions taught us about belonging</h3>
                <p>
                  Residents did not ask for another slogan about community. They asked for predictable meeting times, translation before the day of an event, and a clear answer to one question: “What happened after I spoke?”
                </p>
                <button class="text-link" type="button" data-article="article-listening">Read the field note</button>
                <template id="article-listening">
                  <span class="dialog-meta">Field note · Community research</span>
                  <h2 id="article-dialog-title">What 317 listening sessions taught us about belonging</h2>
                  <p>
                    Over the past year, chapters hosted 317 listening sessions in libraries, places of worship, apartment courtyards, union halls, and online rooms. We asked residents where they felt able to influence a decision—and where participation felt like theater.
                  </p>
                  <p>
                    The most consistent barrier was not apathy. It was uncertainty. People wanted to know whether childcare would actually be available, whether an interpreter would be present from the beginning, and whether their contribution would receive a response. Small operational details carried enormous emotional weight.
                  </p>
                  <div class="dialog-callout">Participation grows when people can trace a line from what they said to what happened next.</div>
                  <p>
                    In response, every Civic Thread meeting now ends with a public decision log: what we heard, what remains unresolved, who owns the next step, and when we will report back. Chapters are also testing forty-eight-hour interpretation requests and rotating meeting schedules.
                  </p>
                  <p>
                    This research will guide our next organizer fellowship and a revised community meeting toolkit. We will publish the toolkit openly so partner organizations can adapt it to their own context.
                  </p>
                </template>
              </div>
            </article>

            <article class="news-card reveal">
              <img class="news-card-image" src="https://picsum.photos/seed/public-comment-guide/640/480" width="640" height="480" loading="lazy" decoding="async" alt="Notes prepared for a first public meeting">
              <div class="news-card-content">
                <div class="news-meta"><span>Organizing guide</span><time datetime="2025-05-28">May 28</time></div>
                <h3>Your first public comment, without the jargon</h3>
                <p>
                  A strong comment does not need to sound like a legal brief. Use this simple structure to connect one lived experience, one shared value, and one specific request.
                </p>
                <button class="text-link" type="button" data-article="article-comment">Read the guide</button>
                <template id="article-comment">
                  <span class="dialog-meta">Organizing guide · Civic participation</span>
                  <h2 id="article-dialog-title">Your first public comment, without the jargon</h2>
                  <p>
                    Public comment is one way to place experience and priorities into the official record. It does not require technical expertise, and you are allowed to read from notes. Start by checking the time limit, accessibility options, and whether remote testimony is available.
                  </p>
                  <h3>A simple three-part structure</h3>
                  <ol>
                    <li><strong>Name the moment:</strong> Briefly describe a real situation and how it affects you or your neighbors.</li>
                    <li><strong>Name the value:</strong> Explain what principle is at stake, such as safety, dignity, access, or stability.</li>
                    <li><strong>Name the request:</strong> Ask for one identifiable action, such as funding a program, delaying a vote, or publishing an implementation timeline.</li>
                  </ol>
                  <p>
                    Close with your name and affiliation if relevant. You do not need to answer questions beyond your experience. A chapter organizer can help you practice, but the story and the request should remain your own.
                  </p>
                </template>
              </div>
            </article>

            <article class="news-card reveal" style="--delay: 80ms">
              <img class="news-card-image" src="https://picsum.photos/seed/coalition-practice/640/480" width="640" height="480" loading="lazy" decoding="async" alt="Representatives from community organizations working together">
              <div class="news-card-content">
                <div class="news-meta"><span>Coalition practice</span><time datetime="2025-05-09">May 9</time></div>
                <h3>Coalition building without leaving small groups behind</h3>
                <p>
                  Shared campaigns can unintentionally reward organizations with the most staff. Four agreements helped our housing coalition distribute voice, visibility, and resources more fairly.
                </p>
                <button class="text-link" type="button" data-article="article-coalition">Read the update</button>
                <template id="article-coalition">
                  <span class="dialog-meta">Coalition practice · Shared leadership</span>
                  <h2 id="article-dialog-title">Coalition building without leaving small groups behind</h2>
                  <p>
                        A coalition is not automatically equitable because many organizations appear on its logo sheet. Groups with paid policy staff often have more time to shape language, attend last-minute meetings, and speak to the press.
                  </p>
                  <p>
                    Our housing coalition adopted four practical agreements: rotating facilitation, a forty-eight-hour review window for major positions, shared speaking opportunities, and a common resource pool for interpretation and participant stipends.
                  </p>
                  <p>
                    We also separate endorsement from workload. A small organization can support a campaign demand without committing to weekly meetings or a minimum number of volunteers. This makes participation more honest and prevents burnout from becoming a condition of belonging.
                  </p>
                  <div class="dialog-callout">Shared credit is not a courtesy. It is part of shared power.</div>
                </template>
              </div>
            </article>
          </div>

          <aside class="events-panel reveal" aria-labelledby="events-title">
            <h3 id="events-title">Come into the room</h3>
            <p>Free, beginner-friendly gatherings with access requests welcomed.</p>
            <div class="event-list">
              <article class="event-item">
                <time class="event-date" data-event-offset="6" datetime="2025-06-18">
                  <span class="event-month">JUN</span>
                  <span class="event-day">18</span>
                </time>
                <div class="event-details">
                  <h4>New Member Welcome</h4>
                  <p>12:00 PM · Online · 45 minutes</p>
                  <a href="#join" data-interest="events">RSVP for welcome</a>
                </div>
              </article>

              <article class="event-item">
                <time class="event-date" data-event-offset="13" datetime="2025-06-25">
                  <span class="event-month">JUN</span>
                  <span class="event-day">25</span>
                </time>
                <div class="event-details">
                  <h4>Tenant Organizing Basics</h4>
                  <p>6:30 PM · Hybrid · Interpretation available</p>
                  <a href="#join" data-interest="campaigns">Get involved</a>
                </div>
              </article>

              <article class="event-item">
                <time class="event-date" data-event-offset="20" datetime="2025-07-02">
                  <span class="event-month">JUL</span>
                  <span class="event-day">02</span>
                </time>
                <div class="event-details">
                  <h4>Neighborhood Story Circle</h4>
                  <p>5:30 PM · Commons Hall · Meal provided</p>
                  <a href="#join" data-interest="stories">Save my seat</a>
                </div>
              </article>
            </div>
          </aside>
        </div>
      </div>
    </section>

    <section class="section section--about" id="about" aria-labelledby="about-title">
      <div class="container">
        <div class="about-grid">
          <div class="about-statement reveal">
            <span class="eyebrow">About the alliance</span>
            <h2 id="about-title">A coalition, not a podium.</h2>
            <p class="lead">
              Civic Thread Alliance exists to make community power more durable, more inclusive, and more joyful.
            </p>
            <p>
              We were founded in 2016 by tenant leaders, artists, disability advocates, librarians, and faith-community volunteers who kept meeting at the same public hearings. They realized that showing up separately made it easier for institutions to divide shared concerns—and harder for residents to sustain the work.
            </p>
            <p>
              Today, local chapters choose priorities through annual assemblies. A delegate council sets alliance-wide strategy, and at least 60% of its seats belong to people directly affected by our campaign issues. We are nonpartisan, but we are not neutral about dignity, access, or democratic participation.
            </p>
            <a class="button button--outline" href="#faq">Read our commitments and FAQs</a>
          </div>

          <div class="principles">
            <article class="principle reveal">
              <span class="principle-number">01 / GOVERNANCE</span>
              <h3>Resident-led agendas</h3>
              <p>
                Campaign priorities begin in chapter assemblies. Staff provide evidence and logistics; they do not override member decisions.
              </p>
            </article>
            <article class="principle reveal" style="--delay: 60ms">
              <span class="principle-number">02 / TRUST</span>
              <h3>Transparent resources</h3>
              <p>
                We publish our funding mix, coalition grants, and campaign expenditures in plain-language annual summaries.
              </p>
            </article>
            <article class="principle reveal" style="--delay: 100ms">
              <span class="principle-number">03 / ACCESS</span>
              <h3>Accessible by default</h3>
              <p>
                Access planning starts before an event is announced, with hybrid options, captions, interpretation, and clear venues.
              </p>
            </article>
            <article class="principle reveal" style="--delay: 140ms">
              <span class="principle-number">04 / CULTURE</span>
              <h3>Joy is infrastructure</h3>
              <p>
                Food, art, music, and celebration are not extras. They sustain relationships long enough to make difficult change possible.
              </p>
            </article>
          </div>
        </div>

        <div class="partner-band reveal">
          <span class="partner-label">Trusted coalition partners</span>
          <ul class="partner-list" aria-label="Partner organizations">
            <li>Northstar Tenants Union</li>
            <li>Mesa Cultural Arts</li>
            <li>Access Transit Coalition</li>
            <li>Riverbend Mutual Aid</li>
            <li>Commons Library Network</li>
          </ul>
        </div>
      </div>
    </section>

    <section class="section" id="faq" aria-labelledby="faq-title">
      <div class="container faq-layout">
        <div class="faq-intro reveal">
          <span class="eyebrow">Good questions</span>
          <h2 id="faq-title">Answers, without the fine-print feeling.</h2>
          <p>
            Still wondering whether this is the right place for you? Write to <a href="mailto:hello@civicthreadalliance.org">hello@civicthreadalliance.org</a> and a real member of our team will respond.
          </p>
        </div>

        <div class="faq-list reveal">
          <details class="faq-item" open>
            <summary>Do I need organizing experience to join?</summary>
            <div class="faq-answer">
              <p>
                Not at all. Most members begin by attending a welcome session, helping with one event, or taking a single digital action. Free trainings cover public speaking, meeting facilitation, campaign strategy, and community research; experienced members are paired with newcomers rather than treated as gatekeepers.
              </p>
            </div>
          </details>

          <details class="faq-item">
            <summary>Is Civic Thread affiliated with a political party?</summary>
            <div class="faq-answer">
              <p>
                No. Civic Thread Alliance is a nonpartisan 501(c)(3) community organization. We do not endorse candidates or coordinate with political campaigns. We evaluate public policies by their likely impact on residents and publish the evidence and community process behind our positions.
              </p>
            </div>
          </details>

          <details class="faq-item">
            <summary>How is the work funded?</summary>
            <div class="faq-answer">
              <p>
                Approximately 58% of our funding comes from individual giving, 27% from independent foundations, 10% from ticketed cultural events and trainings, and 5% from sliding-scale coalition contributions. No organization is denied partnership because it cannot pay. We do not accept contributions that require candidate endorsements, personal data, or control over a campaign position.
              </p>
            </div>
          </details>

          <details class="faq-item">
            <summary>I cannot attend evening meetings. Can I still participate?</summary>
            <div class="faq-answer">
              <p>
                Yes. Members contribute through daytime calls, asynchronous research, translation, art, phone banking, childcare teams, and accessible digital actions. Chapters also rotate meeting times and offer remote participation. Tell us what makes participation workable for you, and we will problem-solve together.
              </p>
            </div>
          </details>

          <details class="faq-item">
            <summary>Can our organization join the coalition?</summary>
            <div class="faq-answer">
              <p>
                We welcome aligned neighborhood associations, cultural groups, service organizations, worker groups, and informal resident teams. Partnership begins with a conversation about shared goals and decision-making—not a fee or a logo exchange. Email our partnerships team to arrange an introductory call.
              </p>
            </div>
          </details>
        </div>
      </div>
    </section>

    <section class="join-section" id="join" aria-labelledby="join-title">
      <div class="container">
        <div class="join-panel reveal">
          <div class="join-copy">
            <span class="eyebrow">There is a place for you here</span>
            <h2 id="join-title">Your corner of the movement is waiting.</h2>
            <p>
              Whether you have ten minutes or ten years of experience, there is a useful role for you. Join free, meet people working on the issues you care about, and choose how often you hear from us.
            </p>
            <p>
              We will match you with a local chapter or a distributed action team, send one thoughtful email each month, and never sell your information.
            </p>
            <ul class="join-benefits">
              <li>A friendly welcome and chapter orientation</li>
              <li>Free organizing and civic-participation training</li>
              <li>Action alerts you can tailor or pause anytime</li>
            </ul>
          </div>

          <div class="join-form-wrap">
            <form id="join-form" action="mailto:join@civicthreadalliance.org" method="post" enctype="text/plain">
              <h3>Join Civic Thread</h3>
              <p class="form-intro">Start with a few details. Membership is free and open to everyone.</p>

              <div class="form-row">
                <div class="form-field">
                  <label for="first-name">First name</label>
                  <input id="first-name" name="firstName" type="text" autocomplete="given-name" placeholder="Your first name" required>
                </div>
                <div class="form-field">
                  <label for="postal-code">ZIP or postal code</label>
                  <input id="postal-code" name="postalCode" type="text" autocomplete="postal-code" maxlength="12" placeholder="e.g. 02903" required>
                </div>
              </div>

              <div class="form-field">
                <label for="email">Email address</label>
                <input id="email" name="email" type="email" autocomplete="email" placeholder="you@example.org" required>
              </div>

              <div class="form-field">
                <label for="interest">I am most interested in</label>
                <select id="interest" name="interest" required>
                  <option value="">Choose a starting point</option>
                  <option value="local">Meeting my local chapter</option>
                  <option value="campaigns">Campaigns and advocacy</option>
                  <option value="events">Community and cultural events</option>
                  <option value="stories">Storytelling and creative work</option>
                  <option value="partnership">Organizational partnership</option>
                </select>
              </div>

              <div class="consent-field">
                <input id="consent" name="consent" type="checkbox" required>
                <label for="consent">Send me action alerts and the monthly Field Notes newsletter. I understand I can unsubscribe at any time.</label>
              </div>

              <button class="button button--accent join-submit" type="submit">Join the movement <span aria-hidden="true">→</span></button>
              <p class="form-privacy">By joining, you acknowledge our <a href="#privacy-dialog" data-open-dialog="privacy-dialog">Privacy Policy</a>.</p>
            </form>

            <div class="join-success" id="join-success" role="status" tabindex="-1" hidden>
              <div class="success-mark" aria-hidden="true">✓</div>
              <h3>Welcome to the thread, <span id="success-name">neighbor</span>.</h3>
              <p>
                You are part of a growing community of people turning care into action. Watch your inbox for a confirmation and your personalized welcome guide.
              </p>
              <button class="text-link" type="button" id="join-another">Register another person</button>
            </div>
          </div>
        </div>
      </div>
    </section>
  </main>

  <footer class="site-footer">
    <div class="container">
      <div class="footer-grid">
        <div class="footer-brand">
          <a class="brand" href="#top" aria-label="Civic Thread Alliance home">
            <img class="brand-logo" src="https://placehold.co/56x56/f3bf57/173b35?text=CT&font=montserrat" width="48" height="48" loading="lazy" alt="Civic Thread Alliance monogram">
            <span class="brand-copy">
              <span class="brand-name">Civic Thread Alliance</span>
              <span class="brand-tagline">Many voices. One shared future.</span>
            </span>
          </a>
          <p>
            We weave community stories, cultural connection, and collective action into lasting change. Independent, nonpartisan, and led by the people closest to the issues.
          </p>
          <div class="social-links" aria-label="Social media">
            <a href="https://www.instagram.com/civicthreadalliance/" target="_blank" rel="noopener noreferrer" aria-label="Civic Thread Alliance on Instagram">
              <svg class="icon" viewBox="0 0 24 24" aria-hidden="true">
                <rect x="3" y="3" width="18" height="18" rx="5"></rect>
                <circle cx="12" cy="12" r="4"></circle>
                <path d="M17.5 6.5h.01"></path>
              </svg>
            </a>
            <a href="https://www.facebook.com/civicthreadalliance/" target="_blank" rel="noopener noreferrer" aria-label="Civic Thread Alliance on Facebook">
              <svg class="icon" viewBox="0 0 24 24" aria-hidden="true">
                <path d="M14 8h3V4h-3c-3 0-5 2-5 5v3H6v4h3v5h4v-5h3l1-4h-4V9c0-.6.4-1 1-1Z"></path>
              </svg>
            </a>
            <a href="https://www.linkedin.com/company/civic-thread-alliance/" target="_blank" rel="noopener noreferrer" aria-label="Civic Thread Alliance on LinkedIn">
              <svg class="icon" viewBox="0 0 24 24" aria-hidden="true">
                <path d="M6 9v10M6 5v.01M10 19v-6a4 4 0 0 1 8 0v6M10 9v10"></path>
              </svg>
            </a>
            <a href="https://www.youtube.com/@civicthreadalliance" target="_blank" rel="noopener noreferrer" aria-label="Civic Thread Alliance on YouTube">
              <svg class="icon" viewBox="0 0 24 24" aria-hidden="true">
                <path d="M21 8s-.2-2-1-2.8c-1-.9-2.1-.9-2.6-1C13.8 4 12 4 12 4s-1.8 0-5.4.2c-.5.1-1.6.1-2.6 1C3.2 6 3 8 3 8s-.2 2.3 0 4.6c.1 2.2.2 3.4.2 3.4s.2 2 1 2.8c1 .9 2.3.9 2.8 1 2.1.2 5 .2 5 .2s1.8 0 5.4-.2c.5-.1 1.6-.1 2.6-1 .8-.8 1-2.8 1-2.8s.1-1.2.2-3.4C21.3 10.3 21 8 21 8Z"></path>
                <path d="m10 9 5 3-5 3Z"></path>
              </svg>
            </a>
          </div>
        </div>

        <div class="footer-column">
          <h2>Explore</h2>
          <ul class="footer-links">
            <li><a href="#work">Our Work</a></li>
            <li><a href="#stories">Community Stories</a></li>
            <li><a href="#campaigns">Current Campaigns</a></li>
            <li><a href="#policy">Policy Impact</a></li>
            <li><a href="#news">News &amp; Events</a></li>
            <li><a href="#about">About Us</a></li>
          </ul>
        </div>

        <div class="footer-column">
          <h2>Take part</h2>
          <ul class="footer-links">
            <li><a href="#join">Become a member</a></li>
            <li><a href="#action-desk">Take an action</a></li>
            <li><a href="#news">Attend an event</a></li>
            <li><a href="mailto:stories@civicthreadalliance.org?subject=Community%20story">Share your story</a></li>
            <li><a href="mailto:partnerships@civicthreadalliance.org?subject=Partnership%20inquiry">Partner with us</a></li>
            <li><a href="mailto:access@civicthreadalliance.org?subject=Accessibility%20request">Request an accommodation</a></li>
          </ul>
        </div>

        <div class="footer-column">
          <h2>Visit or write</h2>
          <address class="footer-contact">
            <p>14 Commons Way, Suite 300<br>Providence, RI 02903</p>
            <p><a href="mailto:hello@civicthreadalliance.org">hello@civicthreadalliance.org</a><br><a href="tel:+14015550148">(401) 555-0148</a></p>
            <p>Office hours<br>Monday–Friday, 9:00 AM–5:30 PM ET</p>
          </address>
        </div>
      </div>

      <div class="footer-bottom">
        <p>© <span data-year>2025</span> Civic Thread Alliance. All rights reserved. Nonpartisan 501(c)(3) · EIN 47-2189056.</p>
        <div class="legal-links">
          <a href="#privacy-dialog" data-open-dialog="privacy-dialog">Privacy</a>
          <a href="#terms-dialog" data-open-dialog="terms-dialog">Terms</a>
          <a href="mailto:access@civicthreadalliance.org?subject=Website%20accessibility">Accessibility</a>
        </div>
      </div>
    </div>
  </footer>

  <dialog id="brief-dialog" aria-labelledby="brief-title">
    <div class="dialog-shell">
      <button class="dialog-close" type="button" data-dialog-close aria-label="Close campaign brief">×</button>
      <div class="dialog-content">
        <span class="dialog-meta">Home Is Here · 2-minute campaign brief</span>
        <h2 id="brief-title">Keep neighbors in the neighborhoods they shape.</h2>
        <p>
          Rising housing costs and speculative acquisitions are displacing residents from communities with strong cultural and social networks. Existing emergency programs often intervene only after a household is already in crisis. Home Is Here focuses on prevention, permanent affordability, and resident ownership.
        </p>
        <h3>Our three shared demands</h3>
        <ol>
          <li><strong>Capitalize a $12 million Community Land Trust Acquisition Fund.</strong> This would help resident-led trusts purchase at-risk buildings and preserve affordability for the long term.</li>
          <li><strong>Guarantee legal counsel for eligible tenants.</strong> Independent representation helps residents understand their rights and prevents avoidable evictions.</li>
          <li><strong>Require meaningful consultation on publicly subsidized development.</strong> Consultation must include accessible meetings, translated materials, published responses, and resident representation throughout delivery.</li>
        </ol>
        <h3>Why this coalition</h3>
        <p>
          The campaign is supported by 23 tenant associations, cultural organizations, legal-aid partners, and neighborhood groups. Civic Thread provides coordination and public research, while campaign demands are approved through resident assemblies.
        </p>
        <div class="dialog-callout">Stable homes are not a private luxury. They are the foundation of participation, culture, health, and community life.</div>
        <p>
          The immediate opportunity is the upcoming housing budget process. Public comment, targeted calls, and visible resident attendance can determine whether these proposals receive a dedicated funding line or remain recommendations.
        </p>
        <div class="dialog-actions">
          <button class="button button--accent" type="button" id="copy-summary">Copy campaign summary</button>
          <button class="button button--outline" type="button" data-dialog-close>Back to the action desk</button>
        </div>
      </div>
    </div>
  </dialog>

  <dialog id="article-dialog" aria-labelledby="article-dialog-title">
    <div class="dialog-shell">
      <button class="dialog-close" type="button" data-dialog-close aria-label="Close article">×</button>
      <div class="dialog-content" id="article-dialog-content"></div>
    </div>
  </dialog>

  <dialog id="privacy-dialog" aria-labelledby="privacy-title">
    <div class="dialog-shell">
      <button class="dialog-close" type="button" data-dialog-close aria-label="Close privacy policy">×</button>
      <div class="dialog-content">
        <span class="dialog-meta">Privacy · Last updated <span data-year>2025</span></span>
        <h2 id="privacy-title">Your story belongs to you.</h2>
        <p>
          Civic Thread Alliance collects only the information needed to provide membership, events, volunteering, and communications you request. This may include your name, contact details, general location, interests, accessibility requests, and participation preferences.
        </p>
        <h3>How we use information</h3>
        <p>
          We use information to connect you with relevant chapters, administer events, respond to inquiries, improve accessibility, and send communications for which you have opted in. We do not sell personal information or use membership lists for candidate advertising.
        </p>
        <h3>Your choices</h3>
        <p>
          You may unsubscribe from communications, request a correction, or ask us to delete your information by emailing <a href="mailto:privacy@civicthreadalliance.org">privacy@civicthreadalliance.org</a>. The on-page action tracker stores checklist progress only in your browser; it is not transmitted to us.
        </p>
        <h3>Retention and care</h3>
        <p>
          We retain information only as long as needed for the stated purpose or a legal obligation. Access is limited to authorized staff and volunteers, and sensitive accessibility details are shared only with the people arranging the relevant accommodation.
        </p>
      </div>
    </div>
  </dialog>

  <dialog id="terms-dialog" aria-labelledby="terms-title">
    <div class="dialog-shell">
      <button class="dialog-close" type="button" data-dialog-close aria-label="Close terms of use">×</button>
      <div class="dialog-content">
        <span class="dialog-meta">Terms of use · Plain-language summary</span>
        <h2 id="terms-title">Use this space with care.</h2>
        <p>
          This website provides general information about Civic Thread Alliance, our campaigns, and opportunities for civic participation. It does not provide legal advice, and campaign resources should be adapted to your local context.
        </p>
        <h3>Community resources</h3>
        <p>
          You may share noncommercial campaign summaries and organizing guides with attribution. Please do not alter materials in a way that misrepresents a campaign position, removes important context, or implies endorsement by another person or organization.
        </p>
        <h3>Respect and accessibility</h3>
        <p>
          Participation in our digital and in-person spaces requires respect for other people’s dignity, privacy, and boundaries. Harassment, discriminatory conduct, and publishing another person’s story or personal details without consent are not permitted.
        </p>
        <h3>Questions</h3>
        <p>
          Questions about these terms, content reuse, or a correction can be sent to <a href="mailto:hello@civicthreadalliance.org">hello@civicthreadalliance.org</a> or mailed to our Providence office.
        </p>
      </div>
    </div>
  </dialog>

  <div class="toast" id="toast" role="status" aria-live="polite"></div>

  <script>
    (() => {
      "use strict";

      const $ = (selector, scope = document) => scope.querySelector(selector);
      const $$ = (selector, scope = document) => Array.from(scope.querySelectorAll(selector));

      // Dynamic dates and current-year details.
      const currentYear = new Date().getFullYear();
      $$("[data-year]").forEach(element => {
        element.textContent = currentYear;
      });

      $$("[data-event-offset]").forEach(timeElement => {
        const eventDate = new Date();
        eventDate.setDate(eventDate.getDate() + Number(timeElement.dataset.eventOffset));
        timeElement.dateTime = eventDate.toISOString().slice(0, 10);
        $(".event-month", timeElement).textContent = eventDate.toLocaleDateString("en-US", { month: "short" }).toUpperCase();
        $(".event-day").textContent;
        $(".event-day", timeElement).textContent = String(eventDate.getDate()).padStart(2, "0");
        timeElement.setAttribute("aria-label", eventDate.toLocaleDateString("en-US", {
          weekday: "long",
          month: "long",
          day: "numeric"
        }));
      });

      // Sticky header treatment and mobile navigation.
      const header = $("#site-header");
      const menuButton = $(".menu-toggle");
      const primaryNav = $("#primary-navigation");

      const updateHeader = () => {
        header.classList.toggle("is-scrolled", window.scrollY > 12);
      };

      updateHeader();
      window.addEventListener("scroll", updateHeader, { passive: true });

      const closeMenu = () => {
        menuButton.setAttribute("aria-expanded", "false");
        $(".sr-only", menuButton).textContent = "Open navigation menu";
        primaryNav.classList.remove("is-open");
      };

      menuButton.addEventListener("click", () => {
        const willOpen = menuButton.getAttribute("aria-expanded") !== "true";
        menuButton.setAttribute("aria-expanded", String(willOpen));
        $(".sr-only", menuButton).textContent = willOpen ? "Close navigation menu" : "Open navigation menu";
        primaryNav.classList.toggle("is-open", willOpen);
      });

      $$("a", primaryNav).forEach(link => link.addEventListener("click", closeMenu));

      document.addEventListener("click", event => {
        if (primaryNav.classList.contains("is-open") && !header.contains(event.target)) {
          closeMenu();
        }
      });

      document.addEventListener("keydown", event => {
        if (event.key === "Escape" && primaryNav.classList.contains("is-open")) {
          closeMenu();
          menuButton.focus();
        }
      });

      window.addEventListener("resize", () => {
        if (window.innerWidth > 1000) closeMenu();
      });

      // Reveal content progressively, with a no-observer fallback.
      const revealElements = $$(".reveal");
      if ("IntersectionObserver" in window) {
        const revealObserver = new IntersectionObserver(entries => {
          entries.forEach(entry => {
            if (entry.isIntersecting) {
              entry.target.classList.add("is-visible");
              revealObserver.unobserve(entry.target);
            }
          });
        }, { threshold: 0.08, rootMargin: "0px 0px -30px" });

        revealElements.forEach(element => revealObserver.observe(element));
      } else {
        revealElements.forEach(element => element.classList.add("is-visible"));
      }

      // Accessible native dialogs.
      const openDialog = dialog => {
        if (!dialog) return;
        if (typeof dialog.showModal === "function") {
          dialog.showModal();
        } else {
          dialog.setAttribute("open", "");
        }
        document.body.classList.add("dialog-open");
      };

      const closeDialog = dialog => {
        if (!dialog) return;
        if (typeof dialog.close === "function") {
          dialog.close();
        } else {
          dialog.removeAttribute("open");
          document.body.classList.remove("dialog-open");
        }
      };

      $$("[data-open-dialog]").forEach(trigger => {
        trigger.addEventListener("click", event => {
          event.preventDefault();
          openDialog(document.getElementById(trigger.dataset.openDialog));
        });
      });

      $$("dialog").forEach(dialog => {
        $$("[data-dialog-close]", dialog).forEach(button => {
          button.addEventListener("click", () => closeDialog(dialog));
        });

        dialog.addEventListener("close", () => {
          document.body.classList.remove("dialog-open");
        });

        dialog.addEventListener("click", event => {
          if (event.target !== dialog) return;
          const bounds = dialog.getBoundingClientRect();
          const outside = event.clientX < bounds.left ||
            event.clientX > bounds.right ||
            event.clientY < bounds.top ||
            event.clientY > bounds.bottom;
          if (outside) closeDialog(dialog);
        });
      });

      // Expand complete news articles in a reusable reader dialog.
      const articleDialog = $("#article-dialog");
      const articleContent = $("#article-dialog-content");

      $$("[data-article]").forEach(button => {
        button.addEventListener("click", () => {
          const template = document.getElementById(button.dataset.article);
          if (!template) return;
          articleContent.replaceChildren(template.content.cloneNode(true));
          openDialog(articleDialog);
        });
      });

      // Toast notifications.
      const toast = $("#toast");
      let toastTimer;

      const showToast = message => {
        window.clearTimeout(toastTimer);
        toast.textContent = message;
        toast.classList.add("is-visible");
        toastTimer = window.setTimeout(() => {
          toast.classList.remove("is-visible");
        }, 4200);
      };

      const copyText = async text => {
        try {
          if (navigator.clipboard && window.isSecureContext) {
            await navigator.clipboard.writeText(text);
          } else {
            const textArea = document.createElement("textarea");
            textArea.value = text;
            textArea.style.position = "fixed";
            textArea.style.opacity = "0";
            document.body.appendChild(textArea);
            textArea.select();
            const copied = document.execCommand("copy");
            textArea.remove();
            if (!copied) throw new Error("Copy command was unavailable");
          }
          return true;
        } catch (error) {
          return false;
        }
      };

      const callScript = "Hello, my name is [your name], and I live in [your neighborhood or ward]. I am calling to ask [representative’s name] to support a $12 million Community Land Trust Acquisition Fund and guaranteed legal counsel for tenants in this year’s housing budget. Stable homes make strong neighborhoods, and residents deserve a meaningful voice in development. Please share my support with the representative. Thank you.";

      $("#copy-script").addEventListener("click", async () => {
        const copied = await copyText(callScript);
        showToast(copied
          ? "Call script copied. Add your name and neighborhood before calling."
          : "Copy was unavailable. Please try again from a secure browser window.");
      });

      $("#copy-summary").addEventListener("click", async () => {
        const summary = "Home Is Here is a resident-led Civic Thread Alliance campaign calling for a $12 million Community Land Trust Acquisition Fund, guaranteed legal counsel for eligible tenants, and meaningful resident consultation on publicly subsidized development. Stable homes are the foundation of inclusive, thriving neighborhoods.";
        const copied = await copyText(summary);
        showToast(copied ? "Campaign summary copied and ready to share." : "Copy was unavailable. Please try again.");
      });

      // Monthly assembly date and downloadable calendar invitation.
      const getNextAssembly = () => {
        const now = new Date();

        const thirdThursday = (year, month) => {
          const date = new Date(year, month, 1, 18, 30, 0, 0);
          const offset = (4 - date.getDay() + 7) % 7;
          date.setDate(1 + offset + 14);
          return date;
        };

        let assembly = thirdThursday(now.getFullYear(), now.getMonth());
        if (assembly <= now) {
          assembly = thirdThursday(now.getFullYear(), now.getMonth() + 1);
        }
        return assembly;
      };

      const assemblyDate = getNextAssembly();
      $("#assembly-date").textContent = `${assemblyDate.toLocaleDateString("en-US", {
        weekday: "long",
        month: "long",
        day: "numeric"
      })} · 6:30 PM · Hybrid Community Action Assembly`;

      const toICSDate = date => date.toISOString().replace(/[-:]/g, "").split(".")[0] + "Z";

      $("#add-calendar").addEventListener("click", () => {
        const endDate = new Date(assemblyDate.getTime() + 90 * 60 * 1000);
        const calendar = [
          "BEGIN:VCALENDAR",
          "VERSION:2.0",
          "CALSCALE:GREGORIAN",
          "PRODID:-//Civic Thread Alliance//Community Action Assembly//EN",
          "BEGIN:VEVENT",
          `UID:assembly-${assemblyDate.getTime()}@civicthreadalliance.org`,
          `DTSTAMP:${toICSDate(new Date())}`,
          `DTSTART:${toICSDate(assemblyDate)}`,
          `DTEND:${toICSDate(endDate)}`,
          "SUMMARY:Civic Thread Community Action Assembly",
          "DESCRIPTION:Meet neighbors, receive a Home Is Here campaign update, and prepare for the upcoming housing budget hearing. Beginners welcome.",
          "LOCATION:Commons Hall\\, 14 Commons Way\\, Providence\\, RI and Online",
          "END:VEVENT",
          "END:VCALENDAR"
        ].join("\r\n");

        const file = new Blob([calendar], { type: "text/calendar;charset=utf-8" });
        const url = URL.createObjectURL(file);
        const link = document.createElement("a");
        link.href = url;
        link.download = "civic-thread-community-assembly.ics";
        document.body.appendChild(link);
        link.click();
        link.remove();
        window.setTimeout(() => URL.revokeObjectURL(url), 1000);
        showToast("Calendar invitation downloaded. We look forward to seeing you.");
      });

      $("#share-campaign").addEventListener("click", async () => {
        const shareData = {
          title: "Home Is Here | Civic Thread Alliance",
          text: "Stable homes make strong neighborhoods. Learn how residents are working for community ownership, tenant counsel, and a real voice in development.",
          url: `${window.location.href.split("#")[0]}#campaigns`
        };

        if (navigator.share) {
          try {
            await navigator.share(shareData);
            return;
          } catch (error) {
            if (error.name === "AbortError") return;
          }
        }

        const copied = await copyText(`${shareData.text} ${shareData.url}`);
        showToast(copied ? "Campaign message and link copied. Send them to a neighbor." : "Sharing was unavailable. Please copy the page address from your browser.");
      });

      // Local action tracker with resilient localStorage access.
      const actionChecks = $$(".action-check");
      const storageKey = "civic-thread-action-plan-v1";
      const progressRing = $("#progress-ring");
      const actionCount = $("#action-count");
      const progressLabel = $("#action-progress-label");
      const actionMessage = $("#action-message");

      const messages = [
        "Four small steps. Start with whichever feels easiest.",
        "A strong start. Your next action is ready when you are.",
        "Halfway there—your effort is part of something bigger.",
        "One step left. Thank you for staying with it.",
        "All four complete. That is people power in practice."
      ];

      const readSavedActions = () => {
        try {
          const saved = JSON.parse(localStorage.getItem(storageKey) || "[]");
          return Array.isArray(saved) ? saved : [];
        } catch (error) {
          return [];
        }
      };

      const updateActionTracker = (save = true) => {
        const completed = actionChecks.filter(check => check.checked);
        const completedIds = completed.map(check => check.dataset.actionId);
        const percentage = (completed.length / actionChecks.length) * 100;

        actionChecks.forEach(check => {
          check.closest(".action-item").classList.toggle("is-complete", check.checked);
        });

        progressRing.style.setProperty("--progress", percentage);
        actionCount.textContent = `${completed.length}/${actionChecks.length}`;
        progressLabel.textContent = `${completed.length} of ${actionChecks.length} actions complete`;
        actionMessage.textContent = messages[completed.length];

        if (save) {
          try {
            localStorage.setItem(storageKey, JSON.stringify(completedIds));
          } catch (error) {
            // The tracker remains functional for this visit when storage is unavailable.
          }
        }
      };

      const savedActions = readSavedActions();
      actionChecks.forEach(check => {
        check.checked = savedActions.includes(check.dataset.actionId);
        check.addEventListener("change", () => updateActionTracker(true));
      });
      updateActionTracker(false);

      $("#reset-actions").addEventListener("click", () => {
        actionChecks.forEach(check => {
          check.checked = false;
        });
        try {
          localStorage.removeItem(storageKey);
        } catch (error) {
          // No action required when browser storage is unavailable.
        }
        updateActionTracker(false);
        showToast("Your action tracker has been reset.");
      });

      // Keep the FAQ focused by opening one answer at a time.
      const faqItems = $$(".faq-item");
      faqItems.forEach(item => {
        item.addEventListener("toggle", () => {
          if (!item.open) return;
          faqItems.forEach(other => {
            if (other !== item) other.open = false;
          });
        });
      });

      // Event links preselect the most relevant membership interest.
      const interestSelect = $("#interest");
      $$("[data-interest]").forEach(link => {
        link.addEventListener("click", () => {
          interestSelect.value = link.dataset.interest;
        });
      });

      // Static-site membership form experience.
      const joinForm = $("#join-form");
      const joinSuccess = $("#join-success");
      const successName = $("#success-name");

      joinForm.addEventListener("submit", event => {
        event.preventDefault();
        if (!joinForm.reportValidity()) return;

        successName.textContent = $("#first-name").value.trim() || "neighbor";
        joinForm.hidden = true;
        joinSuccess.hidden = false;
        joinSuccess.focus();
      });

      $("#join-another").addEventListener("click", () => {
        joinForm.reset();
        joinSuccess.hidden = true;
        joinForm.hidden = false;
        $("#first-name").focus();
      });

      // Graceful image fallback while retaining the selected layout dimensions.
      $$("img").forEach(image => {
        image.addEventListener("error", () => {
          if (image.dataset.fallbackApplied) return;
          image.dataset.fallbackApplied = "true";
          const width = Number(image.getAttribute("width")) || 800;
          const height = Number(image.getAttribute("height")) || 600;
          image.src = `https://placehold.co/${width}x${height}/e4ebe0/173b35?text=Civic+Thread&font=montserrat`;
        });
      });
    })();
  </script>
</body>
</html>
View Axe Report (JSON)
{
  "testEngine": {
    "name": "axe-core",
    "version": "4.10.2"
  },
  "testRunner": {
    "name": "axe"
  },
  "testEnvironment": {
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/156.0.8078.4 Safari/537.36",
    "windowWidth": 1280,
    "windowHeight": 720,
    "orientationAngle": 0,
    "orientationType": "landscape-primary"
  },
  "timestamp": "2026-11-12T10:16:11.354Z",
  "url": "https://benchmark.aimac.invalid/406ad6ff52e9edfb43a1dd6435b05da306cd3cbb767e09aeb9e78ae4b8f534e4.html",
  "toolOptions": {
    "runOnly": {
      "type": "tag",
      "values": [
        "wcag2a",
        "wcag2aa",
        "wcag21a",
        "wcag21aa",
        "wcag22a",
        "wcag22aa"
      ]
    },
    "resultTypes": [
      "violations"
    ],
    "reporter": "v1"
  },
  "inapplicable": [
    {
      "id": "area-alt",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag244",
        "wcag412",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT6.a",
        "EN-301-549",
        "EN-9.2.4.4",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure <area> elements of image maps have alternative text",
      "help": "Active <area> elements must have alternative text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/area-alt?application=axeAPI",
      "nodes": []
    },
    {
      "id": "aria-braille-equivalent",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure aria-braillelabel and aria-brailleroledescription have a non-braille equivalent",
      "help": "aria-braille attributes must have a non-braille equivalent",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-braille-equivalent?application=axeAPI",
      "nodes": []
    },
    {
      "id": "aria-command-name",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "TTv5",
        "TT6.a",
        "EN-301-549",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure every ARIA button, link and menuitem has an accessible name",
      "help": "ARIA commands must have an accessible name",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-command-name?application=axeAPI",
      "nodes": []
    },
    {
      "id": "aria-input-field-name",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "TTv5",
        "TT5.c",
        "EN-301-549",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure every ARIA input field has an accessible name",
      "help": "ARIA input fields must have an accessible name",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-input-field-name?application=axeAPI",
      "nodes": []
    },
    {
      "id": "aria-meter-name",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag111",
        "EN-301-549",
        "EN-9.1.1.1"
      ],
      "description": "Ensure every ARIA meter node has an accessible name",
      "help": "ARIA meter nodes must have an accessible name",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-meter-name?application=axeAPI",
      "nodes": []
    },
    {
      "id": "aria-required-children",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag131",
        "EN-301-549",
        "EN-9.1.3.1"
      ],
      "description": "Ensure elements with an ARIA role that require child roles contain them",
      "help": "Certain ARIA roles must contain particular children",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-required-children?application=axeAPI",
      "nodes": []
    },
    {
      "id": "aria-required-parent",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag131",
        "EN-301-549",
        "EN-9.1.3.1"
      ],
      "description": "Ensure elements with an ARIA role that require parent roles are contained by them",
      "help": "Certain ARIA roles must be contained by particular parents",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-required-parent?application=axeAPI",
      "nodes": []
    },
    {
      "id": "aria-toggle-field-name",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "TTv5",
        "TT5.c",
        "EN-301-549",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure every ARIA toggle field has an accessible name",
      "help": "ARIA toggle fields must have an accessible name",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-toggle-field-name?application=axeAPI",
      "nodes": []
    },
    {
      "id": "aria-tooltip-name",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure every ARIA tooltip node has an accessible name",
      "help": "ARIA tooltip nodes must have an accessible name",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-tooltip-name?application=axeAPI",
      "nodes": []
    },
    {
      "id": "avoid-inline-spacing",
      "impact": null,
      "tags": [
        "cat.structure",
        "wcag21aa",
        "wcag1412",
        "EN-301-549",
        "EN-9.1.4.12",
        "ACT"
      ],
      "description": "Ensure that text spacing set through style attributes can be adjusted with custom stylesheets",
      "help": "Inline text spacing must be adjustable with custom stylesheets",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/avoid-inline-spacing?application=axeAPI",
      "nodes": []
    },
    {
      "id": "blink",
      "impact": null,
      "tags": [
        "cat.time-and-media",
        "wcag2a",
        "wcag222",
        "section508",
        "section508.22.j",
        "TTv5",
        "TT2.b",
        "EN-301-549",
        "EN-9.2.2.2"
      ],
      "description": "Ensure <blink> elements are not used",
      "help": "<blink> elements are deprecated and must not be used",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/blink?application=axeAPI",
      "nodes": []
    },
    {
      "id": "definition-list",
      "impact": null,
      "tags": [
        "cat.structure",
        "wcag2a",
        "wcag131",
        "EN-301-549",
        "EN-9.1.3.1"
      ],
      "description": "Ensure <dl> elements are structured correctly",
      "help": "<dl> elements must only directly contain properly-ordered <dt> and <dd> groups, <script>, <template> or <div> elements",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/definition-list?application=axeAPI",
      "nodes": []
    },
    {
      "id": "dlitem",
      "impact": null,
      "tags": [
        "cat.structure",
        "wcag2a",
        "wcag131",
        "EN-301-549",
        "EN-9.1.3.1"
      ],
      "description": "Ensure <dt> and <dd> elements are contained by a <dl>",
      "help": "<dt> and <dd> elements must be contained by a <dl>",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/dlitem?application=axeAPI",
      "nodes": []
    },
    {
      "id": "frame-focusable-content",
      "impact": null,
      "tags": [
        "cat.keyboard",
        "wcag2a",
        "wcag211",
        "TTv5",
        "TT4.a",
        "EN-301-549",
        "EN-9.2.1.1"
      ],
      "description": "Ensure <frame> and <iframe> elements with focusable content do not have tabindex=-1",
      "help": "Frames with focusable content must not have tabindex=-1",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/frame-focusable-content?application=axeAPI",
      "nodes": []
    },
    {
      "id": "frame-title-unique",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag412",
        "TTv5",
        "TT12.d",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure <iframe> and <frame> elements contain a unique title attribute",
      "help": "Frames must have a unique title attribute",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/frame-title-unique?application=axeAPI",
      "nodes": []
    },
    {
      "id": "frame-title",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag412",
        "section508",
        "section508.22.i",
        "TTv5",
        "TT12.d",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure <iframe> and <frame> elements have an accessible name",
      "help": "Frames must have an accessible name",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/frame-title?application=axeAPI",
      "nodes": []
    },
    {
      "id": "html-xml-lang-mismatch",
      "impact": null,
      "tags": [
        "cat.language",
        "wcag2a",
        "wcag311",
        "EN-301-549",
        "EN-9.3.1.1",
        "ACT"
      ],
      "description": "Ensure that HTML elements with both valid lang and xml:lang attributes agree on the base language of the page",
      "help": "HTML elements with lang and xml:lang must have the same base language",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/html-xml-lang-mismatch?application=axeAPI",
      "nodes": []
    },
    {
      "id": "input-button-name",
      "impact": null,
      "tags": [
        "cat.name-role-value",
        "wcag2a",
        "wcag412",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT5.c",
        "EN-301-549",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure input buttons have discernible text",
      "help": "Input buttons must have discernible text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/input-button-name?application=axeAPI",
      "nodes": []
    },
    {
      "id": "input-image-alt",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag111",
        "wcag412",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT7.a",
        "EN-301-549",
        "EN-9.1.1.1",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure <input type=\"image\"> elements have alternative text",
      "help": "Image buttons must have alternative text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/input-image-alt?application=axeAPI",
      "nodes": []
    },
    {
      "id": "marquee",
      "impact": null,
      "tags": [
        "cat.parsing",
        "wcag2a",
        "wcag222",
        "TTv5",
        "TT2.b",
        "EN-301-549",
        "EN-9.2.2.2"
      ],
      "description": "Ensure <marquee> elements are not used",
      "help": "<marquee> elements are deprecated and must not be used",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/marquee?application=axeAPI",
      "nodes": []
    },
    {
      "id": "meta-refresh",
      "impact": null,
      "tags": [
        "cat.time-and-media",
        "wcag2a",
        "wcag221",
        "TTv5",
        "TT8.a",
        "EN-301-549",
        "EN-9.2.2.1"
      ],
      "description": "Ensure <meta http-equiv=\"refresh\"> is not used for delayed refresh",
      "help": "Delayed refresh under 20 hours must not be used",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/meta-refresh?application=axeAPI",
      "nodes": []
    },
    {
      "id": "object-alt",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag111",
        "section508",
        "section508.22.a",
        "EN-301-549",
        "EN-9.1.1.1"
      ],
      "description": "Ensure <object> elements have alternative text",
      "help": "<object> elements must have alternative text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/object-alt?application=axeAPI",
      "nodes": []
    },
    {
      "id": "role-img-alt",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag111",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT7.a",
        "EN-301-549",
        "EN-9.1.1.1",
        "ACT"
      ],
      "description": "Ensure [role=\"img\"] elements have alternative text",
      "help": "[role=\"img\"] elements must have an alternative text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/role-img-alt?application=axeAPI",
      "nodes": []
    },
    {
      "id": "scrollable-region-focusable",
      "impact": null,
      "tags": [
        "cat.keyboard",
        "wcag2a",
        "wcag211",
        "wcag213",
        "TTv5",
        "TT4.a",
        "EN-301-549",
        "EN-9.2.1.1",
        "EN-9.2.1.3"
      ],
      "description": "Ensure elements that have scrollable content are accessible by keyboard",
      "help": "Scrollable region must have keyboard access",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/scrollable-region-focusable?application=axeAPI",
      "nodes": []
    },
    {
      "id": "server-side-image-map",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag211",
        "section508",
        "section508.22.f",
        "TTv5",
        "TT4.a",
        "EN-301-549",
        "EN-9.2.1.1"
      ],
      "description": "Ensure that server-side image maps are not used",
      "help": "Server-side image maps must not be used",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/server-side-image-map?application=axeAPI",
      "nodes": []
    },
    {
      "id": "svg-img-alt",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag111",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT7.a",
        "EN-301-549",
        "EN-9.1.1.1",
        "ACT"
      ],
      "description": "Ensure <svg> elements with an img, graphics-document or graphics-symbol role have an accessible text",
      "help": "<svg> elements with an img role must have an alternative text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/svg-img-alt?application=axeAPI",
      "nodes": []
    },
    {
      "id": "td-headers-attr",
      "impact": null,
      "tags": [
        "cat.tables",
        "wcag2a",
        "wcag131",
        "section508",
        "section508.22.g",
        "TTv5",
        "TT14.b",
        "EN-301-549",
        "EN-9.1.3.1"
      ],
      "description": "Ensure that each cell in a table that uses the headers attribute refers only to other cells in that table",
      "help": "Table cells that use the headers attribute must only refer to cells in the same table",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/td-headers-attr?application=axeAPI",
      "nodes": []
    },
    {
      "id": "th-has-data-cells",
      "impact": null,
      "tags": [
        "cat.tables",
        "wcag2a",
        "wcag131",
        "section508",
        "section508.22.g",
        "TTv5",
        "TT14.b",
        "EN-301-549",
        "EN-9.1.3.1"
      ],
      "description": "Ensure that <th> elements and elements with role=columnheader/rowheader have data cells they describe",
      "help": "Table headers in a data table must refer to data cells",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/th-has-data-cells?application=axeAPI",
      "nodes": []
    },
    {
      "id": "valid-lang",
      "impact": null,
      "tags": [
        "cat.language",
        "wcag2aa",
        "wcag312",
        "TTv5",
        "TT11.b",
        "EN-301-549",
        "EN-9.3.1.2",
        "ACT"
      ],
      "description": "Ensure lang attributes have valid values",
      "help": "lang attribute must have a valid value",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/valid-lang?application=axeAPI",
      "nodes": []
    },
    {
      "id": "video-caption",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag122",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT17.a",
        "EN-301-549",
        "EN-9.1.2.2"
      ],
      "description": "Ensure <video> elements have captions",
      "help": "<video> elements must have captions",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/video-caption?application=axeAPI",
      "nodes": []
    },
    {
      "id": "no-autoplay-audio",
      "impact": null,
      "tags": [
        "cat.time-and-media",
        "wcag2a",
        "wcag142",
        "TTv5",
        "TT2.a",
        "EN-301-549",
        "EN-9.1.4.2",
        "ACT"
      ],
      "description": "Ensure <video> or <audio> elements do not autoplay audio for more than 3 seconds without a control mechanism to stop or mute the audio",
      "help": "<video> or <audio> elements must not play automatically",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/no-autoplay-audio?application=axeAPI",
      "nodes": []
    }
  ],
  "passes": [
    {
      "id": "aria-allowed-attr",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure an element's role supports its ARIA attributes",
      "help": "Elements must only use supported ARIA attributes",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-allowed-attr?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [
            {
              "id": "aria-allowed-attr",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "ARIA attributes are used correctly for the defined role"
            }
          ],
          "none": [
            {
              "id": "aria-unsupported-attr",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "ARIA attribute is supported"
            }
          ],
          "impact": null,
          "html": "<a class=\"brand\" href=\"#top\" aria-label=\"Civic Thread Alliance home\">",
          "target": [
            ".header-inner > .brand[href$=\"#top\"][aria-label=\"Civic Thread Alliance home\"]"
          ]
        }
      ]
    },
    {
      "id": "aria-conditional-attr",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure ARIA attributes are used as described in the specification of the element's role",
      "help": "ARIA attributes must be used as specified for the element's role",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-conditional-attr?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [
            {
              "id": "aria-conditional-attr",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "ARIA attribute is allowed"
            }
          ],
          "none": [],
          "impact": null,
          "html": "<a class=\"brand\" href=\"#top\" aria-label=\"Civic Thread Alliance home\">",
          "target": [
            ".header-inner > .brand[href$=\"#top\"][aria-label=\"Civic Thread Alliance home\"]"
          ]
        }
      ]
    },
    {
      "id": "aria-deprecated-role",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure elements do not use deprecated roles",
      "help": "Deprecated ARIA roles must not be used",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-deprecated-role?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [],
          "none": [
            {
              "id": "deprecatedrole",
              "data": null,
              "relatedNodes": [],
              "impact": "minor",
              "message": "ARIA role is not deprecated"
            }
          ],
          "impact": null,
          "html": "<div class=\"progress-track\" role=\"progressbar\" aria-label=\"Campaign endorsement goal\" aria-valuemin=\"0\" aria-valuemax=\"100\" aria-valuenow=\"68\">\n                    <span></span>\n                  </div>",
          "target": [
            ".progress-track"
          ]
        }
      ]
    },
    {
      "id": "aria-hidden-body",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag131",
        "wcag412",
        "EN-301-549",
        "EN-9.1.3.1",
        "EN-9.4.1.2"
      ],
      "description": "Ensure aria-hidden=\"true\" is not present on the document body.",
      "help": "aria-hidden=\"true\" must not be present on the document body",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-hidden-body?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "aria-hidden-body",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "No aria-hidden attribute is present on document body"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<body>",
          "target": [
            "body"
          ]
        }
      ]
    },
    {
      "id": "aria-hidden-focus",
      "impact": null,
      "tags": [
        "cat.name-role-value",
        "wcag2a",
        "wcag412",
        "TTv5",
        "TT6.a",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure aria-hidden elements are not focusable nor contain focusable elements",
      "help": "ARIA hidden element must not be focusable or contain focusable elements",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-hidden-focus?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [
            {
              "id": "focusable-modal-open",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "No focusable elements while a modal is open"
            },
            {
              "id": "focusable-disabled",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "No focusable elements contained within element"
            },
            {
              "id": "focusable-not-tabbable",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "No focusable elements contained within element"
            }
          ],
          "none": [],
          "impact": null,
          "html": "<span aria-hidden=\"true\">\u2192</span>",
          "target": [
            "a[href$=\"#campaigns\"] > span[aria-hidden=\"true\"]"
          ]
        }
      ]
    },
    {
      "id": "aria-progressbar-name",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag111",
        "EN-301-549",
        "EN-9.1.1.1"
      ],
      "description": "Ensure every ARIA progressbar node has an accessible name",
      "help": "ARIA progressbar nodes must have an accessible name",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-progressbar-name?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "aria-label",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "aria-label attribute exists and is not empty"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<div class=\"progress-track\" role=\"progressbar\" aria-label=\"Campaign endorsement goal\" aria-valuemin=\"0\" aria-valuemax=\"100\" aria-valuenow=\"68\">\n                    <span></span>\n                  </div>",
          "target": [
            ".progress-track"
          ]
        }
      ]
    },
    {
      "id": "aria-prohibited-attr",
      "impact": "serious",
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure ARIA attributes are not prohibited for an element's role",
      "help": "Elements must only use permitted ARIA attributes",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-prohibited-attr?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [],
          "none": [
            {
              "id": "aria-prohibited-attr",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "ARIA attribute is allowed"
            }
          ],
          "impact": null,
          "html": "<a class=\"brand\" href=\"#top\" aria-label=\"Civic Thread Alliance home\">",
          "target": [
            ".header-inner > .brand[href$=\"#top\"][aria-label=\"Civic Thread Alliance home\"]"
          ]
        }
      ]
    },
    {
      "id": "aria-required-attr",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure elements with ARIA roles have all required ARIA attributes",
      "help": "Required ARIA attributes must be provided",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-required-attr?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "aria-required-attr",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "All required ARIA attributes are present"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<div class=\"progress-track\" role=\"progressbar\" aria-label=\"Campaign endorsement goal\" aria-valuemin=\"0\" aria-valuemax=\"100\" aria-valuenow=\"68\">\n                    <span></span>\n                  </div>",
          "target": [
            ".progress-track"
          ]
        }
      ]
    },
    {
      "id": "aria-roles",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure all elements with a role attribute use a valid value",
      "help": "ARIA roles used must conform to valid values",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-roles?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [],
          "none": [
            {
              "id": "invalidrole",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "ARIA role is valid"
            },
            {
              "id": "abstractrole",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "Abstract roles are not used"
            },
            {
              "id": "unsupportedrole",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "ARIA role is supported"
            }
          ],
          "impact": null,
          "html": "<div class=\"progress-track\" role=\"progressbar\" aria-label=\"Campaign endorsement goal\" aria-valuemin=\"0\" aria-valuemax=\"100\" aria-valuenow=\"68\">\n                    <span></span>\n                  </div>",
          "target": [
            ".progress-track"
          ]
        }
      ]
    },
    {
      "id": "aria-valid-attr-value",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure all ARIA attributes have valid values",
      "help": "ARIA attributes must conform to valid values",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-valid-attr-value?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [
            {
              "id": "aria-valid-attr-value",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "ARIA attribute values are valid"
            },
            {
              "id": "aria-errormessage",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "aria-errormessage exists and references elements visible to screen readers that use a supported aria-errormessage technique"
            },
            {
              "id": "aria-level",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "aria-level values are valid"
            }
          ],
          "none": [],
          "impact": null,
          "html": "<a class=\"brand\" href=\"#top\" aria-label=\"Civic Thread Alliance home\">",
          "target": [
            ".header-inner > .brand[href$=\"#top\"][aria-label=\"Civic Thread Alliance home\"]"
          ]
        }
      ]
    },
    {
      "id": "aria-valid-attr",
      "impact": null,
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure attributes that begin with aria- are valid ARIA attributes",
      "help": "ARIA attributes must conform to valid names",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-valid-attr?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "aria-valid-attr",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "ARIA attribute name is valid"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<a class=\"brand\" href=\"#top\" aria-label=\"Civic Thread Alliance home\">",
          "target": [
            ".header-inner > .brand[href$=\"#top\"][aria-label=\"Civic Thread Alliance home\"]"
          ]
        }
      ]
    },
    {
      "id": "autocomplete-valid",
      "impact": null,
      "tags": [
        "cat.forms",
        "wcag21aa",
        "wcag135",
        "EN-301-549",
        "EN-9.1.3.5",
        "ACT"
      ],
      "description": "Ensure the autocomplete attribute is correct and suitable for the form field",
      "help": "autocomplete attribute must be used correctly",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/autocomplete-valid?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [
            {
              "id": "autocomplete-valid",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "the autocomplete attribute is correctly formatted"
            }
          ],
          "none": [],
          "impact": null,
          "html": "<input id=\"first-name\" name=\"firstName\" type=\"text\" autocomplete=\"given-name\" placeholder=\"Your first name\" required=\"\">",
          "target": [
            "#first-name"
          ]
        }
      ]
    },
    {
      "id": "button-name",
      "impact": null,
      "tags": [
        "cat.name-role-value",
        "wcag2a",
        "wcag412",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT6.a",
        "EN-301-549",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure buttons have discernible text",
      "help": "Buttons must have discernible text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/button-name?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "button-has-visible-text",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "Element has inner text that is visible to screen readers"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<button class=\"button button--outline\" type=\"button\" data-open-dialog=\"brief-dialog\">Read the 2-minute brief</button>",
          "target": [
            ".button--outline.button[data-open-dialog=\"brief-dialog\"]"
          ]
        }
      ]
    },
    {
      "id": "bypass",
      "impact": null,
      "tags": [
        "cat.keyboard",
        "wcag2a",
        "wcag241",
        "section508",
        "section508.22.o",
        "TTv5",
        "TT9.a",
        "EN-301-549",
        "EN-9.2.4.1"
      ],
      "description": "Ensure each page has at least one mechanism for a user to bypass navigation and jump straight to the content",
      "help": "Page must have means to bypass repeated blocks",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/bypass?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "internal-link-present",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "Valid skip link found"
            },
            {
              "id": "header-present",
              "data": null,
              "relatedNodes": [
                {
                  "html": "<h1 id=\"hero-title\">A fairer future is <em>woven together.</em></h1>",
                  "target": [
                    "#hero-title"
                  ]
                },
                {
                  "html": "<h2 id=\"work-title\">We make belonging a public practice.</h2>",
                  "target": [
                    "#work-title"
                  ]
                },
                {
                  "html": "<h3>Belonging by design</h3>",
                  "target": [
                    ".pillar:nth-child(1) > h3"
                  ]
                },
                {
                  "html": "<h3>Power with, not for</h3>",
                  "target": [
                    ".pillar:nth-child(2) > h3"
                  ]
                },
                {
                  "html": "<h3>Policy people can feel</h3>",
                  "target": [
                    ".pillar:nth-child(3) > h3"
                  ]
                },
                {
                  "html": "<h2 id=\"campaigns-title\">Three campaigns. One shared agenda.</h2>",
                  "target": [
                    "#campaigns-title"
                  ]
                },
                {
                  "html": "<h3>Home Is Here</h3>",
                  "target": [
                    ".campaign-feature-content > h3"
                  ]
                },
                {
                  "html": "<h3>Safe Routes for All</h3>",
                  "target": [
                    ".campaign-card:nth-child(1) > h3"
                  ]
                },
                {
                  "html": "<h3>Culture Is Common Ground</h3>",
                  "target": [
                    ".campaign-card:nth-child(2) > h3"
                  ]
                },
                {
                  "html": "<h3 id=\"action-title\">Your 20-minute action plan</h3>",
                  "target": [
                    "#action-title"
                  ]
                },
                {
                  "html": "<h4><label for=\"action-brief\">Know the ask</label></h4>",
                  "target": [
                    ".action-item:nth-child(1) > div > h4"
                  ]
                },
                {
                  "html": "<h4><label for=\"action-call\">Make the one-minute call</label></h4>",
                  "target": [
                    ".action-item:nth-child(2) > div > h4"
                  ]
                },
                {
                  "html": "<h4><label for=\"action-attend\">Show up with neighbors</label></h4>",
                  "target": [
                    ".action-item:nth-child(3) > div > h4"
                  ]
                },
                {
                  "html": "<h4><label for=\"action-share\">Grow the circle</label></h4>",
                  "target": [
                    ".action-item:nth-child(4) > div > h4"
                  ]
                },
                {
                  "html": "<h2 id=\"stories-title\">The people are not the footnotes. They are the story.</h2>",
                  "target": [
                    "#stories-title"
                  ]
                },
                {
                  "html": "<h3>The night-shift riders who redrew Route 8</h3>",
                  "target": [
                    ".story-main-content > h3"
                  ]
                },
                {
                  "html": "<h3>A welcome in twelve languages</h3>",
                  "target": [
                    ".story-mini:nth-child(1) > .story-mini-content > h3"
                  ]
                },
                {
                  "html": "<h3>A vacant lot becomes a shared future</h3>",
                  "target": [
                    ".story-mini:nth-child(2) > .story-mini-content > h3"
                  ]
                },
                {
                  "html": "<h3 class=\"testimonial-heading\">In their own words</h3>",
                  "target": [
                    ".testimonial-heading"
                  ]
                },
                {
                  "html": "<h2 id=\"policy-title\">Good policy is only the beginning.</h2>",
                  "target": [
                    "#policy-title"
                  ]
                },
                {
                  "html": "<h3>What changed because people showed up</h3>",
                  "target": [
                    ".policy-timeline > h3"
                  ]
                },
                {
                  "html": "<h4>Language Access Ordinance</h4>",
                  "target": [
                    ".timeline-item:nth-child(2) > div > h4"
                  ]
                },
                {
                  "html": "<h4>People\u2019s Budget Pilot</h4>",
                  "target": [
                    ".timeline-item:nth-child(3) > div > h4"
                  ]
                },
                {
                  "html": "<h4>Safe Streets Standard</h4>",
                  "target": [
                    ".timeline-item:nth-child(4) > div > h4"
                  ]
                },
                {
                  "html": "<h2 id=\"news-title\">Notes from the movement.</h2>",
                  "target": [
                    "#news-title"
                  ]
                },
                {
                  "html": "<h3>What 317 listening sessions taught us about belonging</h3>",
                  "target": [
                    ".news-card--lead > .news-card-content > h3"
                  ]
                },
                {
                  "html": "<h3>Your first public comment, without the jargon</h3>",
                  "target": [
                    ".news-card:nth-child(2) > .news-card-content > h3"
                  ]
                },
                {
                  "html": "<h3>Coalition building without leaving small groups behind</h3>",
                  "target": [
                    ".news-card:nth-child(3) > .news-card-content > h3"
                  ]
                },
                {
                  "html": "<h3 id=\"events-title\">Come into the room</h3>",
                  "target": [
                    "#events-title"
                  ]
                },
                {
                  "html": "<h4>New Member Welcome</h4>",
                  "target": [
                    ".event-item:nth-child(1) > .event-details > h4"
                  ]
                },
                {
                  "html": "<h4>Tenant Organizing Basics</h4>",
                  "target": [
                    ".event-item:nth-child(2) > .event-details > h4"
                  ]
                },
                {
                  "html": "<h4>Neighborhood Story Circle</h4>",
                  "target": [
                    ".event-item:nth-child(3) > .event-details > h4"
                  ]
                },
                {
                  "html": "<h2 id=\"about-title\">A coalition, not a podium.</h2>",
                  "target": [
                    "#about-title"
                  ]
                },
                {
                  "html": "<h3>Resident-led agendas</h3>",
                  "target": [
                    ".principle:nth-child(1) > h3"
                  ]
                },
                {
                  "html": "<h3>Transparent resources</h3>",
                  "target": [
                    ".principle:nth-child(2) > h3"
                  ]
                },
                {
                  "html": "<h3>Accessible by default</h3>",
                  "target": [
                    ".principle:nth-child(3) > h3"
                  ]
                },
                {
                  "html": "<h3>Joy is infrastructure</h3>",
                  "target": [
                    ".principle:nth-child(4) > h3"
                  ]
                },
                {
                  "html": "<h2 id=\"faq-title\">Answers, without the fine-print feeling.</h2>",
                  "target": [
                    "#faq-title"
                  ]
                },
                {
                  "html": "<h2 id=\"join-title\">Your corner of the movement is waiting.</h2>",
                  "target": [
                    "#join-title"
                  ]
                },
                {
                  "html": "<h3>Join Civic Thread</h3>",
                  "target": [
                    "#join-form > h3"
                  ]
                },
                {
                  "html": "<h2>Explore</h2>",
                  "target": [
                    ".footer-column:nth-child(2) > h2"
                  ]
                },
                {
                  "html": "<h2>Take part</h2>",
                  "target": [
                    ".footer-column:nth-child(3) > h2"
                  ]
                },
                {
                  "html": "<h2>Visit or write</h2>",
                  "target": [
                    ".footer-column:nth-child(4) > h2"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Page has a heading"
            },
            {
              "id": "landmark",
              "data": null,
              "relatedNodes": [
                {
                  "html": "<main id=\"main-content\">",
                  "target": [
                    "#main-content"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Page has a landmark region"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<html lang=\"en\" class=\"js\">",
          "target": [
            "html"
          ]
        }
      ]
    },
    {
      "id": "color-contrast",
      "impact": "serious",
      "tags": [
        "cat.color",
        "wcag2aa",
        "wcag143",
        "TTv5",
        "TT13.c",
        "EN-301-549",
        "EN-9.1.4.3",
        "ACT"
      ],
      "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
      "help": "Elements must meet minimum color contrast ratio thresholds",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/color-contrast?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#f3bf57",
                "bgColor": "#0c2925",
                "contrastRatio": 9.12,
                "fontSize": "9.6pt (12.8px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [],
              "impact": "serious",
              "message": "Element has sufficient color contrast of 9.12"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<span class=\"announcement-label\">Campaign update</span>",
          "target": [
            ".announcement-label"
          ]
        }
      ]
    },
    {
      "id": "document-title",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag242",
        "TTv5",
        "TT12.a",
        "EN-301-549",
        "EN-9.2.4.2",
        "ACT"
      ],
      "description": "Ensure each HTML document contains a non-empty <title> element",
      "help": "Documents must have <title> element to aid in navigation",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/document-title?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "doc-has-title",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "Document has a non-empty <title> element"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<html lang=\"en\" class=\"js\">",
          "target": [
            "html"
          ]
        }
      ]
    },
    {
      "id": "duplicate-id-aria",
      "impact": null,
      "tags": [
        "cat.parsing",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure every id attribute value used in ARIA and in labels is unique",
      "help": "IDs used in ARIA and labels must be unique",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/duplicate-id-aria?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "duplicate-id-aria",
              "data": "primary-navigation",
              "relatedNodes": [],
              "impact": "critical",
              "message": "Document has no elements referenced with ARIA or labels that share the same id attribute"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<nav class=\"primary-nav\" id=\"primary-navigation\" aria-label=\"Primary navigation\">",
          "target": [
            "#primary-navigation"
          ]
        }
      ]
    },
    {
      "id": "form-field-multiple-labels",
      "impact": null,
      "tags": [
        "cat.forms",
        "wcag2a",
        "wcag332",
        "TTv5",
        "TT5.c",
        "EN-301-549",
        "EN-9.3.3.2"
      ],
      "description": "Ensure form field does not have multiple label elements",
      "help": "Form field must not have multiple label elements",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/form-field-multiple-labels?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [],
          "none": [
            {
              "id": "multiple-label",
              "data": null,
              "relatedNodes": [
                {
                  "html": "<label for=\"action-brief\">Know the ask</label>",
                  "target": [
                    "label[for=\"action-brief\"]"
                  ]
                }
              ],
              "impact": "moderate",
              "message": "Form field does not have multiple label elements"
            }
          ],
          "impact": null,
          "html": "<input class=\"action-check\" type=\"checkbox\" id=\"action-brief\" data-action-id=\"brief\" aria-label=\"Mark Know the ask complete\">",
          "target": [
            "#action-brief"
          ]
        }
      ]
    },
    {
      "id": "html-has-lang",
      "impact": null,
      "tags": [
        "cat.language",
        "wcag2a",
        "wcag311",
        "TTv5",
        "TT11.a",
        "EN-301-549",
        "EN-9.3.1.1",
        "ACT"
      ],
      "description": "Ensure every HTML document has a lang attribute",
      "help": "<html> element must have a lang attribute",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/html-has-lang?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "has-lang",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "The <html> element has a lang attribute"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<html lang=\"en\" class=\"js\">",
          "target": [
            "html"
          ]
        }
      ]
    },
    {
      "id": "html-lang-valid",
      "impact": null,
      "tags": [
        "cat.language",
        "wcag2a",
        "wcag311",
        "TTv5",
        "TT11.a",
        "EN-301-549",
        "EN-9.3.1.1",
        "ACT"
      ],
      "description": "Ensure the lang attribute of the <html> element has a valid value",
      "help": "<html> element must have a valid value for the lang attribute",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/html-lang-valid?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [],
          "none": [
            {
              "id": "valid-lang",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "Value of lang attribute is included in the list of valid languages"
            }
          ],
          "impact": null,
          "html": "<html lang=\"en\" class=\"js\">",
          "target": [
            "html"
          ]
        }
      ]
    },
    {
      "id": "image-alt",
      "impact": null,
      "tags": [
        "cat.text-alternatives",
        "wcag2a",
        "wcag111",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT7.a",
        "TT7.b",
        "EN-301-549",
        "EN-9.1.1.1",
        "ACT"
      ],
      "description": "Ensure <img> elements have alternative text or a role of none or presentation",
      "help": "Images must have alternative text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/image-alt?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "has-alt",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "Element has an alt attribute"
            }
          ],
          "all": [],
          "none": [
            {
              "id": "alt-space-value",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "Element has a valid alt attribute value"
            }
          ],
          "impact": null,
          "html": "<img class=\"brand-logo\" src=\"https://placehold.co/56x56/173b35/f7f3eb?text=CT&amp;font=montserrat\" width=\"48\" height=\"48\" alt=\"Civic Thread Alliance CT logo\">",
          "target": [
            "img[alt=\"Civic Thread Alliance CT logo\"]"
          ]
        }
      ]
    },
    {
      "id": "label",
      "impact": null,
      "tags": [
        "cat.forms",
        "wcag2a",
        "wcag412",
        "section508",
        "section508.22.n",
        "TTv5",
        "TT5.c",
        "EN-301-549",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure every form element has a label",
      "help": "Form elements must have labels",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/label?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "explicit-label",
              "data": null,
              "relatedNodes": [
                {
                  "html": "<label for=\"action-brief\">Know the ask</label>",
                  "target": [
                    "label[for=\"action-brief\"]"
                  ]
                }
              ],
              "impact": "critical",
              "message": "Element has an explicit <label>"
            },
            {
              "id": "aria-label",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "aria-label attribute exists and is not empty"
            }
          ],
          "all": [],
          "none": [
            {
              "id": "hidden-explicit-label",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "Form element has a visible explicit <label>"
            }
          ],
          "impact": null,
          "html": "<input class=\"action-check\" type=\"checkbox\" id=\"action-brief\" data-action-id=\"brief\" aria-label=\"Mark Know the ask complete\">",
          "target": [
            "#action-brief"
          ]
        }
      ]
    },
    {
      "id": "link-name",
      "impact": null,
      "tags": [
        "cat.name-role-value",
        "wcag2a",
        "wcag244",
        "wcag412",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT6.a",
        "EN-301-549",
        "EN-9.2.4.4",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure links have discernible text",
      "help": "Links must have discernible text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/link-name?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "has-visible-text",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "Element has text that is visible to screen readers"
            }
          ],
          "all": [],
          "none": [
            {
              "id": "focusable-no-name",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "Element is not in tab order or has accessible text"
            }
          ],
          "impact": null,
          "html": "<a class=\"skip-link\" href=\"#main-content\">Skip to main content</a>",
          "target": [
            ".skip-link"
          ]
        }
      ]
    },
    {
      "id": "list",
      "impact": null,
      "tags": [
        "cat.structure",
        "wcag2a",
        "wcag131",
        "EN-301-549",
        "EN-9.1.3.1"
      ],
      "description": "Ensure that lists are structured correctly",
      "help": "<ul> and <ol> must only directly contain <li>, <script> or <template> elements",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/list?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [],
          "none": [
            {
              "id": "only-listitems",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "List element only has direct children that are allowed inside <li> elements"
            }
          ],
          "impact": null,
          "html": "<ul class=\"partner-list\" aria-label=\"Partner organizations\">\n            <li>Northstar Tenants Union</li>\n            <li>Mesa Cultural Arts</li>\n            <li>Access Transit Coalition</li>\n            <li>Riverbend Mutual Aid</li>\n            <li>Commons Library Network</li>\n          </ul>",
          "target": [
            ".partner-list"
          ]
        }
      ]
    },
    {
      "id": "listitem",
      "impact": null,
      "tags": [
        "cat.structure",
        "wcag2a",
        "wcag131",
        "EN-301-549",
        "EN-9.1.3.1"
      ],
      "description": "Ensure <li> elements are used semantically",
      "help": "<li> elements must be contained in a <ul> or <ol>",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/listitem?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "listitem",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "List item has a <ul>, <ol> or role=\"list\" parent element"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<li>Northstar Tenants Union</li>",
          "target": [
            ".partner-list > li:nth-child(1)"
          ]
        }
      ]
    },
    {
      "id": "meta-viewport",
      "impact": null,
      "tags": [
        "cat.sensory-and-visual-cues",
        "wcag2aa",
        "wcag144",
        "EN-301-549",
        "EN-9.1.4.4",
        "ACT"
      ],
      "description": "Ensure <meta name=\"viewport\"> does not disable text scaling and zooming",
      "help": "Zooming and scaling must not be disabled",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/meta-viewport?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "meta-viewport",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "<meta> tag does not disable zooming on mobile devices"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">",
          "target": [
            "meta[name=\"viewport\"]"
          ]
        }
      ]
    },
    {
      "id": "nested-interactive",
      "impact": null,
      "tags": [
        "cat.keyboard",
        "wcag2a",
        "wcag412",
        "TTv5",
        "TT6.a",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure interactive controls are not nested as they are not always announced by screen readers or can cause focus problems for assistive technologies",
      "help": "Interactive controls must not be nested",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/nested-interactive?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "no-focusable-content",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "Element does not have focusable descendants"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<img class=\"brand-logo\" src=\"https://placehold.co/56x56/173b35/f7f3eb?text=CT&amp;font=montserrat\" width=\"48\" height=\"48\" alt=\"Civic Thread Alliance CT logo\">",
          "target": [
            "img[alt=\"Civic Thread Alliance CT logo\"]"
          ]
        }
      ]
    },
    {
      "id": "select-name",
      "impact": null,
      "tags": [
        "cat.forms",
        "wcag2a",
        "wcag412",
        "section508",
        "section508.22.n",
        "TTv5",
        "TT5.c",
        "EN-301-549",
        "EN-9.4.1.2",
        "ACT"
      ],
      "description": "Ensure select element has an accessible name",
      "help": "Select element must have an accessible name",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/select-name?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "explicit-label",
              "data": null,
              "relatedNodes": [
                {
                  "html": "<label for=\"interest\">I am most interested in</label>",
                  "target": [
                    "label[for=\"interest\"]"
                  ]
                }
              ],
              "impact": "critical",
              "message": "Element has an explicit <label>"
            }
          ],
          "all": [],
          "none": [
            {
              "id": "hidden-explicit-label",
              "data": null,
              "relatedNodes": [],
              "impact": "critical",
              "message": "Form element has a visible explicit <label>"
            }
          ],
          "impact": null,
          "html": "<select id=\"interest\" name=\"interest\" required=\"\">",
          "target": [
            "#interest"
          ]
        }
      ]
    },
    {
      "id": "summary-name",
      "impact": null,
      "tags": [
        "cat.name-role-value",
        "wcag2a",
        "wcag412",
        "section508",
        "section508.22.a",
        "TTv5",
        "TT6.a",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure summary elements have discernible text",
      "help": "Summary elements must have discernible text",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/summary-name?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "has-visible-text",
              "data": null,
              "relatedNodes": [],
              "impact": "serious",
              "message": "Element has text that is visible to screen readers"
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<summary>How we measure impact</summary>",
          "target": [
            ".methodology > summary"
          ]
        }
      ]
    },
    {
      "id": "target-size",
      "impact": null,
      "tags": [
        "cat.sensory-and-visual-cues",
        "wcag22aa",
        "wcag258"
      ],
      "description": "Ensure touch targets have sufficient size and space",
      "help": "All touch targets must be 24px large, or leave sufficient space",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/target-size?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "target-size",
              "data": {
                "minSize": 24,
                "width": 198.8,
                "height": 50.4
              },
              "relatedNodes": [],
              "impact": "serious",
              "message": "Control has sufficient size (198.8px by 50.4px, should be at least 24px by 24px)"
            },
            {
              "id": "target-offset",
              "data": {
                "closestOffset": 24,
                "minOffset": 24
              },
              "relatedNodes": [],
              "impact": "serious",
              "message": "Target has sufficient space from its closest neighbors. Safe clickable space has a diameter of 24px which is at least 24px."
            }
          ],
          "all": [],
          "none": [],
          "impact": null,
          "html": "<a class=\"skip-link\" href=\"#main-content\">Skip to main content</a>",
          "target": [
            ".skip-link"
          ]
        }
      ]
    }
  ],
  "incomplete": [
    {
      "id": "aria-prohibited-attr",
      "impact": "serious",
      "tags": [
        "cat.aria",
        "wcag2a",
        "wcag412",
        "EN-301-549",
        "EN-9.4.1.2"
      ],
      "description": "Ensure ARIA attributes are not prohibited for an element's role",
      "help": "Elements must only use permitted ARIA attributes",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/aria-prohibited-attr?application=axeAPI",
      "nodes": [
        {
          "any": [],
          "all": [],
          "none": [
            {
              "id": "aria-prohibited-attr",
              "data": {
                "role": null,
                "nodeName": "div",
                "messageKey": "noRoleSingular",
                "prohibited": [
                  "aria-label"
                ]
              },
              "relatedNodes": [],
              "impact": "serious",
              "message": "aria-label attribute is not well supported on a div with no valid role attribute."
            }
          ],
          "impact": "serious",
          "html": "<div class=\"impact-strip\" aria-label=\"Organization impact at a glance\">",
          "target": [
            ".impact-strip"
          ],
          "failureSummary": "Fix all of the following:\n  aria-label attribute is not well supported on a div with no valid role attribute."
        }
      ]
    },
    {
      "id": "color-contrast",
      "impact": "serious",
      "tags": [
        "cat.color",
        "wcag2aa",
        "wcag143",
        "TTv5",
        "TT13.c",
        "EN-301-549",
        "EN-9.1.4.3",
        "ACT"
      ],
      "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
      "help": "Elements must meet minimum color contrast ratio thresholds",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/color-contrast?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "messageKey": "nonBmp"
              },
              "relatedNodes": [],
              "impact": "serious",
              "message": "Element content contains only non-text characters"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span aria-hidden=\"true\">\u2192</span>",
          "target": [
            "a[href$=\"#campaigns\"] > span[aria-hidden=\"true\"]"
          ],
          "failureSummary": "Fix any of the following:\n  Element content contains only non-text characters"
        }
      ]
    },
    {
      "id": "link-in-text-block",
      "impact": "serious",
      "tags": [
        "cat.color",
        "wcag2a",
        "wcag141",
        "TTv5",
        "TT13.a",
        "EN-301-549",
        "EN-9.1.4.1"
      ],
      "description": "Ensure links are distinguished from surrounding text in a way that does not rely on color",
      "help": "Links must be distinguishable without relying on color",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/link-in-text-block?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "link-in-text-block",
              "data": {
                "messageKey": "bgOverlap"
              },
              "relatedNodes": [
                {
                  "html": "<div class=\"footer-brand\">",
                  "target": [
                    ".footer-brand"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element's contrast ratio could not be determined because of element overlap"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<a class=\"brand\" href=\"#top\" aria-label=\"Civic Thread Alliance home\">",
          "target": [
            ".footer-brand > .brand[href$=\"#top\"][aria-label=\"Civic Thread Alliance home\"]"
          ],
          "failureSummary": "Fix any of the following:\n  Element's contrast ratio could not be determined because of element overlap"
        }
      ]
    }
  ],
  "violations": [
    {
      "id": "color-contrast",
      "impact": "serious",
      "tags": [
        "cat.color",
        "wcag2aa",
        "wcag143",
        "TTv5",
        "TT13.c",
        "EN-301-549",
        "EN-9.1.4.3",
        "ACT"
      ],
      "description": "Ensure the contrast between foreground and background colors meets WCAG 2 AA minimum contrast ratio thresholds",
      "help": "Elements must meet minimum color contrast ratio thresholds",
      "helpUrl": "https://dequeuniversity.com/rules/axe/4.10/color-contrast?application=axeAPI",
      "nodes": [
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#65736d",
                "bgColor": "#f7f3eb",
                "contrastRatio": 4.48,
                "fontSize": "7.4pt (9.92px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<header class=\"site-header\" id=\"site-header\">",
                  "target": [
                    "#site-header"
                  ]
                },
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 7.4pt (9.92px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"brand-tagline\">Many voices. One shared future.</span>",
          "target": [
            ".header-inner > .brand[href$=\"#top\"][aria-label=\"Civic Thread Alliance home\"] > .brand-copy > .brand-tagline"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 7.4pt (9.92px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#798987",
                "bgColor": "#0c2925",
                "contrastRatio": 4.22,
                "fontSize": "7.9pt (10.56px)",
                "fontWeight": "normal",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<footer class=\"site-footer\">",
                  "target": [
                    "footer"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.22 (foreground color: #798987, background color: #0c2925, font size: 7.9pt (10.56px), font weight: normal). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<p>\u00a9 <span data-year=\"\">2026</span> Civic Thread Alliance. All rights reserved. Nonpartisan 501(c)(3) \u00b7 EIN 47-2189056.</p>",
          "target": [
            ".footer-bottom > p"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.22 (foreground color: #798987, background color: #0c2925, font size: 7.9pt (10.56px), font weight: normal). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#798987",
                "bgColor": "#0c2925",
                "contrastRatio": 4.22,
                "fontSize": "7.9pt (10.56px)",
                "fontWeight": "normal",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<footer class=\"site-footer\">",
                  "target": [
                    "footer"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.22 (foreground color: #798987, background color: #0c2925, font size: 7.9pt (10.56px), font weight: normal). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span data-year=\"\">2026</span>",
          "target": [
            "p > span[data-year=\"\"]"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.22 (foreground color: #798987, background color: #0c2925, font size: 7.9pt (10.56px), font weight: normal). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#e97556",
                "bgColor": "#fffdf8",
                "contrastRatio": 2.89,
                "fontSize": "8.2pt (10.88px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<article class=\"campaign-feature reveal is-visible\">",
                  "target": [
                    ".campaign-feature"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"tag\">Housing justice \u00b7 Lead campaign</span>",
          "target": [
            ".campaign-feature-content > .tag"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#869996",
                "bgColor": "#173b35",
                "contrastRatio": 4.09,
                "fontSize": "7.8pt (10.4px)",
                "fontWeight": "normal",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<aside class=\"action-desk reveal is-visible\" id=\"action-desk\" aria-labelledby=\"action-title\">",
                  "target": [
                    "#action-desk"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.09 (foreground color: #869996, background color: #173b35, font size: 7.8pt (10.4px), font weight: normal). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"action-privacy\">Your checklist stays in this browser. We never see or sell your action data.</span>",
          "target": [
            ".action-privacy"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.09 (foreground color: #869996, background color: #173b35, font size: 7.8pt (10.4px), font weight: normal). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#e97556",
                "bgColor": "#fffdf8",
                "contrastRatio": 2.89,
                "fontSize": "8.2pt (10.88px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<article class=\"campaign-card reveal is-visible\">",
                  "target": [
                    ".campaign-card.is-visible:nth-child(1)"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"tag\">Mobility \u00b7 Accessibility</span>",
          "target": [
            ".campaign-card.is-visible:nth-child(1) > .tag"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#e97556",
                "bgColor": "#fffdf8",
                "contrastRatio": 2.89,
                "fontSize": "8.2pt (10.88px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<article class=\"campaign-card reveal is-visible\" style=\"--delay: 80ms\">",
                  "target": [
                    ".campaign-card.is-visible:nth-child(2)"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"tag\">Culture \u00b7 Public investment</span>",
          "target": [
            ".campaign-card.is-visible:nth-child(2) > .tag"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#e97556",
                "bgColor": "#fffdf8",
                "contrastRatio": 2.89,
                "fontSize": "8.2pt (10.88px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<article class=\"story-main reveal is-visible\">",
                  "target": [
                    ".story-main"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"tag\">Transit justice \u00b7 Eastside</span>",
          "target": [
            ".story-main-content > .tag"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#e97556",
                "bgColor": "#fffdf8",
                "contrastRatio": 2.89,
                "fontSize": "8.2pt (10.88px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<article class=\"story-mini reveal is-visible\" style=\"--delay: 80ms\">",
                  "target": [
                    ".story-mini.is-visible"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"tag\">Language access</span>",
          "target": [
            ".story-mini.is-visible > .story-mini-content > .tag"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#e97556",
                "bgColor": "#fffdf8",
                "contrastRatio": 2.89,
                "fontSize": "8.2pt (10.88px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<article class=\"story-mini reveal is-visible\" style=\"--delay: 80ms\">",
                  "target": [
                    ".story-mini.is-visible:nth-child(1)"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"tag\">Language access</span>",
          "target": [
            ".story-mini.is-visible:nth-child(1) > .story-mini-content > .tag"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#e97556",
                "bgColor": "#fffdf8",
                "contrastRatio": 2.89,
                "fontSize": "8.2pt (10.88px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<article class=\"story-mini reveal is-visible\" style=\"--delay: 140ms\">",
                  "target": [
                    ".story-mini.is-visible:nth-child(2)"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"tag\">Community ownership</span>",
          "target": [
            ".story-mini.is-visible:nth-child(2) > .story-mini-content > .tag"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#65736d",
                "bgColor": "#f7f3eb",
                "contrastRatio": 4.48,
                "fontSize": "8.4pt (11.2px)",
                "fontWeight": "normal",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 8.4pt (11.2px), font weight: normal). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span>Tenant leader \u00b7 Southside</span>",
          "target": [
            ".testimonial.is-visible:nth-child(1) > .testimonial-person > div > span"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 8.4pt (11.2px), font weight: normal). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#65736d",
                "bgColor": "#f7f3eb",
                "contrastRatio": 4.48,
                "fontSize": "8.4pt (11.2px)",
                "fontWeight": "normal",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 8.4pt (11.2px), font weight: normal). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span>Director \u00b7 Mesa Cultural Arts</span>",
          "target": [
            ".testimonial.is-visible:nth-child(2) > .testimonial-person > div > span"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 8.4pt (11.2px), font weight: normal). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#65736d",
                "bgColor": "#f7f3eb",
                "contrastRatio": 4.48,
                "fontSize": "8.4pt (11.2px)",
                "fontWeight": "normal",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 8.4pt (11.2px), font weight: normal). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span>New member \u00b7 Riverbend</span>",
          "target": [
            ".testimonial.is-visible:nth-child(3) > .testimonial-person > div > span"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 8.4pt (11.2px), font weight: normal). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#65736d",
                "bgColor": "#f7f3eb",
                "contrastRatio": 4.48,
                "fontSize": "12.0pt (16px)",
                "fontWeight": "normal",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 12.0pt (16px), font weight: normal). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<p>\n            Practical lessons, campaign reporting, and honest reflections from our organizers and partners. No victory laps without the messy middle.\n          </p>",
          "target": [
            ".news-header > p"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 12.0pt (16px), font weight: normal). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#e97556",
                "bgColor": "#fffdf8",
                "contrastRatio": 2.89,
                "fontSize": "8.2pt (10.88px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<article class=\"campaign-card reveal is-visible\">",
                  "target": [
                    ".campaign-card:nth-child(1)"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"tag\">Mobility \u00b7 Accessibility</span>",
          "target": [
            ".campaign-card:nth-child(1) > .tag"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#e97556",
                "bgColor": "#fffdf8",
                "contrastRatio": 2.89,
                "fontSize": "8.2pt (10.88px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<article class=\"campaign-card reveal is-visible\" style=\"--delay: 80ms\">",
                  "target": [
                    ".campaign-card:nth-child(2)"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"tag\">Culture \u00b7 Public investment</span>",
          "target": [
            ".campaign-card:nth-child(2) > .tag"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#e97556",
                "bgColor": "#fffdf8",
                "contrastRatio": 2.89,
                "fontSize": "8.2pt (10.88px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<article class=\"story-mini reveal is-visible\" style=\"--delay: 80ms\">",
                  "target": [
                    ".story-mini:nth-child(1)"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"tag\">Language access</span>",
          "target": [
            ".story-mini:nth-child(1) > .story-mini-content > .tag"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#e97556",
                "bgColor": "#fffdf8",
                "contrastRatio": 2.89,
                "fontSize": "8.2pt (10.88px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<article class=\"story-mini reveal is-visible\" style=\"--delay: 140ms\">",
                  "target": [
                    ".story-mini:nth-child(2)"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span class=\"tag\">Community ownership</span>",
          "target": [
            ".story-mini:nth-child(2) > .story-mini-content > .tag"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 8.2pt (10.88px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#65736d",
                "bgColor": "#f7f3eb",
                "contrastRatio": 4.48,
                "fontSize": "8.4pt (11.2px)",
                "fontWeight": "normal",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 8.4pt (11.2px), font weight: normal). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span>Tenant leader \u00b7 Southside</span>",
          "target": [
            ".testimonial:nth-child(1) > .testimonial-person > div > span"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 8.4pt (11.2px), font weight: normal). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#65736d",
                "bgColor": "#f7f3eb",
                "contrastRatio": 4.48,
                "fontSize": "8.4pt (11.2px)",
                "fontWeight": "normal",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 8.4pt (11.2px), font weight: normal). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span>Director \u00b7 Mesa Cultural Arts</span>",
          "target": [
            ".testimonial:nth-child(2) > .testimonial-person > div > span"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 8.4pt (11.2px), font weight: normal). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#65736d",
                "bgColor": "#f7f3eb",
                "contrastRatio": 4.48,
                "fontSize": "8.4pt (11.2px)",
                "fontWeight": "normal",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 8.4pt (11.2px), font weight: normal). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span>New member \u00b7 Riverbend</span>",
          "target": [
            ".testimonial:nth-child(3) > .testimonial-person > div > span"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 8.4pt (11.2px), font weight: normal). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#e97556",
                "bgColor": "#fffdf8",
                "contrastRatio": 2.89,
                "fontSize": "7.9pt (10.56px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<article class=\"news-card news-card--lead reveal is-visible\">",
                  "target": [
                    ".news-card--lead"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 7.9pt (10.56px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span>Field note</span>",
          "target": [
            ".news-card--lead > .news-card-content > .news-meta > span:nth-child(1)"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 7.9pt (10.56px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#e97556",
                "bgColor": "#fffdf8",
                "contrastRatio": 2.89,
                "fontSize": "7.9pt (10.56px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<article class=\"news-card reveal is-visible\">",
                  "target": [
                    ".news-card:nth-child(2)"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 7.9pt (10.56px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span>Organizing guide</span>",
          "target": [
            ".news-card:nth-child(2) > .news-card-content > .news-meta > span"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 7.9pt (10.56px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#e97556",
                "bgColor": "#fffdf8",
                "contrastRatio": 2.89,
                "fontSize": "7.9pt (10.56px)",
                "fontWeight": "bold",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<article class=\"news-card reveal is-visible\" style=\"--delay: 80ms\">",
                  "target": [
                    ".news-card:nth-child(3)"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 7.9pt (10.56px), font weight: bold). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<span>Coalition practice</span>",
          "target": [
            ".news-card:nth-child(3) > .news-card-content > .news-meta > span"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 2.89 (foreground color: #e97556, background color: #fffdf8, font size: 7.9pt (10.56px), font weight: bold). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#65736d",
                "bgColor": "#f7f3eb",
                "contrastRatio": 4.48,
                "fontSize": "12.0pt (16px)",
                "fontWeight": "normal",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 12.0pt (16px), font weight: normal). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<p>\n            Still wondering whether this is the right place for you? Write to <a href=\"mailto:hello@civicthreadalliance.org\">hello@civicthreadalliance.org</a> and a real member of our team will respond.\n          </p>",
          "target": [
            ".faq-intro > p"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 12.0pt (16px), font weight: normal). Expected contrast ratio of 4.5:1"
        },
        {
          "any": [
            {
              "id": "color-contrast",
              "data": {
                "fgColor": "#65736d",
                "bgColor": "#f7f3eb",
                "contrastRatio": 4.48,
                "fontSize": "12.0pt (16px)",
                "fontWeight": "normal",
                "messageKey": null,
                "expectedContrastRatio": "4.5:1",
                "shadowColor": null
              },
              "relatedNodes": [
                {
                  "html": "<body>",
                  "target": [
                    "body"
                  ]
                }
              ],
              "impact": "serious",
              "message": "Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 12.0pt (16px), font weight: normal). Expected contrast ratio of 4.5:1"
            }
          ],
          "all": [],
          "none": [],
          "impact": "serious",
          "html": "<a href=\"mailto:hello@civicthreadalliance.org\">hello@civicthreadalliance.org</a>",
          "target": [
            ".faq-intro > p > a"
          ],
          "failureSummary": "Fix any of the following:\n  Element has insufficient color contrast of 4.48 (foreground color: #65736d, background color: #f7f3eb, font size: 12.0pt (16px), font weight: normal). Expected contrast ratio of 4.5:1"
        }
      ]
    }
  ],
  "coverage": {
    "contract": "main-document-vertical-scroll",
    "complete": true,
    "positions": [
      {
        "y": 0,
        "height": 11061
      },
      {
        "y": 576,
        "height": 11061
      },
      {
        "y": 1152,
        "height": 11061
      },
      {
        "y": 1728,
        "height": 11061
      },
      {
        "y": 2304,
        "height": 11061
      },
      {
        "y": 2880,
        "height": 11061
      },
      {
        "y": 3456,
        "height": 11061
      },
      {
        "y": 4032,
        "height": 11061
      },
      {
        "y": 4608,
        "height": 11061
      },
      {
        "y": 5184,
        "height": 11061
      },
      {
        "y": 5760,
        "height": 11061
      },
      {
        "y": 6336,
        "height": 11061
      },
      {
        "y": 6912,
        "height": 11061
      },
      {
        "y": 7488,
        "height": 11061
      },
      {
        "y": 8064,
        "height": 11061
      },
      {
        "y": 8640,
        "height": 11061
      },
      {
        "y": 9216,
        "height": 11061
      },
      {
        "y": 9792,
        "height": 11061
      },
      {
        "y": 10341,
        "height": 11061
      }
    ],
    "scans": 20,
    "max_states": 512,
    "settle_ms": 5000,
    "page_timeout_seconds": 150,
    "layout_stability": "consecutive 100ms size samples within one CSS pixel",
    "animation_settling": "finite animations present when scroll resources are ready finish or are cancelled",
    "interactive_states": "not exercised",
    "horizontal_scroll": "not exercised"
  }
}
System Prompt
You are a lead web developer at a top digital agency, tasked with creating a one-page website for a new client based on the given specifications, delivered as an HTML file. First non-whitespace char '<', last non-whitespace char '>'. Use the following services to generate placeholder images where needed:
- placehold.co (text): https://placehold.co/[{w}x{h}|{size}][/{bg-color}/{text-color}]?text={text}&font=[lato|lora|montserrat|noto sans|open sans|oswald|playfair display|poppins|pt sans|raleway|roboto|source sans|source sans pro]
- picsum.photos (photos): https://picsum.photos/[{w}/{h}|{size}]?[grayscale][&blur={1-10}]
- pravatar.cc (avatars): https://i.pravatar.cc/{size}?u={identifier}
Choose sizes appropriate to layout.
User Prompt
Create a **complete, polished, production-quality** primary web page for a new client in the "Society" sector.
Your goal is to generate the full HTML code for a page that is not just functional but also visually compelling, content-rich, and feels like a finished product ready for launch.

**Client & Category:**
- Industry: "Society"
- Description: Social issues, advocacy, cultural organizations, and community initiatives.

**Your Creative Task:**
1.  **Invent:** Create a unique, professional-sounding site name and a strong tagline fitting the "Society" category.
2.  **Define Page:** Determine the most effective primary page type (e.g., homepage, service landing page, category portal) to showcase this fictional entity.
3.  **Design:** Develop an opinionated, modern, and professional layout. Make distinct choices about structure and flow.

**Content & Structure Requirements (Deliver a COMPLETE page):**
-   **Overall:** The final page must feel substantial and complete, with realistic amounts of text (multiple paragraphs per section where appropriate, avoid single sentences), well-integrated placeholder images, and logical flow. It should look like a real website a business would proudly use.
-   **HEADER:** Include the invented site name, tagline, a logo placeholder image, and a primary navigation bar. Ensure the navigation has **at least 5-7 clearly defined, relevant links** including: "News", "About", "Join".
-   **MAIN CONTENT:** Structure this area with **at least 3-4 distinct, well-developed sections**.
    -   Address key topics relevant to the "Society" category. Consider themes similar to: "Community Stories", "Campaign Updates", "Policy Impact".
    -   **Content Depth:** Populate each section with **substantial, realistic text** (multiple sentences/paragraphs). Use authentic industry language and terminology like: "inclusion", "awareness campaign", "coalition building".
    -   **Visuals:** Integrate relevant placeholder images logically within the content sections.
    -   **Calls to Action:** Include clear and contextually relevant CTAs. Use strong verbs similar to: "Join Movement", "Get Involved", "Stand With Us".
-   **ENGAGEMENT (Recommended):** Strongly consider incorporating **one meaningful interactive element** that would genuinely benefit a user in the "Society" sector. Ideas similar but not limited to: "action tracker".
-   **SIDEBAR (Optional):** If your design includes a sidebar, populate it with **useful, relevant content**. Ideas: "partner organizations", "movement updates", "event calendar".
-   **FOOTER:** Include a professional footer with invented contact details, copyright (current year), social media links, and standard links (Privacy, Terms).
-   **MODERN WEB PATTERNS:** Include modern web patterns like testimonial cards, feature grids, or FAQ accordions where appropriate.