{"version":3,"sources":["webpack:///./config/modern-polyfills.js","webpack:///./app/scripts/kickstart.js","webpack:///./app/scripts/components/PartyPill.tsx","webpack:///./app/scripts/components/CandidateRow.tsx","webpack:///./app/scripts/components/EmptyTable.js","webpack:///./app/scripts/components/Contest.tsx","webpack:///./app/scripts/components/DistrictInfo.tsx","webpack:///./app/scripts/components/SeatPartyDivider.tsx","webpack:///./app/scripts/components/Portal.js","webpack:///./app/scripts/utils/debounce.js","webpack:///./app/scripts/utils/noop.js","webpack:///./app/scripts/components/Typeahead.js","webpack:///./app/scripts/components/CountyInfo.js","webpack:///./app/scripts/utils/branch-ballot.js","webpack:///./app/scripts/endpoints.ts","webpack:///./app/scripts/components/LocalRaces.js","webpack:///./app/scripts/components/AsyncComponent.js","webpack:///./app/scripts/components/YourRaces.js","webpack:///./app/scripts/utils/load-asset-url.js","webpack:///./app/scripts/utils/legislative-districts.js","webpack:///./app/scripts/components/Ad.js","webpack:///./app/scripts/BallotApp.tsx","webpack:///./app/scripts/packs/main.js","webpack:///./app/scripts/utils/load-json-script.js","webpack:///./app/scripts/election-utils.ts","webpack:///./app/scripts/utils/get-json.js","webpack:///./app/scripts/packs/ballot-filter.js","webpack:///./app/scripts/utils/shallow-equal.ts","webpack:///./app/scripts/components/PureComponent.tsx"],"names":["require","window","ttData","document","addEventListener","e","link","target","closest","href","getAttribute","startsWith","test","rel","relatedContentContainer","getElementById","related_category","then","_ref","RelatedContent","default","render","h","title","_ref2","AdLoader","delay","init","PartyPill","excludeInitial","party","style","partyPrefix","slice","toLowerCase","partyInitial","toUpperCase","classes","cx","concat","class","capfirst","defaultProps","memoize","CandidateRow","Component","_this$props","this","props","ballotName","isIncumbent","rowClass","IsAsterisk","_defineProperty","contestIsCalled","isViewable","Header","colSpan","columnCount","EmptyTable","converter","PreactHTMLConverter","Contest","onePrimaryParty","contest","contestTitle","isShowcaseRace","redistrictingNote","notes","renderParty","children","onePrimary","length","directory_slug","isSboeDistrict4","office","office_division","isSpecialElection","election_type","IsNoted","get_directory_slug","xlinkHref","map","index","convert","value","includeCountyRundown","DistrictInfo","constructor","super","setState","isExpanded","state","type","onClick","toggle","aria-expanded","String","viewBox","aria-hidden","d","fill","stroke","stroke-width","SeatPartyDivider","viewAllCandidates","partyName","annotations","partyBallot","tableHeader","renderCandidate","candidates","sort_candidates_alphabetically","candidacies","candidate","idx","isHomepage","Portal","componentDidMount","renderPortal","componentWillUnmount","defaultNode","body","removeChild","node","portal","componentDidUpdate","createElement","appendChild","debounce","func","wait","immediate","timeout","args","context","timestamp","result","later","last","Date","now","setTimeout","apply","arguments","callNow","Typeahead","highlightedIndex","isOpen","handleOnBlur","bind","handleOnClear","handleOnFocus","handleOnInput","debouncedHandleOnInput","debounceDuration","handleKeyDown","setInputRef","setMenuRef","setItemRef","listRefs","_","prevState","count","getFilteredItems","Boolean","maybeScrollItemIntoView","element","inputRef","menuRef","_this$state","itemNode","menuNode","scrollIntoView","onlyScrollIfNeeded","items","shouldItemRender","sortItems","filter","item","sort","a","b","highlightItemOnMouseEnter","selectItemOnClick","getItemValue","onSelect","blur","renderList","ref","onMouseDown","event","preventDefault","cloneElement","renderItem","onTouchStart","onMouseEnter","el","renderAttribution","onClear","onBlur","inputProps","onFocus","onChange","keyEvents","key","call","_this$props2","renderInput","_objectSpread","role","autocomplete","onInput","onKeyDown","aria-label","noop","ArrowDown","itemsCount","newIndex","ArrowUp","Enter","keyCode","_this$state2","select","setSelectionRange","Escape","CountyInfo","PureComponent","data","isLoaded","fetchAddress","prevProps","fips","slug","county","replace","getJSON","process","getElementsByClassName","display","admin_title","name","web_site","phone_number","COVERED_DISTRICT_TYPES","createBallot","location","method","headers","JSON","stringify","election","COUNTY_DISTRICT_TYPES","isCountyCourtRace","race","officeName","district","trim","isCountyEducationRace","CITY_DISTRICT_TYPES","isCityRace","includes","EDUCATION_DISTRICT_TYPES","isEducationRace","getLocalRaceTitle","longName","LOCAL_RACE_GROUPS","label","matches","filterDownBallotRaces","races","localRaces","group","filterLocalMeasures","measures","measure","localeCompare","numeric","sensitivity","PARTY_NAMES","D","R","L","G","I","N","LocalCandidate","LocalRace","_id","LocalMeasure","ballotText","LocalRaces","expanded","toggleExpanded","componentWillReceiveProps","nextProps","resetKey","section","getBoundingClientRect","top","behavior","block","_this$props$races","_this$props$measures","asyncComponent","importComponent","PreactComponent","component","m","elementId","AsyncDistrictMap","AsyncDistrictStats","googleIMG","parse","textContent","asset_url","PlacesLib","bounds","east","west","south","north","toCoordinates","latLng","latitude","lat","longitude","lng","YourRaces","contests","coordinates","lookupError","lookupPending","lookedFoundStored","results","selectedPlaceId","bodyWidth","width","branchBallot","branchPending","activeRaceFilters","raceSearchQuery","handleGeocode","debouncedHandleGeocode","onSubmit","onJumpToAllRaces","getContainerWidth","toggleRaceFilter","onRaceSearchChange","sessionToken","branchRequestId","selectedPrediction","branchPrefetch","innerWidth","clearZip","zipInput","activeWithoutAll","f","heading","clearBodyOverflowLock","overflow","once","AutocompleteSessionToken","input","async","request","locationRestriction","includedPrimaryTypes","region","AutocompleteSuggestion","fetchAutocompleteSuggestions","suggestions","s","id","placePrediction","placeId","description","text","toString","place_id","_prediction","getPredictions","prefetchSelectedPlace","prediction","placePromise","place","toPlace","Place","fetchFields","fields","prefetchZip","promise","prefetchBranchBallot","zipComponent","addressComponents","find","types","longText","buildBranchLocation","console","warn","components","findComponent","match","c","undefined","stateComponent","zip","parseInt","address","formattedAddress","city","shortText","Number","isNaN","requestId","prefetch","emptyGroupKeys","some","push","_ref3","addressInput","checkValidity","emailInput","includeGeography","LOOKUP_URL","_ref4","hasSboeRace","sboe","_ref5","catch","error","loadBranchBallot","reportValidity","google","maps","importLibrary","removeEventListener","shouldShowRace","localMeasures","localRacesByGroup","forEach","normalizeForSearch","str","raceSearchTerm","matchesRaceSearch","raceSearchTitles","us_house","tx_senate","tx_house","localRaceSearchItems","raceSearchItems","addressFeedback","noteMatches","raceCounts","education","all","reduce","total","matchLocalSearch","getTitle","exactMatches","shownLocalRaces","shownLocalMeasures","raceSlotCategories","totalRaceSlots","Object","keys","visibleRaceSlots","for","placeholder","required","isHighlighted","src","alt","_extends","setAttribute","counties","_resultsPortal","disabled","query","office_slug","determineContestTitleYourRaces","candidateId","is_incumbent","point","Ad","App","fetchData","dropDuplicateSpecials","seats_mapped","number","array","propertyName","texasHouseGroups","usHouseGroups","unique_seats","i","findIndex","texasHouse","usHouse","chunk","_yourPortal","querySelector","_usPortal","contestGroup","determineContestTitle","_supremePortal","_sboePortal","_crimPortal","_fifteenthPortal","_senatePortal","_housePortal","loadJsonScript","roundThousands","num","intcomma","Math","round","intword","timer","arr","size","acc","entries","entry","other","callback","ms","clearTimeout","TT_directory_slugs","sort_name","OFFICE_DISPLAY_NAMES","determineDistrictTitle","division_type","jsonResponse","res","ok","Error","status","statusText","json","fetch","filterBar","searchInput","searchList","searchClear","resultsCount","buttons","Array","prototype","querySelectorAll","normalize","titleEl","category","dataset","raceCategory","getActiveFilter","active","classList","contains","showAll","indexOf","baseLabels","updateCounts","categoryCounts","btn","officeContainer","parentElement","topLevelAds","nestedAds","refreshNestedAds","next","matchesSearch","term","totalRaces","visibleRaces","seats","hidden","seat","anySeatMatches","seatTitle","seatMatches","isFiltered","ad","innerHTML","seatEntries","refreshSeatEntries","contestsContainers","MutationObserver","seatObserver","container","observe","childList","subtree","scrollToAllRacesTop","remove","add","allBtn","currentMatches","li","className","selectEntry","passive","updateClearButton","focus","min","max","jumpToPersonalizedLink","hOP","hasOwnProperty","is","x","y","shallowEqual","objA","objB","keysA","keysB","shouldComponentUpdate"],"mappings":"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","file":"main.cb459ba8b5.mjs","sourcesContent":["'use strict';\n\n// We depend on intersection-observer enough that it should just be assumed as necessary\nrequire('intersection-observer');\n","import { h, render } from 'preact';\nimport { delay } from './election-utils';\n\n// just in case this gets removed\nwindow.ttData = window.ttData || {};\n\n// open links in a new tab\ndocument.addEventListener('click', e => {\n  const link = e.target.closest && e.target.closest('a[href]');\n  if (!link || link.target) return;\n\n  const href = link.getAttribute('href');\n  if (href.startsWith('#') || /^(mailto|tel|javascript):/i.test(href)) return;\n\n  link.target = '_blank';\n  link.rel = 'noopener';\n});\n\n// related content\nconst relatedContentContainer = document.getElementById(\n  'related-content-container'\n);\n\nif (relatedContentContainer && window.ttData.related_category) {\n  import(\n    /* webpackChunkName: \"RelatedContent\" */ './components/RelatedContent'\n  ).then(({ default: RelatedContent }) =>\n    render(\n      <RelatedContent\n        title={'Read more'}\n        related_category={window.ttData.related_category}\n      />,\n      relatedContentContainer\n    )\n  );\n}\n\nimport(/* webpackChunkName: \"ads\" */ './utils/ad-loader').then(\n  ({ default: AdLoader }) => {\n    delay(function() {\n      const ads = new AdLoader();\n      ads.init();\n    }, 600); // end delay\n  }\n);\n","// packages\nimport cx from 'classnames';\nimport { capfirst } from 'journalize';\nimport memoize from 'lodash.memoize';\nimport { h } from 'preact';\n\ntype Props = {\n  excludeInitial?: boolean;\n  party: string;\n  style: string;\n};\n\nfunction PartyPill({ excludeInitial, party, style }: Props) {\n  const partyPrefix = party.slice(0, 3).toLowerCase();\n  const partyInitial = party[0].toUpperCase();\n\n  const classes = cx('circle-pill', `pill--${partyPrefix}`);\n\n  return (\n    <span class={classes} style={style} title={capfirst(party)}>\n      {!excludeInitial && partyInitial}\n    </span>\n  );\n}\n\nPartyPill.defaultProps = {\n  excludeInitial: false,\n};\n\nexport default memoize(PartyPill, ({ party, style }) => ({\n  party: party,\n  style: style,\n}));\n","import cx from 'classnames';\nimport { Component, h, VNode } from 'preact';\n\nimport PartyPill from './PartyPill';\n\ninterface Props {\n  ballotName: string;\n  candidateId: string;\n  isIncumbent: boolean;\n  party: string;\n}\n\nclass CandidateRow extends Component<Props> {\n  static Header: VNode;\n  static columnCount: number;\n\n  render() {\n    const { ballotName, isIncumbent, party } = this.props;\n\n    let divStyle;\n\n    let rowClass = cx('candidate', 'contest__candidate-row');\n\n    const IsAsterisk =\n      ballotName == 'Andrew White' || ballotName == 'Jay Nagy' ? true : false;\n\n    return (\n      <tr class={rowClass}>\n        <td class=\"candidate__cell candidate__party\">\n          <PartyPill party={party} />\n        </td>\n        <th class=\"candidate__cell candidate__name\">\n          {ballotName}\n          {IsAsterisk && <span class=\"asterisk_out\">*</span>}{' '}\n          {isIncumbent && (\n            <span class=\"pill pill--basic\" title=\"Currently holds this seat\">\n              Incumbent\n            </span>\n          )}\n        </th>\n      </tr>\n    );\n  }\n}\n\nCandidateRow.defaultProps = {\n  contestIsCalled: false,\n  isViewable: true,\n};\n\nCandidateRow.Header = (\n  <thead>\n    <tr>\n      <th class=\"contest__candidate-header\" colSpan={2}>\n        Candidates\n      </th>\n    </tr>\n  </thead>\n);\n\nCandidateRow.columnCount = 2;\n\nexport default CandidateRow;\n","import { h } from 'preact';\nimport cx from 'classnames';\nimport CandidateRow from './CandidateRow';\n\nconst EmptyTable = ({ party }) => {\n  const rowClass = cx('seat__race', {\n    'seat__race--Democrat': party == 'Democrat',\n    'seat__race--Republican': party == 'Republican',\n  });\n  return (\n    <div class={rowClass}>\n      <div class=\"race\">\n        <span>\n          <h4 class=\"race__title\">{party} </h4>\n        </span>\n      </div>\n      <table class=\"race__candidates\">{CandidateRow.Header}</table>\n      <div class=\"no_primary no_primary_candidates\">\n        No primary candidates running\n      </div>\n    </div>\n  );\n};\n\nexport default EmptyTable;\n","import cx from 'classnames';\nimport { Component, h } from 'preact';\nimport { PreactHTMLConverter } from 'preact-html-converter';\n\n// components\nimport EmptyTable from './EmptyTable';\n\n// internal\nimport { get_directory_slug } from '../election-utils';\n\nconst converter = PreactHTMLConverter();\n\ntype Props = {\n  contest: { [key: string]: any };\n  notes: { [key: string]: any };\n  columnCount: number;\n  contestTitle: string;\n  renderParty: any;\n  renderCandidate: any;\n  children?: any;\n};\n\nclass Contest extends Component<Props> {\n  render() {\n    const {\n      contest,\n      columnCount,\n      contestTitle,\n      isShowcaseRace,\n      redistrictingNote,\n      notes,\n      renderParty,\n      children,\n    } = this.props;\n\n    const onePrimary = contest.length == 1;\n\n    let onePrimaryParty;\n\n    if (onePrimary) {\n      onePrimaryParty = contest[0].party;\n    }\n\n    const isSboeDistrict4 =\n      contest &&\n      contest[0] &&\n      contest[0].office === 'State Board of Education' &&\n      contest[0].office_division === 4;\n\n    const isSpecialElection =\n      contest &&\n      contest[0] &&\n      contest[0].election_type === 'special' &&\n      !isSboeDistrict4;\n\n    let directory_slug;\n\n    const IsNoted = notes && notes.length > 0 ? true : false;\n\n    if (contest[0]) {\n      directory_slug = get_directory_slug(contest[0].office);\n    }\n\n    return (\n      <div class={cx('seat', { 'special-election': isSpecialElection })}>\n        {!isShowcaseRace && contest && (\n          <h3 class=\"seat__title\">\n            {isSpecialElection && (\n              <div class=\"special-election__title\">Special Election</div>\n            )}\n            <span>{contestTitle}</span>\n            {directory_slug[0] != null && (\n              <a\n                class=\"t-links-unset\"\n                href={`https://directory.texastribune.org/districts/${directory_slug[0]['directory-slug']}/${contest[0]['office_division']}/`}\n              >\n                <span\n                  class=\"icon-div\"\n                  title=\"Click to learn more about this district\"\n                >\n                  <svg class=\"icon icon-info\">\n                    <use xlinkHref=\"#icon-info\"></use>\n                  </svg>\n                </span>\n              </a>\n            )}\n            {redistrictingNote && contest && (\n              <div class=\"redistrictingNote\">\n                Newly drawn{' '}\n                <a href=\"https://www.texastribune.org/2025/09/04/2025-texas-redistricting-maps/\">\n                  in 2025\n                </a>\n              </div>\n            )}\n          </h3>\n        )}\n\n        <div class={cx('seat__races', { 'seat__races--single': onePrimary })}>\n          {onePrimary && onePrimaryParty == 'Republican' && (\n            <EmptyTable party={'Democrat'} />\n          )}\n          {contest.map((party: any, index) => renderParty(party, index))}\n          {onePrimary && onePrimaryParty == 'Democrat' && (\n            <EmptyTable party={'Republican'} />\n          )}\n        </div>\n        {IsNoted == true && (\n          <p class=\"note__text note__text__both-parties\">\n            {converter.convert(notes[0].value)}\n          </p>\n        )}\n        {children}\n      </div>\n    );\n  }\n}\n\nContest.defaultProps = {\n  isShowcaseRace: false,\n  includeCountyRundown: false,\n};\n\nexport default Contest;\n","import cx from 'classnames';\nimport { Component, h } from 'preact';\n\ntype Props = {\n  children?: any;\n};\n\ntype State = {\n  isExpanded: boolean;\n};\n\nclass DistrictInfo extends Component<Props, State> {\n  constructor(props: Props) {\n    super(props);\n    this.state = { isExpanded: true };\n  }\n\n  toggle = () => {\n    this.setState({ isExpanded: !this.state.isExpanded });\n  };\n\n  render() {\n    const { children } = this.props;\n    const { isExpanded } = this.state;\n\n    return (\n      <div class=\"district-info\">\n        <button\n          type=\"button\"\n          class={cx('district-info__toggle', { 'is-expanded': isExpanded })}\n          onClick={this.toggle}\n          aria-expanded={String(isExpanded)}\n        >\n          <h4 class=\"district-grid__title\">About this district</h4>\n          <svg\n            class=\"district-info__chevron\"\n            viewBox=\"0 0 12 8\"\n            aria-hidden=\"true\"\n          >\n            <path\n              d=\"M1 1l5 5 5-5\"\n              fill=\"none\"\n              stroke=\"currentColor\"\n              stroke-width=\"2\"\n            />\n          </svg>\n        </button>\n        {isExpanded && <div class=\"district-grid\">{children}</div>}\n      </div>\n    );\n  }\n}\n\nexport default DistrictInfo;\n","import cx from 'classnames';\nimport { Component, h } from 'preact';\n\nimport { PreactHTMLConverter } from 'preact-html-converter';\n\n// internal\nimport { sort_candidates_alphabetically } from '../election-utils';\n\ninterface Props {\n  partyName: string;\n  tableHeader: JSX.Element;\n  notes: { [key: string]: any };\n  columnCount: number;\n  partyBallot: { [key: string]: any };\n  renderCandidate: any;\n  contestTitle: string;\n}\n\nclass SeatPartyDivider extends Component {\n  constructor() {\n    super();\n\n    this.state = {\n      viewAllCandidates: false,\n    };\n  }\n\n  render() {\n    const {\n      partyName,\n      annotations,\n      notes,\n      partyBallot,\n      tableHeader,\n      columnCount,\n      renderCandidate,\n      contestTitle,\n    } = this.props;\n\n    const { viewAllCandidates } = this.state;\n\n    const converter = PreactHTMLConverter();\n\n    const candidates = sort_candidates_alphabetically(partyBallot.candidacies);\n\n    const rowClass = cx('seat__race', {\n      'seat__race--Democrat': partyName == 'Democrat',\n      'seat__race--Republican': partyName == 'Republican',\n    });\n\n    const IsNoted = notes && notes.length > 0 ? true : false;\n\n    return (\n      <div class={rowClass}>\n        {partyName && (\n          <div class=\"race\">\n            <span>\n              <h4 class=\"race__title\">{partyName} </h4>\n            </span>\n          </div>\n        )}\n\n        <table class=\"race__candidates\">\n          {tableHeader}\n          <tbody>\n            {candidates.map((candidate: any, idx: any) =>\n              renderCandidate(candidate, idx)\n            )}\n          </tbody>\n        </table>\n\n        {IsNoted == true && (\n          <p class=\"note__text\">{converter.convert(notes[0].value)}</p>\n        )}\n      </div>\n    );\n  }\n}\n\nSeatPartyDivider.defaultProps = {\n  isShowcaseRace: false,\n  isHomepage: false,\n};\n\nexport default SeatPartyDivider;\n","import { Component, h, render } from 'preact';\n\nclass Portal extends Component {\n  componentDidMount() {\n    this.renderPortal();\n  }\n\n  componentWillUnmount() {\n    if (this.defaultNode) {\n      document.body.removeChild(this.defaultNode);\n    } else {\n      // Unmount the children rendered in custom node\n      render(null, this.props.node, this.portal);\n    }\n\n    this.defaultNode = null;\n    this.portal = null;\n  }\n\n  componentDidUpdate() {\n    this.renderPortal();\n  }\n\n  renderPortal() {\n    if (!this.props.node && !this.defaultNode) {\n      this.defaultNode = document.createElement('div');\n      document.body.appendChild(this.defaultNode);\n    }\n\n    const children = this.props.children;\n\n    this.portal = render(\n      (children && children[0]) || null,\n      this.props.node || this.defaultNode,\n      this.portal\n    );\n  }\n\n  render() {\n    return null;\n  }\n}\n\nexport default Portal;\n","export default function debounce(func, wait, immediate) {\n  var timeout, args, context, timestamp, result;\n\n  var later = function() {\n    var last = Date.now() - timestamp;\n\n    if (last < wait && last >= 0) {\n      timeout = setTimeout(later, wait - last);\n    } else {\n      timeout = null;\n      if (!immediate) {\n        result = func.apply(context, args);\n        if (!timeout) context = args = null;\n      }\n    }\n  };\n\n  return function() {\n    context = this;\n    args = arguments;\n    timestamp = Date.now();\n    var callNow = immediate && !timeout;\n    if (!timeout) timeout = setTimeout(later, wait);\n    if (callNow) {\n      result = func.apply(context, args);\n      context = args = null;\n    }\n\n    return result;\n  };\n}\n","export default () => {};\n","// packages\nimport { cloneElement, Component, h } from 'preact';\nimport scrollIntoView from 'dom-scroll-into-view';\n\n// internal\nimport debounce from '../utils/debounce';\nimport noop from '../utils/noop';\n\nclass Typeahead extends Component {\n  constructor(props) {\n    super(props);\n\n    this.state = {\n      highlightedIndex: null,\n      isOpen: false,\n    };\n\n    this.handleOnBlur = this.handleOnBlur.bind(this);\n    this.handleOnClear = this.handleOnClear.bind(this);\n    this.handleOnFocus = this.handleOnFocus.bind(this);\n    this.handleOnInput = this.handleOnInput.bind(this);\n    this.debouncedHandleOnInput = debounce(\n      this.handleOnInput,\n      this.props.debounceDuration\n    );\n    this.handleKeyDown = this.handleKeyDown.bind(this);\n    this.setInputRef = this.setInputRef.bind(this);\n    this.setMenuRef = this.setMenuRef.bind(this);\n    this.setItemRef = this.setItemRef.bind(this);\n\n    this.listRefs = {};\n  }\n\n  static getDerivedStateFromProps(_, prevState) {\n    if (prevState.highlightedIndex == null) {\n      return { highlightedIndex: 0 };\n    }\n  }\n\n  componentDidUpdate() {\n    const { highlightedIndex } = this.state;\n    const count = this.getFilteredItems(this.props).length;\n\n    if (Boolean(highlightedIndex) && highlightedIndex >= count) {\n      this.setState({ highlightedIndex: 0 });\n    }\n\n    this.maybeScrollItemIntoView();\n  }\n\n  setInputRef(element) {\n    this.inputRef = element;\n  }\n\n  setMenuRef(element) {\n    this.menuRef = element;\n  }\n\n  setItemRef(element, idx) {\n    this.listRefs[`item-${idx}`] = element;\n  }\n\n  maybeScrollItemIntoView() {\n    const { highlightedIndex, isOpen } = this.state;\n\n    if (isOpen && highlightedIndex != null) {\n      const itemNode = this.listRefs[`item-${this.state.highlightedIndex}`];\n      const menuNode = this.menuRef;\n\n      if (itemNode && menuNode) {\n        scrollIntoView(itemNode, menuNode, {\n          onlyScrollIfNeeded: true,\n        });\n      }\n    }\n  }\n\n  getFilteredItems(props) {\n    let { items } = props;\n\n    const { shouldItemRender, sortItems } = props;\n\n    if (shouldItemRender) {\n      items = items.filter(item => shouldItemRender(item, props.value));\n    }\n\n    if (sortItems) {\n      items = items.sort((a, b) => sortItems(a, b, props.value));\n    }\n\n    return items;\n  }\n\n  highlightItemOnMouseEnter(highlightedIndex) {\n    this.setState({ highlightedIndex });\n  }\n\n  selectItemOnClick(item) {\n    const { getItemValue, onSelect } = this.props;\n\n    const value = getItemValue(item);\n\n    this.setState(\n      {\n        highlightedIndex: null,\n        isOpen: false,\n      },\n      () => {\n        this.inputRef.blur();\n        onSelect(value, item);\n      }\n    );\n  }\n\n  renderList() {\n    const { highlightedIndex } = this.state;\n    const props = this.props;\n\n    if (!props.value) return null;\n\n    const items = this.getFilteredItems(props);\n\n    return (\n      <ul\n        class=\"listbox\"\n        ref={this.setMenuRef}\n        onMouseDown={event => event.preventDefault()}\n      >\n        {items.map((item, idx) => {\n          return cloneElement(\n            props.renderItem(item, idx === highlightedIndex),\n            {\n              onClick: () => this.selectItemOnClick(item),\n              // Selects on touchstart directly rather than waiting for the\n              // browser to synthesize mousedown/click from the tap — on some\n              // mobile browsers that synthesis is delayed or dropped once a\n              // scroll gesture looks possible, which otherwise leaves a tap\n              // doing nothing until a later keyboard Enter re-triggers\n              // selection through a different path.\n              onTouchStart: event => {\n                event.preventDefault();\n                this.selectItemOnClick(item);\n              },\n              onMouseEnter: () => this.highlightItemOnMouseEnter(idx),\n              ref: el => this.setItemRef(el, idx),\n            }\n          );\n        })}\n        {items.length > 0 && props.renderAttribution()}\n      </ul>\n    );\n  }\n\n  handleOnClear(event) {\n    this.setState({ isOpen: false });\n\n    this.props.onClear(event);\n  }\n\n  handleOnBlur() {\n    // On touch devices blur can fire on touchstart, before the tap's click\n    // event reaches the item — closing synchronously here would unmount the\n    // list first and the tap would never register. Deferring a tick lets\n    // that click land first, same fix as ballot-filter.js's own\n    // setTimeout(0) on its search dropdown's blur handler.\n    setTimeout(() => this.setState({ isOpen: false }), 0);\n\n    const { onBlur } = this.props.inputProps;\n    if (onBlur) onBlur(event);\n  }\n\n  handleOnFocus(event) {\n    const { value } = this.props;\n\n    if (value.length > 0) this.setState({ isOpen: true });\n\n    const { onFocus } = this.props.inputProps;\n    if (onFocus) onFocus(event);\n  }\n\n  handleOnInput(event) {\n    const { value } = event.target;\n\n    this.props.onChange(value, event);\n\n    if (value.length <= 0) {\n      this.setState({ highlightedIndex: null });\n    }\n  }\n\n  handleKeyDown(event) {\n    const { isOpen } = this.state;\n\n    if (isOpen && Typeahead.keyEvents[event.key]) {\n      Typeahead.keyEvents[event.key].call(this, event);\n    } else if (!isOpen) {\n      this.setState({ isOpen: true });\n    }\n  }\n\n  render() {\n    const { inputProps, onClear, renderInput, value } = this.props;\n    const { isOpen } = this.state;\n\n    return (\n      <div class=\"typeahead\">\n        <div class=\"typeahead__input-wrapper\">\n          {renderInput({\n            ...inputProps,\n            role: 'combobox',\n            'aria-autocomplete': 'list',\n            'aria-expanded': String(isOpen),\n            autocomplete: 'off',\n            onBlur: this.handleOnBlur,\n            onFocus: this.handleOnFocus,\n            onInput: this.handleOnInput,\n            onKeyDown: this.handleKeyDown,\n            value,\n            ref: this.setInputRef,\n          })}\n          {onClear && value && (\n            <button\n              onClick={this.handleOnClear}\n              type=\"button\"\n              class=\"close\"\n              aria-label=\"Clear\"\n            >\n              <span aria-hidden=\"true\">&times;</span>\n            </button>\n          )}\n        </div>\n        {isOpen && this.renderList()}\n      </div>\n    );\n  }\n}\n\nTypeahead.defaultProps = {\n  debounceDuration: 150,\n  inputProps: {},\n  onChange: noop,\n  onClear: noop,\n  onSelect: noop,\n  renderInput: props => <input {...props} />,\n  value: '',\n};\n\nTypeahead.keyEvents = {\n  ArrowDown(event) {\n    event.preventDefault();\n\n    const items = this.getFilteredItems(this.props);\n    const itemsCount = items.length;\n    if (itemsCount < 1) return;\n\n    const { highlightedIndex } = this.state;\n\n    const newIndex =\n      highlightedIndex < itemsCount - 1\n        ? highlightedIndex + 1\n        : highlightedIndex;\n\n    this.setState({ highlightedIndex: newIndex });\n  },\n\n  ArrowUp(event) {\n    event.preventDefault();\n\n    const items = this.getFilteredItems(this.props);\n    const itemsCount = items.length;\n    if (itemsCount < 1) return;\n\n    const { highlightedIndex } = this.state;\n\n    const newIndex =\n      highlightedIndex > 0 ? highlightedIndex - 1 : highlightedIndex;\n\n    this.setState({ highlightedIndex: newIndex });\n  },\n\n  Enter(event) {\n    // not the right kind of Enter, abort\n    if (event.keyCode !== 13) return;\n\n    const { highlightedIndex, isOpen } = this.state;\n\n    if (!isOpen) {\n      // the menu is not open\n      return;\n    } else if (highlightedIndex == null) {\n      // input has control, but there's nothing selected\n      this.setState({ isOpen: false }, () => this.inputRef.select());\n    } else {\n      // the input has control and we have an item\n      event.preventDefault();\n\n      const item = this.getFilteredItems(this.props)[highlightedIndex];\n      const value = this.props.getItemValue(item);\n\n      this.setState(\n        {\n          highlightedIndex: null,\n          isOpen: false,\n        },\n        () => {\n          this.inputRef.setSelectionRange(value.length, value.length);\n          this.props.onSelect(value, item);\n        }\n      );\n    }\n  },\n\n  Escape() {\n    this.setState({\n      highlightedIndex: null,\n      isOpen: false,\n    });\n  },\n};\n\nexport default Typeahead;\n","import { h } from 'preact';\nimport getJSON from '../utils/get-json';\nimport PureComponent from './PureComponent';\n\nimport { PreactHTMLConverter } from 'preact-html-converter';\n\nconst converter = PreactHTMLConverter();\n\nclass CountyInfo extends PureComponent {\n  constructor() {\n    super();\n\n    this.state = { data: null, isLoaded: false };\n  }\n\n  componentDidMount() {\n    this.fetchAddress();\n  }\n\n  componentDidUpdate(prevProps) {\n    if (this.props.fips !== prevProps.fips) {\n      this.fetchAddress();\n    }\n  }\n\n  fetchAddress() {\n    const { county } = this.props;\n    const slug = county.toLowerCase().replace(/\\s+/g, '');\n\n    getJSON(`${process.env.PUBLIC_PATH}api/counties/${slug}.json`).then(\n      data => {\n        this.setState({ data, isLoaded: true });\n      }\n    );\n  }\n\n  render() {\n    const { county } = this.props;\n    const { data, isLoaded } = this.state;\n\n    if (!isLoaded) return null;\n\n    document.getElementsByClassName('intro-prose')[0].style.display = 'none';\n\n    return (\n      <div class=\"t-serif t-links-underlined has-page-padding\">\n        <p class=\"t-copy\">\n          Because you shared your location with us, we were able to determine\n          you are in <span class=\"font-weight-bold\">{county} County</span>. Your\n          general election contact is{' '}\n          <span class=\"font-weight-bold\">\n            {data.admin_title} {converter.convert(data.name)}\n          </span>\n          . To learn more about your local and county races and see a sample\n          ballot,{' '}\n          <a class=\"t-links-underlined\" href={data.web_site}>\n            you can visit the county's website\n          </a>\n          , or call the election office at{' '}\n          <span class=\"font-weight-bold\">{data.phone_number}</span>.\n        </p>\n      </div>\n    );\n  }\n}\n\nexport default CountyInfo;\n","import getJSON from './get-json';\nimport {\n  BRANCH_API_BASE,\n  BRANCH_ORG_ID,\n  BRANCH_ELECTION_KEY,\n} from '../endpoints';\n\nconst COVERED_DISTRICT_TYPES = [\n  'state',\n  'congressional',\n  'state-senate',\n  'state-house',\n  'state-board-of-education',\n];\n\nexport function createBallot(location) {\n  return getJSON(`${BRANCH_API_BASE}/ballots`, {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n      'X-Organization-Id': BRANCH_ORG_ID,\n    },\n    body: JSON.stringify({\n      location,\n      election: BRANCH_ELECTION_KEY,\n    }),\n  });\n}\n\nconst COUNTY_DISTRICT_TYPES = ['county', 'county-district'];\n\nconst isCountyCourtRace = race => {\n  const officeName = race.officeName || '';\n\n  return (\n    race.district.type === 'county' &&\n    /court|judge/i.test(officeName) &&\n    !/^county judge$/i.test(officeName.trim())\n  );\n};\n\nconst isCountyEducationRace = race =>\n  race.district.type === 'county' && /education/i.test(race.officeName || '');\n\nconst isCountyRace = race =>\n  COUNTY_DISTRICT_TYPES.includes(race.district.type) &&\n  !isCountyCourtRace(race) &&\n  !isCountyEducationRace(race);\n\nconst CITY_DISTRICT_TYPES = ['city', 'city-council'];\n\nconst isCityRace = race => CITY_DISTRICT_TYPES.includes(race.district.type);\n\nconst EDUCATION_DISTRICT_TYPES = ['state-school', 'state-school-subdistrict'];\n\nconst isEducationRace = race =>\n  EDUCATION_DISTRICT_TYPES.includes(race.district.type) ||\n  isCountyEducationRace(race);\n\nconst isJudicialRace = race =>\n  isCountyCourtRace(race) ||\n  (!COUNTY_DISTRICT_TYPES.includes(race.district.type) &&\n    !isCityRace(race) &&\n    !isEducationRace(race));\n\nexport const getLocalRaceTitle = race => race.longName || race.officeName;\n\nexport const LOCAL_RACE_GROUPS = [\n  { key: 'local-county', label: 'Local: County', matches: isCountyRace },\n  { key: 'local-city', label: 'Local: City', matches: isCityRace },\n  {\n    key: 'local-education',\n    label: 'Local: Education',\n    matches: isEducationRace,\n  },\n  { key: 'local-judicial', label: 'Local: Judicial', matches: isJudicialRace },\n];\n\nexport function filterDownBallotRaces(races) {\n  if (!races) return [];\n\n  const localRaces = races.filter(race => {\n    if (!race.district) return false;\n    return !COVERED_DISTRICT_TYPES.includes(race.district.type);\n  });\n\n  return [].concat(\n    ...LOCAL_RACE_GROUPS.map(group => localRaces.filter(group.matches))\n  );\n}\n\nexport function filterLocalMeasures(measures) {\n  if (!measures) return [];\n\n  return measures\n    .filter(\n      measure =>\n        measure.title &&\n        measure.district &&\n        !COVERED_DISTRICT_TYPES.includes(measure.district.type)\n    )\n    .sort((a, b) =>\n      a.title.localeCompare(b.title, 'en', {\n        numeric: true,\n        sensitivity: 'base',\n      })\n    );\n}\n","// JSON updated by Republic\nconst FLAT_BALLOT_URL =\n  'https://s3.us-east-1.amazonaws.com/sos-test-2.texastribune.org/2026_general/ballot_page/results_FLAT_for_ballot_test.json';\n\n// Branch API (VoterGuideOS) local races and elections\nconst BRANCH_API_BASE = 'https://www.branch.vote/api/v1';\nconst BRANCH_ORG_ID = '6a91a5e29f7c4de2d9e86f8a';\nconst BRANCH_ELECTION_KEY = '2026-texas-general-election';\n\nexport { FLAT_BALLOT_URL, BRANCH_API_BASE, BRANCH_ORG_ID, BRANCH_ELECTION_KEY };\n","import { h } from 'preact';\nimport PureComponent from './PureComponent';\nimport PartyPill from './PartyPill';\nimport { getLocalRaceTitle } from '../utils/branch-ballot';\n\nconst PARTY_NAMES = {\n  D: 'Democrat',\n  R: 'Republican',\n  L: 'Libertarian',\n  G: 'Green',\n  I: 'Independent',\n  N: 'Nonpartisan',\n};\n\nconst partyName = party => PARTY_NAMES[party] || party;\n\n// How many local races and measures show before the \"See more\" button is clicked.\nconst INITIAL_VISIBLE_RACES = 4;\n\nclass LocalCandidate extends PureComponent {\n  render() {\n    const { candidate } = this.props;\n\n    return (\n      <tr class=\"candidate race__candidate-row\">\n        <td class=\"candidate__cell candidate__party\">\n          {candidate.party && <PartyPill party={partyName(candidate.party)} />}\n        </td>\n        <th class=\"candidate__cell candidate__name\">{candidate.name}</th>\n      </tr>\n    );\n  }\n}\n\nclass LocalRace extends PureComponent {\n  render() {\n    const { race } = this.props;\n    const candidates = race.candidates || [];\n\n    return (\n      <div class=\"seat\">\n        <h3 class=\"seat__title\">\n          <span>{getLocalRaceTitle(race)}</span>\n        </h3>\n        {candidates.length > 0 ? (\n          <table class=\"race__candidates\">\n            <thead>\n              <tr>\n                <th class=\"contest__candidate-header\" colSpan={2}>\n                  Candidates\n                </th>\n              </tr>\n            </thead>\n            <tbody>\n              {candidates.map(candidate => (\n                <LocalCandidate key={candidate._id} candidate={candidate} />\n              ))}\n            </tbody>\n          </table>\n        ) : (\n          <div class=\"no_primary_candidates\">No candidates listed yet.</div>\n        )}\n      </div>\n    );\n  }\n}\n\nclass LocalMeasure extends PureComponent {\n  render() {\n    const { measure } = this.props;\n\n    return (\n      <div class=\"seat\">\n        <h3 class=\"seat__title\">\n          <span>{measure.title}</span>\n        </h3>\n        {measure.ballotText && (\n          <p class=\"local-measure__text\">{measure.ballotText}</p>\n        )}\n      </div>\n    );\n  }\n}\n\nclass LocalRaces extends PureComponent {\n  constructor() {\n    super();\n\n    this.state = { expanded: false };\n    this.toggleExpanded = this.toggleExpanded.bind(this);\n  }\n\n  // Collapse again when a new lookup replaces the races (resetKey changes),\n  // so the next address doesn't inherit the previous one's expanded state.\n  componentWillReceiveProps(nextProps) {\n    if (nextProps.resetKey !== this.props.resetKey) {\n      this.setState({ expanded: false });\n    }\n  }\n\n  toggleExpanded() {\n    const { expanded } = this.state;\n\n    if (!expanded) {\n      this.setState({ expanded: true });\n      return;\n    }\n\n    this.setState({ expanded: false }, () => {\n      if (!this.section) return;\n\n      // The button floats, so the reader can click it from anywhere in the\n      // long list — and most of what they were looking at disappears. If the\n      // top of the section is now above the screen, land on it right away\n      // rather than scrolling back up past rows that no longer exist.\n      if (this.section.getBoundingClientRect().top < 0) {\n        this.section.scrollIntoView({ behavior: 'instant', block: 'start' });\n      }\n    });\n  }\n\n  render() {\n    const { races = [], measures = [] } = this.props;\n    const { expanded } = this.state;\n\n    if (races.length === 0 && measures.length === 0) {\n      return (\n        <div class=\"local-races-section\">\n          <p class=\"has-padding t-serif\">\n            Local race information isn't fully available for your address yet.\n          </p>\n        </div>\n      );\n    }\n\n    // Measures go in the same grid (and behind the same \"See all\") as the\n    // races, so the local section reads as one list.\n    const items = [\n      ...races.map(race => <LocalRace key={race._id} race={race} />),\n      ...measures.map(measure => (\n        <LocalMeasure key={measure._id} measure={measure} />\n      )),\n    ];\n\n    return (\n      <div class=\"local-races-section\" ref={el => (this.section = el)}>\n        <div class=\"local-races\">\n          {expanded ? items : items.slice(0, INITIAL_VISIBLE_RACES)}\n        </div>\n        {items.length > INITIAL_VISIBLE_RACES && (\n          <button\n            type=\"button\"\n            class={\n              expanded\n                ? 'local-races-section__more local-races-section__more--floating'\n                : 'local-races-section__more'\n            }\n            onClick={this.toggleExpanded}\n          >\n            {expanded\n              ? 'See less'\n              : `See all (+${items.length - INITIAL_VISIBLE_RACES})`}\n          </button>\n        )}\n      </div>\n    );\n  }\n}\n\nexport default LocalRaces;\n","import { Component as PreactComponent, h } from 'preact';\n\nfunction resolve(m) {\n  return m && m.default ? m.default : m;\n}\n\nfunction asyncComponent(importComponent) {\n  return class extends PreactComponent {\n    constructor() {\n      super();\n\n      this.state = { component: null };\n    }\n\n    componentDidMount() {\n      importComponent().then(component =>\n        this.setState({ component: resolve(component) })\n      );\n    }\n\n    render() {\n      const { component: Component } = this.state;\n\n      return Component ? <Component {...this.props} /> : null;\n    }\n  };\n}\n\nexport default asyncComponent;\n","// packages\nimport cx from 'classnames';\nimport { h } from 'preact';\n\n// components\nimport CandidateRow from './CandidateRow';\nimport Contest from './Contest';\nimport DistrictInfo from './DistrictInfo';\nimport SeatPartyDivider from './SeatPartyDivider';\nimport Portal from './Portal';\nimport PureComponent from './PureComponent';\nimport Typeahead from './Typeahead';\nimport CountyInfo from './CountyInfo';\nimport LocalRaces from './LocalRaces';\nimport asyncComponent from './AsyncComponent';\n\n// Lazy-loaded so the district map code (d3, turf, etc.) isn't in the initial bundle\nconst AsyncDistrictMap = asyncComponent(() =>\n  import(\n    /* webpackPrefetch: true, webpackChunkName: \"DistrictMap\" */ './DistrictMapNew'\n  )\n);\n\n// Lazy-loaded district demographics/turnout stats (eligible voters, race\n// breakdown, 2024 turnout, previous-results chart)\nconst AsyncDistrictStats = asyncComponent(() =>\n  import(\n    /* webpackPrefetch: true, webpackChunkName: \"DistrictStats\" */ './DistrictStatsNew'\n  )\n);\n\n// internal\nimport debounce from '../utils/debounce';\nimport { determineContestTitleYourRaces } from '../election-utils';\nimport { lookup } from '../utils/legislative-districts';\nimport {\n  createBallot,\n  filterDownBallotRaces,\n  filterLocalMeasures,\n  getLocalRaceTitle,\n  LOCAL_RACE_GROUPS,\n} from '../utils/branch-ballot';\nimport loadAssetURL from '../utils/load-asset-url';\n\nconst googleIMG = loadAssetURL('powered-by-google');\n\nlet PlacesLib = null; // { AutocompleteSessionToken, AutocompleteSuggestion, Place } loaded via importLibrary()\n\nconst bounds = {\n  east: -93.514764,\n  west: -106.662177,\n  south: 25.843902,\n  north: 36.500199,\n};\n\nconst toLocationRestriction = b => ({\n  west: b.west,\n  east: b.east,\n  south: b.south,\n  north: b.north,\n});\n\nconst getPredictions = async (input, sessionToken) => {\n  if (!input || input.trim().length < 2) return [];\n\n  const request = {\n    input,\n    locationRestriction: toLocationRestriction(bounds),\n    includedPrimaryTypes: ['street_address', 'premise', 'route'],\n    region: 'us',\n    sessionToken,\n  };\n\n  const {\n    suggestions,\n  } = await PlacesLib.AutocompleteSuggestion.fetchAutocompleteSuggestions(\n    request\n  );\n\n  return suggestions.map(s => ({\n    id: s.placePrediction.placeId,\n    description: s.placePrediction.text.toString(),\n    place_id: s.placePrediction.placeId,\n    _prediction: s.placePrediction,\n  }));\n};\n\n// always render what's provided, the geocoder decides\nconst shouldItemRender = () => true;\n\n// Place.location is a LatLng whose lat/lng are functions in some versions of\n// the Places library and plain numbers in others.\nconst toCoordinates = latLng => ({\n  latitude: typeof latLng.lat === 'function' ? latLng.lat() : latLng.lat,\n  longitude: typeof latLng.lng === 'function' ? latLng.lng() : latLng.lng,\n});\n\nclass YourRaces extends PureComponent {\n  constructor() {\n    super();\n\n    this.state = {\n      contests: [],\n      coordinates: null,\n      data: null,\n      lookupError: false,\n      lookupPending: false,\n      lookedFoundStored: false,\n      results: [],\n      value: '',\n      selectedPlaceId: null, // Chosen from the suggestions list; lookup runs on submit\n      bodyWidth: null,\n      width: null,\n      branchBallot: null, // Down-ballot local races/candidates from Branch\n      branchPending: false, // true from submit until Branch responds (or fails)\n      activeRaceFilters: [], // empty = \"All\" — show every race\n      raceSearchQuery: '',\n    };\n\n    this.handleGeocode = this.handleGeocode.bind(this);\n    this.debouncedHandleGeocode = debounce(this.handleGeocode, 300);\n    this.onChange = this.onChange.bind(this);\n    this.onClear = this.onClear.bind(this);\n    this.onSelect = this.onSelect.bind(this);\n    this.onSubmit = this.onSubmit.bind(this);\n    this.onJumpToAllRaces = this.onJumpToAllRaces.bind(this);\n    this.getContainerWidth = this.getContainerWidth.bind(this);\n    this.toggleRaceFilter = this.toggleRaceFilter.bind(this);\n    this.onRaceSearchChange = this.onRaceSearchChange.bind(this);\n    this.sessionToken = null;\n    this.branchRequestId = 0; // lets a stale Branch response be ignored\n    this.selectedPrediction = null; // _prediction for the selected suggestion, used at submit\n    this.branchPrefetch = null; // { placeId, promise } — Branch request started on selection\n  }\n\n  // Calculate responsive widths for the district map, based on browser size\n  getContainerWidth() {\n    const bodyWidth = window.innerWidth;\n    const width =\n      bodyWidth > 543 ? 220 : bodyWidth > 330 ? 280 : bodyWidth - 70;\n    this.setState({\n      width: width,\n      bodyWidth: bodyWidth,\n    });\n  }\n\n  // Clears the prefetched ZIP when a selection is invalidated, so a stale\n  // value from a previous address can't tag along on a later submission.\n  clearZip() {\n    const zipInput = document.getElementById('signup-zip');\n    if (zipInput) zipInput.value = '';\n  }\n\n  onClear(value) {\n    this.setState({ value: '', selectedPlaceId: null });\n    this.selectedPrediction = null;\n    this.clearZip();\n  }\n\n  // \"all\" is exclusive with every other filter\n  toggleRaceFilter(filter) {\n    this.setState(({ activeRaceFilters }) => {\n      if (filter === 'all') return { activeRaceFilters: [] };\n\n      const activeWithoutAll = activeRaceFilters.filter(f => f !== 'all');\n      const isActive = activeWithoutAll.includes(filter);\n\n      return {\n        activeRaceFilters: isActive\n          ? activeWithoutAll.filter(f => f !== filter)\n          : [...activeWithoutAll, filter],\n      };\n    });\n  }\n\n  onJumpToAllRaces(event) {\n    event.preventDefault();\n    const heading = document.getElementById('all-races__heading');\n    if (!heading) return;\n\n    heading.scrollIntoView({ behavior: 'smooth', block: 'start' });\n\n    const clearBodyOverflowLock = () => {\n      if (document.body.style.overflow) document.body.style.overflow = '';\n    };\n    if ('onscrollend' in window) {\n      window.addEventListener('scrollend', clearBodyOverflowLock, {\n        once: true,\n      });\n    } else {\n      setTimeout(clearBodyOverflowLock, 600);\n    }\n  }\n\n  onRaceSearchChange(value) {\n    this.setState({ raceSearchQuery: value });\n  }\n\n  onChange(value) {\n    this.setState(\n      { value, selectedPlaceId: null },\n      this.debouncedHandleGeocode\n    );\n    this.selectedPrediction = null;\n    this.clearZip();\n    // Start a new autocomplete session when the user begins typing\n    if (!this.sessionToken && PlacesLib) {\n      this.sessionToken = new PlacesLib.AutocompleteSessionToken();\n    }\n  }\n\n  async handleGeocode() {\n    if (!PlacesLib) return;\n    const { value: input } = this.state;\n    try {\n      const results = await getPredictions(input, this.sessionToken);\n      this.setState({ results });\n    } catch (e) {\n      this.setState({ results: [] });\n    }\n  }\n\n  onSelect({ name, placeId, _prediction }) {\n    this.setState({\n      value: name,\n      selectedPlaceId: placeId,\n      results: [],\n      lookupError: false,\n    });\n    this.selectedPrediction = _prediction;\n\n    this.prefetchSelectedPlace(placeId, _prediction);\n  }\n\n  // As soon as an address is picked (before the email/submit step), fetch its\n  // details once and use them for both the signup form's ZIP and a head start\n  // on the Branch request — so local races are usually ready by the time the\n  // reader submits.\n  prefetchSelectedPlace(placeId, prediction) {\n    if (!PlacesLib) return;\n\n    const placePromise = (async () => {\n      const place = prediction\n        ? prediction.toPlace()\n        : new PlacesLib.Place({ id: placeId });\n\n      await place.fetchFields({\n        fields: ['location', 'formattedAddress', 'addressComponents'],\n      });\n\n      return place;\n    })();\n\n    this.prefetchZip(placePromise);\n    this.branchPrefetch = {\n      placeId,\n      promise: this.prefetchBranchBallot(placePromise),\n    };\n  }\n\n  // Grabs the ZIP for the email signup form's hidden field\n  async prefetchZip(placePromise) {\n    const zipInput = document.getElementById('signup-zip');\n    if (!zipInput) return;\n\n    try {\n      const place = await placePromise;\n\n      const zipComponent = (place.addressComponents || []).find(component =>\n        component.types.includes('postal_code')\n      );\n      zipInput.value = zipComponent ? zipComponent.longText : '';\n    } catch (e) {\n      // Non-critical enhancement — leave the field blank if this fails.\n    }\n  }\n\n  // Resolves to the Branch ballot, or null if anything fails — never rejects,\n  // so an unused prefetch can't surface as an unhandled rejection. A null is\n  // retried from scratch on submit (see loadBranchBallot).\n  async prefetchBranchBallot(placePromise) {\n    try {\n      const place = await placePromise;\n\n      return await createBallot(\n        this.buildBranchLocation(place, toCoordinates(place.location))\n      );\n    } catch (e) {\n      console.warn('Branch prefetch failed', e);\n      return null;\n    }\n  }\n\n  // build the Branch location from an already-fetched (geocoded) Google Place\n  buildBranchLocation(place, coordinates) {\n    const components = place.addressComponents || [];\n    const findComponent = type => {\n      const match = components.find(c => c.types.includes(type));\n      return match ? match.longText : undefined;\n    };\n\n    const stateComponent = components.find(c =>\n      c.types.includes('administrative_area_level_1')\n    );\n\n    // Branch's schema types zip as an integer; omit it if Google didn't\n    // return a usable one.\n    const zip = parseInt(findComponent('postal_code'), 10);\n\n    return {\n      latitude: coordinates.latitude,\n      longitude: coordinates.longitude,\n      address: place.formattedAddress,\n      addressComponents: {\n        city: findComponent('locality'),\n        county: findComponent('administrative_area_level_2'),\n        state: stateComponent ? stateComponent.shortText : undefined,\n        zip: Number.isNaN(zip) ? undefined : zip,\n      },\n    };\n  }\n\n  // get down-ballot local races from Branch — reusing the request already\n  // started when this address was selected, if there is one.\n  async loadBranchBallot(place, coordinates, placeId) {\n    const requestId = ++this.branchRequestId;\n    let branchBallot = null;\n\n    try {\n      const prefetch = this.branchPrefetch;\n      if (prefetch && prefetch.placeId === placeId) {\n        branchBallot = await prefetch.promise;\n      }\n\n      // No usable prefetch (never started, or it failed) — ask now.\n      if (!branchBallot) {\n        await place.fetchFields({\n          fields: ['formattedAddress', 'addressComponents'],\n        });\n\n        branchBallot = await createBallot(\n          this.buildBranchLocation(place, coordinates)\n        );\n      }\n    } catch (e) {\n      console.warn('Branch ballot request failed', e);\n      branchBallot = null;\n    }\n\n    // A newer submit has replaced this one — drop the stale response.\n    if (requestId !== this.branchRequestId) return;\n\n    // Filter buttons only exist for groups that have races at this address, so\n    // drop any leftover filter from a previous address rather than strand it.\n    const localRaces = branchBallot\n      ? filterDownBallotRaces(branchBallot.races)\n      : [];\n    const emptyGroupKeys = LOCAL_RACE_GROUPS.filter(\n      group => !localRaces.some(group.matches)\n    ).map(group => group.key);\n    if (\n      !branchBallot ||\n      filterLocalMeasures(branchBallot.measures).length === 0\n    ) {\n      emptyGroupKeys.push('local-measures');\n    }\n\n    this.setState(({ activeRaceFilters }) => ({\n      branchBallot,\n      branchPending: false,\n      activeRaceFilters: activeRaceFilters.filter(\n        filter => !emptyGroupKeys.includes(filter)\n      ),\n    }));\n  }\n\n  // run the district lookup for whichever address was selected from the\n  // dropdown.\n  async onSubmit(event) {\n    event.preventDefault();\n\n    // Same native validation UI as the email field below — catches hitting\n    // Enter/submit with the address field left empty.\n    const addressInput = document.getElementById('address-input');\n    if (addressInput && !addressInput.checkValidity()) {\n      addressInput.reportValidity();\n      return;\n    }\n\n    const { selectedPlaceId } = this.state;\n    if (!selectedPlaceId) return;\n\n    // Email is mandatory to see personalized results — block here (with the\n    // browser's native validation UI) before running the district lookup.\n    const emailInput = document.getElementById('signup-email');\n    if (emailInput && !emailInput.checkValidity()) {\n      emailInput.reportValidity();\n      return;\n    }\n\n    // Clear the previous address's local races so they don't linger next to\n    // the new address's results while Branch is still responding.\n    this.setState({\n      lookupError: false,\n      lookupPending: true,\n      branchBallot: null,\n      branchPending: true,\n    });\n\n    try {\n      const place = this.selectedPrediction\n        ? this.selectedPrediction.toPlace()\n        : new PlacesLib.Place({ id: selectedPlaceId });\n\n      await place.fetchFields({ fields: ['location'] });\n\n      const coordinates = toCoordinates(place.location);\n\n      // Reset session so the next keystroke starts a fresh token\n      this.sessionToken = null;\n\n      lookup(coordinates)\n        .then(({ data }) => {\n          // The SBOE button is hidden when this address has no SBOE race, so\n          // don't leave its filter stuck on from a previous address.\n          const hasSboeRace =\n            data.sboe &&\n            this.props.contests.some(\n              contest =>\n                contest.office === 'State Board of Education' &&\n                contest.office_division === data.sboe.district\n            );\n\n          this.setState(({ activeRaceFilters }) => ({\n            coordinates,\n            data,\n            lookupPending: false,\n            lookedFoundStored: false,\n            activeRaceFilters: hasSboeRace\n              ? activeRaceFilters\n              : activeRaceFilters.filter(filter => filter !== 'education'),\n          }));\n        })\n        .catch(e => {\n          console.error('District lookup failed', { coordinates, error: e });\n          this.setState({\n            data: null,\n            lookupError: true,\n            lookupPending: false,\n          });\n        });\n\n      // Local races (Branch/VoterGuideOS)\n      this.loadBranchBallot(place, coordinates, selectedPlaceId);\n    } catch (e) {\n      console.error('Google place details failed', {\n        placeId: selectedPlaceId,\n        error: e,\n      });\n      this.setState({\n        data: null,\n        lookupError: true,\n        lookupPending: false,\n        branchPending: false,\n      });\n      this.sessionToken = null;\n    }\n  }\n\n  async componentDidMount() {\n    PlacesLib = await google.maps.importLibrary('places');\n\n    this.getContainerWidth();\n    window.addEventListener('resize', this.getContainerWidth);\n\n    // // If we ever wanted to show a default location, coordinates for Governor mansion in Austin\n    // let latitude = 30.2730665;\n    // let longitude = -97.74341629999999;\n    // let coordinates = { latitude, longitude };\n\n    // lookup(coordinates)\n    //   .then(({ data }) => {\n    //     this.setState({\n    //       coordinates,\n    //       data,\n    //       lookupPending: false,\n    //       lookedFoundStored: false,\n    //     });\n    //   })\n    //   .catch(() =>\n    //     this.setState({\n    //       data: null,\n    //       lookupError: true,\n    //       lookupPending: false,\n    //     })\n    //   );\n  }\n\n  componentWillUnmount() {\n    window.removeEventListener('resize', this.getContainerWidth);\n  }\n\n  render() {\n    const { contests, notes } = this.props;\n    const {\n      coordinates,\n      data,\n      lookupError,\n      lookupPending,\n      results,\n      value,\n      bodyWidth,\n      width,\n      activeRaceFilters,\n      raceSearchQuery,\n      branchBallot,\n      branchPending,\n    } = this.state;\n\n    const shouldShowRace = filter =>\n      activeRaceFilters.length === 0 || activeRaceFilters.includes(filter);\n\n    // Down-ballot races from Branch — arrive after the district lookup, so\n    // this is empty until then (or if Branch fails).\n    const localRaces = branchBallot\n      ? filterDownBallotRaces(branchBallot.races)\n      : [];\n    const localMeasures = branchBallot\n      ? filterLocalMeasures(branchBallot.measures)\n      : [];\n    const localRacesByGroup = {};\n    LOCAL_RACE_GROUPS.forEach(group => {\n      localRacesByGroup[group.key] = localRaces.filter(group.matches);\n    });\n\n    // Loose match\n    const normalizeForSearch = str =>\n      str.toLowerCase().replace(/[^a-z0-9]/g, '');\n\n    const raceSearchTerm = normalizeForSearch(raceSearchQuery.trim());\n    const matchesRaceSearch = title =>\n      !raceSearchTerm || normalizeForSearch(title).includes(raceSearchTerm);\n\n    const raceSearchTitles = data && {\n      'us-house': `U.S. House District ${data.us_house.district}`,\n      'tx-senate': `Texas Senate District ${data.tx_senate.district}`,\n      'tx-house': `Texas House District ${data.tx_house.district}`,\n      sboe: `State Board of Education District ${data.sboe.district}`,\n    };\n\n    // Local races and measures come from a separate (later) request, so they\n    // join the suggestions once Branch has responded.\n    const localRaceSearchItems = [\n      ...localRaces.map(race => ({\n        key: race._id,\n        title: getLocalRaceTitle(race),\n      })),\n      ...localMeasures.map(measure => ({\n        key: measure._id,\n        title: measure.title,\n      })),\n    ];\n\n    const raceSearchItems = raceSearchTitles && [\n      { key: 'us-house', title: raceSearchTitles['us-house'] },\n      { key: 'tx-senate', title: raceSearchTitles['tx-senate'] },\n      { key: 'tx-house', title: raceSearchTitles['tx-house'] },\n      { key: 'sboe', title: raceSearchTitles.sboe },\n      ...localRaceSearchItems,\n    ];\n\n    let addressFeedback = null;\n\n    const matches = {\n      'us-house': null,\n      sboe: null,\n      'tx-senate': null,\n      'tx-house': null,\n    };\n\n    const noteMatches = {\n      'us-house': null,\n      sboe: null,\n      'tx-senate': null,\n      'tx-house': null,\n    };\n\n    if (data) {\n      matches['us-house'] = contests.filter(\n        contest =>\n          contest.office === 'U.S. House' &&\n          contest.office_division === data.us_house.district\n      );\n\n      matches['sboe'] = contests.filter(\n        contest =>\n          contest.office === 'State Board of Education' &&\n          contest.office_division === data.sboe.district\n      );\n\n      matches['tx-senate'] = contests.filter(\n        contest =>\n          contest.office === 'Texas Senate' &&\n          contest.office_division === data.tx_senate.district\n      );\n\n      matches['tx-house'] = contests.filter(\n        contest =>\n          contest.office === 'Texas House' &&\n          contest.office_division === data.tx_house.district\n      );\n\n      noteMatches['us-house'] = notes.filter(\n        contest =>\n          contest.type === 'us-house-district-' + data.us_house.district\n      );\n\n      noteMatches['sboe'] = notes.filter(\n        contest =>\n          contest.type ===\n          'state-board-of-education-district-' + data.sboe.district\n      );\n\n      noteMatches['tx-senate'] = notes.filter(\n        contest =>\n          contest.type === 'texas-senate-district-' + data.tx_senate.district\n      );\n\n      noteMatches['tx-house'] = notes.filter(\n        contest =>\n          contest.type === 'texas-house-district-' + data.tx_house.district\n      );\n    }\n\n    // Counts shown in the filter buttons below — a seat with no match (e.g.\n    // \"not up for election this year\") doesn't count as a race.\n    const raceCounts = data && {\n      'us-house': matches['us-house'].length > 0 ? 1 : 0,\n      'state-legislature':\n        (matches['tx-senate'].length > 0 ? 1 : 0) +\n        (matches['tx-house'].length > 0 ? 1 : 0),\n      education: matches['sboe'].length > 0 ? 1 : 0,\n    };\n    if (raceCounts) {\n      LOCAL_RACE_GROUPS.forEach(group => {\n        raceCounts[group.key] = localRacesByGroup[group.key].length;\n      });\n      raceCounts['local-measures'] = localMeasures.length;\n      raceCounts.all =\n        raceCounts['us-house'] +\n        raceCounts['state-legislature'] +\n        raceCounts.education +\n        LOCAL_RACE_GROUPS.reduce(\n          (total, group) => total + raceCounts[group.key],\n          0\n        ) +\n        raceCounts['local-measures'];\n    }\n\n    // Narrows local items to the race search. A title typed (or picked from\n    // the suggestions) exactly wins over partial matches, so picking\n    // \"…Post 1\" doesn't also pull in Posts 10 through 15.\n    const matchLocalSearch = (items, getTitle) => {\n      if (!raceSearchTerm) return items;\n\n      const exactMatches = items.filter(\n        item => normalizeForSearch(getTitle(item)) === raceSearchTerm\n      );\n\n      return exactMatches.length > 0\n        ? exactMatches\n        : items.filter(item => matchesRaceSearch(getTitle(item)));\n    };\n\n    // Local races that pass the active filters (county, city, education,\n    // judicial) and the search\n    const shownLocalRaces = matchLocalSearch(\n      [].concat(\n        ...LOCAL_RACE_GROUPS.filter(group => shouldShowRace(group.key)).map(\n          group => localRacesByGroup[group.key]\n        )\n      ),\n      getLocalRaceTitle\n    );\n    const shownLocalMeasures = matchLocalSearch(\n      shouldShowRace('local-measures') ? localMeasures : [],\n      measure => measure.title\n    );\n\n    // \"Showing X of Y races\" below the search bar — a seat with no match\n    // (not up for election this year) is hidden entirely, so it shouldn't\n    // count toward either number.\n    const raceSlotCategories = {\n      'us-house': 'us-house',\n      'tx-senate': 'state-legislature',\n      'tx-house': 'state-legislature',\n      sboe: 'education',\n    };\n    const totalRaceSlots = data\n      ? Object.keys(raceSlotCategories).filter(slug => matches[slug].length > 0)\n          .length +\n        localRaces.length +\n        localMeasures.length\n      : 0;\n    const visibleRaceSlots = data\n      ? Object.keys(raceSlotCategories).filter(\n          slug =>\n            matches[slug].length > 0 &&\n            shouldShowRace(raceSlotCategories[slug]) &&\n            matchesRaceSearch(raceSearchTitles[slug])\n        ).length +\n        shownLocalRaces.length +\n        shownLocalMeasures.length\n      : 0;\n\n    if (lookupPending) {\n      addressFeedback = (\n        <p class=\"has-padding t-serif t-weight-bold t-align-center\">\n          Finding your details...{' '}\n          <svg class=\"icon icon-spinner animate-pulse\">\n            <use xlinkHref=\"#icon-spinner\" />\n          </svg>\n        </p>\n      );\n    }\n\n    if (lookupError) {\n      addressFeedback = (\n        <p class=\"has-padding t-serif t-weight-bold t-align-center\">\n          Hmm... we were unable to find you in Texas. Please check your address\n          and try again!\n        </p>\n      );\n    }\n\n    if (coordinates && !lookupPending && !lookupError) {\n      addressFeedback = (\n        <p class=\"has-padding t-serif t-weight-bold t-align-center\">\n          We found your information! These races have been personalized for you.{' '}\n          <br></br>\n          <br></br>\n          <span class=\"t-weight-normal\">\n            Scroll down to the <a href=\"#all-races__heading\">all races</a>{' '}\n            section to see the federal and statewide candidates on every Texan's\n            ballot.\n          </span>\n        </p>\n      );\n    }\n\n    const inputProps = {\n      id: 'address-input',\n      class: 'address-input__input',\n      placeholder: '1010 Colorado St, Austin, TX, 78701',\n      required: true,\n    };\n\n    return (\n      <form\n        id=\"address-form\"\n        class=\"address-input t-sans\"\n        onSubmit={this.onSubmit}\n      >\n        <svg class=\"icon icon-drawn-left-arrow\">\n          <use xlinkHref=\"#icon-drawn-left-arrow\"></use>\n        </svg>\n        <label class=\"address-input__label\" for=\"address-input\">\n          Enter your address\n        </label>\n\n        <Typeahead\n          inputProps={inputProps}\n          items={results}\n          getItemValue={item => ({\n            name: item.description,\n            placeId: item.place_id,\n            _prediction: item._prediction,\n          })}\n          value={value}\n          onChange={this.onChange}\n          onClear={this.onClear}\n          onSelect={this.onSelect}\n          renderItem={(item, isHighlighted) => (\n            <li\n              class={cx('listbox__item', {\n                'listbox__item--highlighted': isHighlighted,\n              })}\n              key={item.id}\n            >\n              {item.description}\n            </li>\n          )}\n          renderAttribution={() => (\n            <li class=\"listbox__item listbox__item--attribution\">\n              <img src={googleIMG} alt=\"Powered by Google\" />\n            </li>\n          )}\n          shouldItemRender={shouldItemRender}\n          renderInput={props => (\n            <input\n              {...props}\n              ref={el => {\n                props.ref(el);\n                this.inputRef = el;\n              }}\n            />\n          )}\n        />\n        <p class=\"address-input__subhead\">We never sell your information.</p>\n\n        <Portal node={document.getElementById('address-submit')}>\n          <div>\n            <button\n              type=\"submit\"\n              ref={el => el && el.setAttribute('form', 'address-form')}\n              class=\"button button--yellow address-input__submit\"\n            >\n              See my ballot\n            </button>\n            <a\n              href=\"#all-races__heading\"\n              class=\"address-input__jump-link t-links-unset\"\n              onClick={this.onJumpToAllRaces}\n            >\n              Or, jump to all races\n            </a>\n          </div>\n        </Portal>\n\n        <Portal node={document.getElementById('your-address-feedback')}>\n          {addressFeedback}\n        </Portal>\n\n        {data && data.counties && (\n          <Portal node={document.getElementById('local-candidates-info')}>\n            <span>\n              <CountyInfo\n                key={data.counties.fips}\n                county={data.counties.name}\n                fips={data.counties.fips}\n              />\n            </span>\n          </Portal>\n        )}\n\n        {data && contests.length > 0 && (\n          <Portal\n            node={document.getElementById('your-races-results')}\n            ref={ref => (this._resultsPortal = ref)}\n          >\n            <div>\n              <div\n                class=\"your-races-filter\"\n                role=\"group\"\n                aria-label=\"Filter your races\"\n              >\n                <button\n                  type=\"button\"\n                  class={cx('your-races-filter__btn', {\n                    'is-active': activeRaceFilters.length === 0,\n                  })}\n                  onClick={() => this.toggleRaceFilter('all')}\n                >\n                  All ({raceCounts.all})\n                </button>\n                <button\n                  type=\"button\"\n                  class={cx('your-races-filter__btn', {\n                    'is-active': activeRaceFilters.includes('us-house'),\n                  })}\n                  onClick={() => this.toggleRaceFilter('us-house')}\n                >\n                  U.S. House ({raceCounts['us-house']})\n                </button>\n                <button\n                  type=\"button\"\n                  class={cx('your-races-filter__btn', {\n                    'is-active': activeRaceFilters.includes(\n                      'state-legislature'\n                    ),\n                  })}\n                  onClick={() => this.toggleRaceFilter('state-legislature')}\n                >\n                  State Legislature ({raceCounts['state-legislature']})\n                </button>\n                {/* Only some SBOE districts are on the ballot each cycle */}\n                {raceCounts.education > 0 && (\n                  <button\n                    type=\"button\"\n                    class={cx('your-races-filter__btn', {\n                      'is-active': activeRaceFilters.includes('education'),\n                    })}\n                    onClick={() => this.toggleRaceFilter('education')}\n                  >\n                    SBOE ({raceCounts.education})\n                  </button>\n                )}\n                {/* Faded placeholder while Branch is still responding; swapped\n                for the real local buttons below once it has. */}\n                {branchPending && (\n                  <button type=\"button\" class=\"your-races-filter__btn\" disabled>\n                    Local\n                  </button>\n                )}\n                {/* Only offered once Branch has responded, and only for groups\n                that have races at this address. */}\n                {!branchPending &&\n                  LOCAL_RACE_GROUPS.filter(\n                    group => raceCounts[group.key] > 0\n                  ).map(group => (\n                    <button\n                      type=\"button\"\n                      class={cx('your-races-filter__btn', {\n                        'is-active': activeRaceFilters.includes(group.key),\n                      })}\n                      onClick={() => this.toggleRaceFilter(group.key)}\n                    >\n                      {group.label} ({raceCounts[group.key]})\n                    </button>\n                  ))}\n                {!branchPending && raceCounts['local-measures'] > 0 && (\n                  <button\n                    type=\"button\"\n                    class={cx('your-races-filter__btn', {\n                      'is-active': activeRaceFilters.includes('local-measures'),\n                    })}\n                    onClick={() => this.toggleRaceFilter('local-measures')}\n                  >\n                    Local: Measures ({raceCounts['local-measures']})\n                  </button>\n                )}\n              </div>\n              <div class=\"your-races-search-bar\" role=\"search\">\n                <label\n                  class=\"your-races-search-bar__label\"\n                  for=\"your-races-search\"\n                ></label>\n                <Typeahead\n                  inputProps={{\n                    id: 'your-races-search',\n                    type: 'search',\n                    class: 'your-races-search-bar__input',\n                    placeholder: 'Filter by district or race',\n                  }}\n                  items={raceSearchItems}\n                  value={raceSearchQuery}\n                  getItemValue={item => item.title}\n                  onChange={this.onRaceSearchChange}\n                  onClear={() => this.onRaceSearchChange('')}\n                  onSelect={value => this.onRaceSearchChange(value)}\n                  shouldItemRender={(item, query) =>\n                    normalizeForSearch(item.title).includes(\n                      normalizeForSearch(query)\n                    )\n                  }\n                  renderItem={(item, isHighlighted) => (\n                    <li\n                      class={cx('listbox__item', {\n                        'listbox__item--highlighted': isHighlighted,\n                      })}\n                      key={item.key}\n                    >\n                      {item.title}\n                    </li>\n                  )}\n                  renderAttribution={() => null}\n                />\n              </div>\n              {data && (\n                <p class=\"your-races-results-count\">\n                  Showing <strong>{visibleRaceSlots}</strong> of{' '}\n                  <strong>{totalRaceSlots}</strong> races.\n                </p>\n              )}\n              <div class=\"representative-districts contest-list\">\n                {shouldShowRace('us-house') &&\n                  matchesRaceSearch(raceSearchTitles['us-house']) && (\n                    <Contest\n                      key={matches['us-house'][0].office_slug}\n                      contest={matches['us-house']}\n                      contestTitle={determineContestTitleYourRaces(\n                        matches['us-house'][0]\n                      )}\n                      notes={noteMatches['us-house'].filter(\n                        item => item.type === matches['us-house'][0].office_slug\n                      )}\n                      redistrictingNote\n                      tableHeader={CandidateRow.Header}\n                      columnCount={CandidateRow.columnCount}\n                      renderParty={party => (\n                        <SeatPartyDivider\n                          partyName={party.party}\n                          partyBallot={party}\n                          tableHeader={CandidateRow.Header}\n                          notes={noteMatches['us-house'].filter(\n                            contest =>\n                              contest.type ===\n                              party.office_slug + '-' + party.party\n                          )}\n                          columnCount={CandidateRow.columnCount}\n                          renderCandidate={(candidate, idx) => (\n                            <CandidateRow\n                              key={candidate.id}\n                              ballotName={candidate.name}\n                              candidateId={candidate.id}\n                              isIncumbent={candidate.is_incumbent}\n                              party={candidate.party}\n                            />\n                          )}\n                        />\n                      )}\n                    >\n                      <DistrictInfo>\n                        <AsyncDistrictStats\n                          name=\"U.S. House\"\n                          district={data['us_house'].district}\n                          slug=\"us-house\"\n                          width={width}\n                        />\n                        <AsyncDistrictMap\n                          slug=\"us-house\"\n                          district={data['us_house'].district}\n                          point={coordinates}\n                          width={width}\n                        />\n                      </DistrictInfo>\n                    </Contest>\n                  )}\n                {shouldShowRace('state-legislature') &&\n                  matchesRaceSearch(raceSearchTitles['tx-senate']) &&\n                  matches['tx-senate'].length > 0 && (\n                    <Contest\n                      key={matches['tx-senate'].id}\n                      contest={matches['tx-senate']}\n                      tableHeader={CandidateRow.Header}\n                      columnCount={CandidateRow.columnCount}\n                      notes={noteMatches['tx-senate'].filter(\n                        item =>\n                          item.type === matches['tx-senate'][0].office_slug\n                      )}\n                      contestTitle={determineContestTitleYourRaces(\n                        matches['tx-senate'][0]\n                      )}\n                      renderParty={party => (\n                        <SeatPartyDivider\n                          partyName={party.party}\n                          partyBallot={party}\n                          tableHeader={CandidateRow.Header}\n                          notes={noteMatches['tx-senate'].filter(\n                            contest =>\n                              contest.type ===\n                              party.office_slug + '-' + party.party\n                          )}\n                          columnCount={CandidateRow.columnCount}\n                          renderCandidate={(candidate, idx) => (\n                            <CandidateRow\n                              key={candidate.id}\n                              ballotName={candidate.name}\n                              candidateId={candidate.id}\n                              isIncumbent={candidate.is_incumbent}\n                              party={candidate.party}\n                            />\n                          )}\n                        />\n                      )}\n                    >\n                      <DistrictInfo>\n                        <AsyncDistrictStats\n                          name=\"Texas Senate\"\n                          district={data['tx_senate'].district}\n                          slug=\"texas-senate\"\n                          width={width}\n                        />\n                        <AsyncDistrictMap\n                          slug=\"texas-senate\"\n                          district={data['tx_senate'].district}\n                          point={coordinates}\n                          width={width}\n                        />\n                      </DistrictInfo>\n                    </Contest>\n                  )}\n                {shouldShowRace('state-legislature') &&\n                  matchesRaceSearch(raceSearchTitles['tx-house']) && (\n                    <Contest\n                      key={matches['tx-house'].id}\n                      contest={matches['tx-house']}\n                      tableHeader={CandidateRow.Header}\n                      columnCount={CandidateRow.columnCount}\n                      notes={noteMatches['tx-house'].filter(\n                        item => item.type === matches['tx-house'][0].office_slug\n                      )}\n                      contestTitle={determineContestTitleYourRaces(\n                        matches['tx-house'][0]\n                      )}\n                      renderParty={party => (\n                        <SeatPartyDivider\n                          partyName={party.party}\n                          partyBallot={party}\n                          tableHeader={CandidateRow.Header}\n                          notes={noteMatches['tx-house'].filter(\n                            contest =>\n                              contest.type ===\n                              party.office_slug + '-' + party.party\n                          )}\n                          columnCount={CandidateRow.columnCount}\n                          renderCandidate={(candidate, idx) => (\n                            <CandidateRow\n                              key={candidate.id}\n                              ballotName={candidate.name}\n                              candidateId={candidate.id}\n                              isIncumbent={candidate.is_incumbent}\n                              party={candidate.party}\n                            />\n                          )}\n                        />\n                      )}\n                    >\n                      <DistrictInfo>\n                        <AsyncDistrictStats\n                          name=\"Texas House\"\n                          district={data['tx_house'].district}\n                          slug=\"texas-house\"\n                          width={width}\n                        />\n                        <AsyncDistrictMap\n                          slug=\"texas-house\"\n                          district={data['tx_house'].district}\n                          point={coordinates}\n                          width={width}\n                        />\n                      </DistrictInfo>\n                    </Contest>\n                  )}\n                {shouldShowRace('education') &&\n                  matchesRaceSearch(raceSearchTitles['sboe']) &&\n                  matches['sboe'].length > 0 && (\n                    <Contest\n                      key={matches['sboe'][0].office_slug}\n                      contest={matches['sboe']}\n                      tableHeader={CandidateRow.Header}\n                      columnCount={CandidateRow.columnCount}\n                      notes={noteMatches['sboe'].filter(\n                        item => item.type === matches['sboe'][0].office_slug\n                      )}\n                      contestTitle={determineContestTitleYourRaces(\n                        matches['sboe'][0]\n                      )}\n                      renderParty={party => (\n                        <SeatPartyDivider\n                          partyName={party.party}\n                          partyBallot={party}\n                          tableHeader={CandidateRow.Header}\n                          notes={noteMatches['sboe'].filter(\n                            contest =>\n                              contest.type ===\n                              party.office_slug + '-' + party.party\n                          )}\n                          columnCount={CandidateRow.columnCount}\n                          renderCandidate={(candidate, idx) => (\n                            <CandidateRow\n                              key={candidate.id}\n                              ballotName={candidate.name}\n                              candidateId={candidate.id}\n                              isIncumbent={candidate.is_incumbent}\n                              party={candidate.party}\n                            />\n                          )}\n                        />\n                      )}\n                    >\n                      <DistrictInfo>\n                        <AsyncDistrictStats\n                          name=\"State Board Of Education\"\n                          district={data['sboe'].district}\n                          slug=\"state-board-of-education\"\n                          width={width}\n                        />\n                        <AsyncDistrictMap\n                          slug=\"state-board-of-education\"\n                          district={data['sboe'].district}\n                          point={coordinates}\n                          width={width}\n                        />\n                      </DistrictInfo>\n                    </Contest>\n                  )}\n              </div>\n            </div>\n          </Portal>\n        )}\n\n        {/* Local races (Branch/VoterGuideOS).\n        Own Portal, own DOM node (still inside the gray\n        .container-gray-two/.results-container-map box, alongside\n        your-races-results) — kept structurally separate from the top-race\n        Contest blocks above so a rendering failure here can never affect\n        them, same isolation principle as loadBranchBallot. */}\n        {branchBallot &&\n          (LOCAL_RACE_GROUPS.some(group => shouldShowRace(group.key)) ||\n            shouldShowRace('local-measures')) &&\n          // A search that matches no local race shouldn't leave the \"isn't\n          // fully available\" message behind\n          (!raceSearchTerm ||\n            shownLocalRaces.length + shownLocalMeasures.length > 0) && (\n            <Portal node={document.getElementById('local-races-results')}>\n              <LocalRaces\n                races={shownLocalRaces}\n                measures={shownLocalMeasures}\n                resetKey={branchBallot}\n              />\n            </Portal>\n          )}\n\n        {/* Rendered into its own node below #local-races-results so the note\n        reads as the footer of the whole gray box (top races, then local\n        races), rather than sitting between them. */}\n        {data && contests.length > 0 && (\n          <Portal node={document.getElementById('your-races-data-note')}>\n            <div class=\"your-races-data-note\">\n              <h3 class=\"your-races-data-note__title\">About the data</h3>\n              <p class=\"your-races-data-note__text\">\n                Demographic data and the 2024 general presidential results are\n                from the{' '}\n                <a\n                  href=\"https://data.capitol.texas.gov/organization/eb7dd023-f166-4613-92ff-b6b3d5c026c6?groups=redistricting\"\n                  target=\"_blank\"\n                >\n                  Texas Legislative Council\n                </a>\n                . Data on local races and measures is from VoterGuideOS. Local\n                races are only available for the 50 most populous counties in\n                Texas.\n              </p>\n            </div>\n          </Portal>\n        )}\n      </form>\n    );\n  }\n}\n\nexport default YourRaces;\n","/**\n * Grabs the contents of a `jsonScript` created JSON inline string and returns\n * it as a JSON object. If the element does not exist, or if the script\n * element does not have the JSON MIME type, null is returned instead.\n *\n * @param  {String} elementId the ID of the JSON script element\n * @return {Object|null}\n */\nexport default function loadAssetURL(elementId) {\n  const element = document.getElementById(elementId);\n\n  if (element && element.getAttribute('type') === 'application/json') {\n    return JSON.parse(element.textContent).asset_url;\n  } else {\n    return null;\n  }\n}\n","import getJSON from './get-json';\n\nconst LOOKUP_URL = ({ latitude, longitude, includeGeography = false }) =>\n  `https://dv-dev.texastribune.org/legislative-lookup-2025/?latitude=${latitude}&longitude=${longitude}`;\n\nexport function lookup({ latitude, longitude }) {\n  return getJSON(LOOKUP_URL({ latitude, longitude }));\n}\n","import cx from 'classnames';\nimport { h } from 'preact';\n\nfunction Ad() {\n  const classes = cx('c-ad-flex_bg--gray preact__ad');\n\n  return (\n    <div class=\"plugin plugin--centered\">\n      <div class={classes}>\n        <div class=\"c-ad-flex__inner\">\n          <p class=\"c-ad-flex__thanks\">\n            The Texas Tribune thanks its sponsors.\n            <a href=\"https://mediakit.texastribune.org/\">\n              <strong>Become one</strong>\n            </a>\n            .\n          </p>\n          <div class=\"c-ad-flex__unit\">\n            <div class=\"dv-gpt-ad\"></div>\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n\nexport default Ad;\n","// packages\nimport cx from 'classnames';\nimport { Component, h } from 'preact';\n\n// components\nimport CandidateRow from './components/CandidateRow';\nimport Contest from './components/Contest';\nimport YourRaces from './components/YourRaces';\nimport Portal from './components/Portal';\nimport SeatPartyDivider from './components/SeatPartyDivider';\nimport Ad from './components/Ad';\n\nimport {\n  determineContestTitle,\n  chunk,\n  dropDuplicateSpecials,\n} from './election-utils';\nimport { FLAT_BALLOT_URL } from './endpoints';\nimport getJSON from './utils/get-json';\n\ntype State = {\n  data: { [key: string]: any };\n};\n\nclass App extends Component<{}, State> {\n  constructor() {\n    super();\n\n    this.state = {\n      data: [],\n    };\n\n    this.fetchData = this.fetchData.bind(this);\n  }\n\n  fetchData() {\n    getJSON(FLAT_BALLOT_URL).then(data =>\n      this.setState({ data: dropDuplicateSpecials(data) })\n    );\n  }\n\n  componentDidMount() {\n    this.fetchData();\n  }\n\n  componentWillUnmount() {}\n\n  componentDidUpdate() {}\n\n  render() {\n    const { notes } = this.props;\n    const { data } = this.state;\n\n    const seats_mapped = data.map(number => ({\n      office: number.office,\n      office_slug: number.office_slug,\n    }));\n\n    function unique(array, propertyName) {\n      return array.filter(\n        (e, i) =>\n          array.findIndex(a => a[propertyName] === e[propertyName]) === i\n      );\n    }\n\n    let unique_seats = unique(seats_mapped, 'office_slug');\n\n    const texasHouse = unique_seats.filter(\n      contest => contest.office === 'Texas House'\n    );\n\n    const usHouse = unique_seats.filter(\n      contest => contest.office === 'U.S. House'\n    );\n\n    let texasHouseGroups, usHouseGroups;\n\n    if (texasHouse.length) {\n      texasHouseGroups = chunk(texasHouse, 30);\n      usHouseGroups = chunk(usHouse, 24);\n    }\n\n    return (\n      <div class=\"ballot-list\">\n        <Portal\n          node={document.getElementById('lookup-select')}\n          ref={ref => (this._yourPortal = ref)}\n        >\n          <YourRaces contests={data} notes={notes} />\n        </Portal>\n\n        <Portal\n          node={document.querySelector('#us-house .contests')}\n          ref={ref => (this._usPortal = ref)}\n        >\n          <div class=\"office__contests\">\n            {usHouse.length > 0 &&\n              usHouseGroups.map(contestGroup => (\n                <div class=\"contest-group\">\n                  <div class=\"seat__contests-double\">\n                    {contestGroup.map(contest => (\n                      <Contest\n                        key={contest.id}\n                        contest={data.filter(\n                          item => item.office_slug === contest.office_slug\n                        )}\n                        tableHeader={CandidateRow.Header}\n                        columnCount={CandidateRow.columnCount}\n                        notes={notes.filter(\n                          item => item.type === contest.office_slug\n                        )}\n                        contestTitle={determineContestTitle(\n                          data.filter(\n                            item => item.office_slug === contest.office_slug\n                          )[0]\n                        )}\n                        renderParty={party => (\n                          <SeatPartyDivider\n                            partyName={party.party}\n                            partyBallot={party}\n                            tableHeader={CandidateRow.Header}\n                            notes={notes.filter(\n                              item =>\n                                item.type ===\n                                contest.office_slug + '-' + party.party\n                            )}\n                            columnCount={CandidateRow.columnCount}\n                            renderCandidate={(candidate, idx) => (\n                              <CandidateRow\n                                key={candidate.id}\n                                ballotName={candidate.name}\n                                candidateId={candidate.id}\n                                isIncumbent={candidate.is_incumbent}\n                                party={candidate.party}\n                              />\n                            )}\n                          />\n                        )}\n                      />\n                    ))}\n                  </div>\n                  <Ad />\n                </div>\n              ))}\n          </div>\n        </Portal>\n\n        <Portal\n          node={document.querySelector('#governor .contests')}\n          ref={ref => (this._supremePortal = ref)}\n        >\n          <div class=\"office__contests\">\n            {unique_seats\n              .filter(contest => contest.office === 'Governor')\n              .map(contest => (\n                <Contest\n                  key={contest.id}\n                  contest={data.filter(\n                    item => item.office_slug === contest.office_slug\n                  )}\n                  notes={notes.filter(\n                    item => item.type === contest.office_slug\n                  )}\n                  isShowcaseRace\n                  tableHeader={CandidateRow.Header}\n                  columnCount={CandidateRow.columnCount}\n                  contestTitle={determineContestTitle(\n                    data.filter(\n                      item => item.office_slug === contest.office_slug\n                    )[0]\n                  )}\n                  renderParty={party => (\n                    <SeatPartyDivider\n                      partyName={party.party}\n                      partyBallot={party}\n                      tableHeader={CandidateRow.Header}\n                      notes={notes.filter(\n                        item =>\n                          item.type === contest.office_slug + '-' + party.party\n                      )}\n                      columnCount={CandidateRow.columnCount}\n                      renderCandidate={(candidate, idx) => (\n                        <CandidateRow\n                          key={candidate.id}\n                          ballotName={candidate.name}\n                          candidateId={candidate.id}\n                          isIncumbent={candidate.is_incumbent}\n                          party={candidate.party}\n                        />\n                      )}\n                    />\n                  )}\n                />\n              ))}\n          </div>\n        </Portal>\n        <Portal\n          node={document.querySelector('#lieutenant-governor .contests')}\n          ref={ref => (this._supremePortal = ref)}\n        >\n          <div class=\"office__contests\">\n            {unique_seats\n              .filter(contest => contest.office === 'Lieutenant Governor')\n              .map(contest => (\n                <Contest\n                  key={contest.id}\n                  contest={data.filter(\n                    item => item.office_slug === contest.office_slug\n                  )}\n                  notes={notes.filter(\n                    item => item.type === contest.office_slug\n                  )}\n                  isShowcaseRace\n                  tableHeader={CandidateRow.Header}\n                  columnCount={CandidateRow.columnCount}\n                  contestTitle={determineContestTitle(\n                    data.filter(\n                      item => item.office_slug === contest.office_slug\n                    )[0]\n                  )}\n                  renderParty={party => (\n                    <SeatPartyDivider\n                      partyName={party.party}\n                      partyBallot={party}\n                      tableHeader={CandidateRow.Header}\n                      notes={notes.filter(\n                        item =>\n                          item.type === contest.office_slug + '-' + party.party\n                      )}\n                      columnCount={CandidateRow.columnCount}\n                      renderCandidate={(candidate, idx) => (\n                        <CandidateRow\n                          key={candidate.id}\n                          ballotName={candidate.name}\n                          candidateId={candidate.id}\n                          isIncumbent={candidate.is_incumbent}\n                          party={candidate.party}\n                        />\n                      )}\n                    />\n                  )}\n                />\n              ))}\n          </div>\n        </Portal>\n        <Portal\n          node={document.querySelector('#attorney-general .contests')}\n          ref={ref => (this._supremePortal = ref)}\n        >\n          <div class=\"office__contests\">\n            {unique_seats\n              .filter(contest => contest.office === 'Attorney General')\n              .map(contest => (\n                <Contest\n                  key={contest.id}\n                  contest={data.filter(\n                    item => item.office_slug === contest.office_slug\n                  )}\n                  notes={notes.filter(\n                    item => item.type === contest.office_slug\n                  )}\n                  isShowcaseRace\n                  tableHeader={CandidateRow.Header}\n                  columnCount={CandidateRow.columnCount}\n                  contestTitle={determineContestTitle(\n                    data.filter(\n                      item => item.office_slug === contest.office_slug\n                    )[0]\n                  )}\n                  renderParty={party => (\n                    <SeatPartyDivider\n                      partyName={party.party}\n                      partyBallot={party}\n                      tableHeader={CandidateRow.Header}\n                      notes={notes.filter(\n                        item =>\n                          item.type === contest.office_slug + '-' + party.party\n                      )}\n                      columnCount={CandidateRow.columnCount}\n                      renderCandidate={(candidate, idx) => (\n                        <CandidateRow\n                          key={candidate.id}\n                          ballotName={candidate.name}\n                          candidateId={candidate.id}\n                          isIncumbent={candidate.is_incumbent}\n                          party={candidate.party}\n                        />\n                      )}\n                    />\n                  )}\n                />\n              ))}\n          </div>\n        </Portal>\n        <Portal\n          node={document.querySelector('#land-commissioner .contests')}\n          ref={ref => (this._supremePortal = ref)}\n        >\n          <div class=\"office__contests\">\n            {unique_seats\n              .filter(contest => contest.office === 'Land Commissioner')\n              .map(contest => (\n                <Contest\n                  key={contest.id}\n                  contest={data.filter(\n                    item => item.office_slug === contest.office_slug\n                  )}\n                  notes={notes.filter(\n                    item => item.type === contest.office_slug\n                  )}\n                  isShowcaseRace\n                  tableHeader={CandidateRow.Header}\n                  columnCount={CandidateRow.columnCount}\n                  contestTitle={determineContestTitle(\n                    data.filter(\n                      item => item.office_slug === contest.office_slug\n                    )[0]\n                  )}\n                  renderParty={party => (\n                    <SeatPartyDivider\n                      partyName={party.party}\n                      partyBallot={party}\n                      tableHeader={CandidateRow.Header}\n                      notes={notes.filter(\n                        item =>\n                          item.type === contest.office_slug + '-' + party.party\n                      )}\n                      columnCount={CandidateRow.columnCount}\n                      renderCandidate={(candidate, idx) => (\n                        <CandidateRow\n                          key={candidate.id}\n                          ballotName={candidate.name}\n                          candidateId={candidate.id}\n                          isIncumbent={candidate.is_incumbent}\n                          party={candidate.party}\n                        />\n                      )}\n                    />\n                  )}\n                />\n              ))}\n          </div>\n        </Portal>\n        <Portal\n          node={document.querySelector('#comptroller .contests')}\n          ref={ref => (this._supremePortal = ref)}\n        >\n          <div class=\"office__contests\">\n            {unique_seats\n              .filter(contest => contest.office === 'Comptroller')\n              .map(contest => (\n                <Contest\n                  key={contest.id}\n                  contest={data.filter(\n                    item => item.office_slug === contest.office_slug\n                  )}\n                  notes={notes.filter(\n                    item => item.type === contest.office_slug\n                  )}\n                  isShowcaseRace\n                  tableHeader={CandidateRow.Header}\n                  columnCount={CandidateRow.columnCount}\n                  contestTitle={determineContestTitle(\n                    data.filter(\n                      item => item.office_slug === contest.office_slug\n                    )[0]\n                  )}\n                  renderParty={party => (\n                    <SeatPartyDivider\n                      partyName={party.party}\n                      partyBallot={party}\n                      tableHeader={CandidateRow.Header}\n                      notes={notes.filter(\n                        item =>\n                          item.type === contest.office_slug + '-' + party.party\n                      )}\n                      columnCount={CandidateRow.columnCount}\n                      renderCandidate={(candidate, idx) => (\n                        <CandidateRow\n                          key={candidate.id}\n                          ballotName={candidate.name}\n                          candidateId={candidate.id}\n                          isIncumbent={candidate.is_incumbent}\n                          party={candidate.party}\n                        />\n                      )}\n                    />\n                  )}\n                />\n              ))}\n          </div>\n        </Portal>\n        <Portal\n          node={document.querySelector('#agriculture-commissioner .contests')}\n          ref={ref => (this._supremePortal = ref)}\n        >\n          <div class=\"office__contests\">\n            {unique_seats\n              .filter(contest => contest.office === 'Agriculture Commissioner')\n              .map(contest => (\n                <Contest\n                  key={contest.id}\n                  contest={data.filter(\n                    item => item.office_slug === contest.office_slug\n                  )}\n                  notes={notes.filter(\n                    item => item.type === contest.office_slug\n                  )}\n                  isShowcaseRace\n                  tableHeader={CandidateRow.Header}\n                  columnCount={CandidateRow.columnCount}\n                  contestTitle={determineContestTitle(\n                    data.filter(\n                      item => item.office_slug === contest.office_slug\n                    )[0]\n                  )}\n                  renderParty={party => (\n                    <SeatPartyDivider\n                      partyName={party.party}\n                      partyBallot={party}\n                      tableHeader={CandidateRow.Header}\n                      notes={notes.filter(\n                        item =>\n                          item.type === contest.office_slug + '-' + party.party\n                      )}\n                      columnCount={CandidateRow.columnCount}\n                      renderCandidate={(candidate, idx) => (\n                        <CandidateRow\n                          key={candidate.id}\n                          ballotName={candidate.name}\n                          candidateId={candidate.id}\n                          isIncumbent={candidate.is_incumbent}\n                          party={candidate.party}\n                        />\n                      )}\n                    />\n                  )}\n                />\n              ))}\n          </div>\n        </Portal>\n        <Portal\n          node={document.querySelector('#us-senate .contests')}\n          ref={ref => (this._supremePortal = ref)}\n        >\n          <div class=\"office__contests\">\n            {unique_seats\n              .filter(contest => contest.office === 'U.S. Senate')\n              .map(contest => (\n                <Contest\n                  key={contest.id}\n                  contest={data.filter(\n                    item => item.office_slug === contest.office_slug\n                  )}\n                  notes={notes.filter(\n                    item => item.type === contest.office_slug\n                  )}\n                  isShowcaseRace\n                  tableHeader={CandidateRow.Header}\n                  columnCount={CandidateRow.columnCount}\n                  contestTitle={determineContestTitle(\n                    data.filter(\n                      item => item.office_slug === contest.office_slug\n                    )[0]\n                  )}\n                  renderParty={party => (\n                    <SeatPartyDivider\n                      partyName={party.party}\n                      partyBallot={party}\n                      tableHeader={CandidateRow.Header}\n                      notes={notes.filter(\n                        item =>\n                          item.type === contest.office_slug + '-' + party.party\n                      )}\n                      columnCount={CandidateRow.columnCount}\n                      renderCandidate={(candidate, idx) => (\n                        <CandidateRow\n                          key={candidate.id}\n                          ballotName={candidate.name}\n                          candidateId={candidate.id}\n                          isIncumbent={candidate.is_incumbent}\n                          party={candidate.party}\n                        />\n                      )}\n                    />\n                  )}\n                />\n              ))}\n          </div>\n        </Portal>\n        <Portal\n          node={document.querySelector('#railroad-commissioner .contests')}\n          ref={ref => (this._supremePortal = ref)}\n        >\n          <div class=\"office__contests\">\n            {unique_seats\n              .filter(contest => contest.office === 'Texas Railroad Commission')\n              .map(contest => (\n                <Contest\n                  key={contest.id}\n                  contest={data.filter(\n                    item => item.office_slug === contest.office_slug\n                  )}\n                  notes={notes.filter(\n                    item => item.type === contest.office_slug\n                  )}\n                  tableHeader={CandidateRow.Header}\n                  columnCount={CandidateRow.columnCount}\n                  contestTitle={determineContestTitle(\n                    data.filter(\n                      item => item.office_slug === contest.office_slug\n                    )[0]\n                  )}\n                  renderParty={party => (\n                    <SeatPartyDivider\n                      partyName={party.party}\n                      partyBallot={party}\n                      tableHeader={CandidateRow.Header}\n                      notes={notes.filter(\n                        item =>\n                          item.type === contest.office_slug + '-' + party.party\n                      )}\n                      columnCount={CandidateRow.columnCount}\n                      renderCandidate={(candidate, idx) => (\n                        <CandidateRow\n                          key={candidate.id}\n                          ballotName={candidate.name}\n                          candidateId={candidate.id}\n                          isIncumbent={candidate.is_incumbent}\n                          party={candidate.party}\n                        />\n                      )}\n                    />\n                  )}\n                />\n              ))}\n          </div>\n        </Portal>\n        <Portal\n          node={document.querySelector('#state-board-of-education .contests')}\n          ref={ref => (this._sboePortal = ref)}\n        >\n          <div class=\"office__contests office__contests--grid\">\n            {unique_seats\n              .filter(contest => contest.office === 'State Board of Education')\n              .map(contest => (\n                <Contest\n                  key={contest.id}\n                  contest={data.filter(\n                    item => item.office_slug === contest.office_slug\n                  )}\n                  notes={notes.filter(\n                    item => item.type === contest.office_slug\n                  )}\n                  tableHeader={CandidateRow.Header}\n                  columnCount={CandidateRow.columnCount}\n                  contestTitle={determineContestTitle(\n                    data.filter(\n                      item => item.office_slug === contest.office_slug\n                    )[0]\n                  )}\n                  renderParty={party => (\n                    <SeatPartyDivider\n                      partyName={party.party}\n                      partyBallot={party}\n                      tableHeader={CandidateRow.Header}\n                      notes={notes.filter(\n                        item =>\n                          item.type === contest.office_slug + '-' + party.party\n                      )}\n                      columnCount={CandidateRow.columnCount}\n                      renderCandidate={(candidate, idx) => (\n                        <CandidateRow\n                          key={candidate.id}\n                          ballotName={candidate.name}\n                          candidateId={candidate.id}\n                          isIncumbent={candidate.is_incumbent}\n                          party={candidate.party}\n                        />\n                      )}\n                    />\n                  )}\n                />\n              ))}\n          </div>\n        </Portal>\n        <Portal\n          node={document.querySelector('#texas-supreme-court .contests')}\n          ref={ref => (this._supremePortal = ref)}\n        >\n          <div class=\"office__contests office__contests--grid\">\n            {unique_seats\n              .filter(contest => contest.office === 'Texas Supreme Court')\n              .map(contest => (\n                <Contest\n                  key={contest.id}\n                  contest={data.filter(\n                    item => item.office_slug === contest.office_slug\n                  )}\n                  notes={notes.filter(\n                    item => item.type === contest.office_slug\n                  )}\n                  tableHeader={CandidateRow.Header}\n                  columnCount={CandidateRow.columnCount}\n                  contestTitle={determineContestTitle(\n                    data.filter(\n                      item => item.office_slug === contest.office_slug\n                    )[0]\n                  )}\n                  renderParty={party => (\n                    <SeatPartyDivider\n                      partyName={party.party}\n                      partyBallot={party}\n                      tableHeader={CandidateRow.Header}\n                      notes={notes.filter(\n                        item =>\n                          item.type === contest.office_slug + '-' + party.party\n                      )}\n                      columnCount={CandidateRow.columnCount}\n                      renderCandidate={(candidate, idx) => (\n                        <CandidateRow\n                          key={candidate.id}\n                          ballotName={candidate.name}\n                          candidateId={candidate.id}\n                          isIncumbent={candidate.is_incumbent}\n                          party={candidate.party}\n                        />\n                      )}\n                    />\n                  )}\n                />\n              ))}\n          </div>\n        </Portal>\n        <Portal\n          node={document.querySelector(\n            '#texas-court-of-criminal-appeals .contests'\n          )}\n          ref={ref => (this._crimPortal = ref)}\n        >\n          <div class=\"office__contests office__contests--grid\">\n            {unique_seats\n              .filter(\n                contest => contest.office === 'Texas Court of Criminal Appeals'\n              )\n              .map(contest => (\n                <Contest\n                  key={contest.id}\n                  contest={data.filter(\n                    item => item.office_slug === contest.office_slug\n                  )}\n                  notes={notes.filter(\n                    item => item.type === contest.office_slug\n                  )}\n                  tableHeader={CandidateRow.Header}\n                  columnCount={CandidateRow.columnCount}\n                  contestTitle={determineContestTitle(\n                    data.filter(\n                      item => item.office_slug === contest.office_slug\n                    )[0]\n                  )}\n                  renderParty={party => (\n                    <SeatPartyDivider\n                      partyName={party.party}\n                      partyBallot={party}\n                      tableHeader={CandidateRow.Header}\n                      notes={notes.filter(\n                        item =>\n                          item.type === contest.office_slug + '-' + party.party\n                      )}\n                      columnCount={CandidateRow.columnCount}\n                      renderCandidate={(candidate, idx) => (\n                        <CandidateRow\n                          key={candidate.id}\n                          ballotName={candidate.name}\n                          candidateId={candidate.id}\n                          isIncumbent={candidate.is_incumbent}\n                          party={candidate.party}\n                        />\n                      )}\n                    />\n                  )}\n                />\n              ))}\n          </div>\n        </Portal>\n        <Portal\n          node={document.querySelector(\n            '#texas-fifteenth-court-of-appeals .contests'\n          )}\n          ref={ref => (this._fifteenthPortal = ref)}\n        >\n          <div class=\"office__contests office__contests--grid\">\n            {unique_seats\n              .filter(\n                contest => contest.office === 'Texas Fifteenth Court of Appeals'\n              )\n              .map(contest => (\n                <Contest\n                  key={contest.id}\n                  contest={data.filter(\n                    item => item.office_slug === contest.office_slug\n                  )}\n                  notes={notes.filter(\n                    item => item.type === contest.office_slug\n                  )}\n                  tableHeader={CandidateRow.Header}\n                  columnCount={CandidateRow.columnCount}\n                  contestTitle={determineContestTitle(\n                    data.filter(\n                      item => item.office_slug === contest.office_slug\n                    )[0]\n                  )}\n                  renderParty={party => (\n                    <SeatPartyDivider\n                      partyName={party.party}\n                      partyBallot={party}\n                      tableHeader={CandidateRow.Header}\n                      notes={notes.filter(\n                        item =>\n                          item.type === contest.office_slug + '-' + party.party\n                      )}\n                      columnCount={CandidateRow.columnCount}\n                      renderCandidate={(candidate, idx) => (\n                        <CandidateRow\n                          key={candidate.id}\n                          ballotName={candidate.name}\n                          candidateId={candidate.id}\n                          isIncumbent={candidate.is_incumbent}\n                          party={candidate.party}\n                        />\n                      )}\n                    />\n                  )}\n                />\n              ))}\n          </div>\n        </Portal>\n        <Portal\n          node={document.querySelector('#texas-senate .contests')}\n          ref={ref => (this._senatePortal = ref)}\n        >\n          <div class=\"office__contests office__contests--grid\">\n            {unique_seats\n              .filter(contest => contest.office === 'Texas Senate')\n              .map(contest => (\n                <Contest\n                  key={contest.id}\n                  contest={data.filter(\n                    item => item.office_slug === contest.office_slug\n                  )}\n                  notes={notes.filter(\n                    item => item.type === contest.office_slug\n                  )}\n                  tableHeader={CandidateRow.Header}\n                  columnCount={CandidateRow.columnCount}\n                  contestTitle={determineContestTitle(\n                    data.filter(\n                      item => item.office_slug === contest.office_slug\n                    )[0]\n                  )}\n                  renderParty={party => (\n                    <SeatPartyDivider\n                      partyName={party.party}\n                      partyBallot={party}\n                      tableHeader={CandidateRow.Header}\n                      notes={notes.filter(\n                        item =>\n                          item.type === contest.office_slug + '-' + party.party\n                      )}\n                      columnCount={CandidateRow.columnCount}\n                      renderCandidate={(candidate, idx) => (\n                        <CandidateRow\n                          key={candidate.id}\n                          ballotName={candidate.name}\n                          candidateId={candidate.id}\n                          isIncumbent={candidate.is_incumbent}\n                          party={candidate.party}\n                        />\n                      )}\n                    />\n                  )}\n                />\n              ))}\n          </div>\n        </Portal>\n\n        <Portal\n          node={document.querySelector('#texas-house .contests')}\n          ref={ref => (this._housePortal = ref)}\n        >\n          <div class=\"office__contests\">\n            {texasHouse.length > 0 &&\n              texasHouseGroups.map(contestGroup => (\n                <div class=\"contest-group\">\n                  <div class=\"seat__contests-double\">\n                    {contestGroup.map(contest => (\n                      <Contest\n                        key={contest.id}\n                        contest={data.filter(\n                          item => item.office_slug === contest.office_slug\n                        )}\n                        notes={notes.filter(\n                          item => item.type === contest.office_slug\n                        )}\n                        tableHeader={CandidateRow.Header}\n                        columnCount={CandidateRow.columnCount}\n                        contestTitle={determineContestTitle(\n                          data.filter(\n                            item => item.office_slug === contest.office_slug\n                          )[0]\n                        )}\n                        renderParty={party => (\n                          <SeatPartyDivider\n                            partyName={party.party}\n                            partyBallot={party}\n                            tableHeader={CandidateRow.Header}\n                            notes={notes.filter(\n                              item =>\n                                item.type ===\n                                contest.office_slug + '-' + party.party\n                            )}\n                            columnCount={CandidateRow.columnCount}\n                            renderCandidate={(candidate, idx) => (\n                              <CandidateRow\n                                key={candidate.id}\n                                ballotName={candidate.name}\n                                candidateId={candidate.id}\n                                isIncumbent={candidate.is_incumbent}\n                                party={candidate.party}\n                              />\n                            )}\n                          />\n                        )}\n                      />\n                    ))}\n                  </div>\n                  <Ad />\n                </div>\n              ))}\n          </div>\n        </Portal>\n      </div>\n    );\n  }\n}\n\nexport default App;\n","// import JS files\nimport '../kickstart';\nimport './ballot-filter';\n\nimport { h, render } from 'preact';\n\n// Components\nimport App from '../BallotApp';\nimport loadJsonScript from '../utils/load-json-script';\n\nconst notes = loadJsonScript('notes_data');\n\nrender(<App notes={notes} />, document.getElementById('app'));\n","/**\n * Grabs the contents of a `jsonScript` created JSON inline string and returns\n * it as a JSON object. If the element does not exist, or if the script\n * element does not have the JSON MIME type, null is returned instead.\n *\n * @param  {String} elementId the ID of the JSON script element\n * @return {Object|null}\n */\nexport default function loadJsonScript(elementId) {\n  const element = document.getElementById(elementId);\n\n  if (element && element.getAttribute('type') === 'application/json') {\n    return JSON.parse(element.textContent);\n  } else {\n    return null;\n  }\n}\n","var journalize = require('journalize');\n\nimport { capfirst, intcomma, intword } from 'journalize';\n\nexport function roundThousands(num) {\n  var integer = 1000;\n  if (num < 1000000) return intcomma(Math.round(num / integer) * integer);\n  else return intword(num);\n}\n\nexport const chunk = (arr, size) =>\n  arr.reduce((acc, _, i) => {\n    if (i % size === 0) acc.push(arr.slice(i, i + size));\n    return acc;\n  }, []);\n\n// Some seats have both a regular race and a special election for the unexpired\n// term on the same ballot (same office_slug, same candidates). Keep only the\n// regular race so each seat shows a single card.\nexport const dropDuplicateSpecials = entries =>\n  entries.filter(\n    entry =>\n      entry.election_type !== 'special' ||\n      !entries.some(\n        other =>\n          other.office_slug === entry.office_slug &&\n          other.election_type === 'general'\n      )\n  );\n\nexport const delay = (function() {\n  var timer = 0;\n  return function(callback, ms) {\n    clearTimeout(timer);\n    timer = setTimeout(callback, ms);\n  };\n})();\n\nconst TT_directory_slugs = [\n  { office: 'Texas House', 'directory-slug': 'tx-house' },\n  { office: 'Texas Senate', 'directory-slug': 'tx-senate' },\n  { office: 'U.S. House', 'directory-slug': 'us-house' },\n  { office: 'State Board of Education', 'directory-slug': 'sboe' },\n];\n\nexport function get_directory_slug(office) {\n  return TT_directory_slugs.filter(slug => slug.office == office);\n}\n\nexport function sort_candidates_alphabetically(candidates) {\n  return candidates.sort((a, b) =>\n    (a.sort_name || a.name || '').localeCompare(b.sort_name || b.name || '')\n  );\n}\n\n// Display overrides for office names as they come from the data.\nconst OFFICE_DISPLAY_NAMES = {\n  'Texas Fifteenth Court of Appeals': 'Texas 15th Court of Appeals',\n};\n\nexport function formatOfficeName(office) {\n  return OFFICE_DISPLAY_NAMES[office] || office;\n}\n\nexport function determineDistrictTitle(contest) {\n  return `${formatOfficeName(contest.office)} ${\n    contest.office === 'President' ||\n    contest.division_type === 'class' ||\n    contest.division_type === 'statewide'\n      ? ''\n      : contest.division_type === 'place' && contest.office_division === 1\n      ? 'Chief Justice'\n      : capfirst(contest.division_type) + ' ' + contest.office_division\n  }`.trim();\n}\n\nexport function determineContestTitle(contest) {\n  if (contest.division_type === 'statewide' || contest.division_type === 'seat')\n    return '';\n\n  return determineDistrictTitle(contest);\n}\n\nexport function determineContestTitleYourRaces(contest) {\n  return determineDistrictTitle(contest);\n}\n","/**\n * A wrapper for the initial response from a fetch call that funnels to\n * res.json().\n *\n * @private\n * @param {Response} res\n * @returns {Promise}\n */\nfunction jsonResponse(res) {\n  if (!res.ok) throw new Error(`${res.status}: ${res.statusText}`);\n\n  return res.json();\n}\n\n/**\n * A light wrapper around fetch that assumes you're seeking a JSON response.\n *\n * @param {String|Request} input\n * @param {Object} init\n * @returns {Promise}\n */\nexport default function getJSON(input, init) {\n  return fetch(input, init).then(jsonResponse);\n}\n","var filterBar = document.getElementById('ballot-filter');\nvar searchInput = document.getElementById('ballot-search-input');\nvar searchList = document.getElementById('ballot-search-listbox');\nvar searchClear = document.getElementById('ballot-search-clear');\nvar resultsCount = document.getElementById('ballot-results-count');\n\nif (filterBar) {\n  var buttons = Array.prototype.slice.call(\n    filterBar.querySelectorAll('[data-filter]')\n  );\n\n  function normalize(str) {\n    return str.toLowerCase().replace(/[^a-z0-9]/g, '');\n  }\n\n  var entries = Array.prototype.slice\n    .call(document.querySelectorAll('.office[data-race-category]'))\n    .map(function(office) {\n      var titleEl = office.querySelector('.office__title');\n      return {\n        office: office,\n        title: titleEl ? titleEl.textContent.trim() : office.id,\n        category: office.dataset.raceCategory,\n      };\n    });\n\n  function getActiveFilter() {\n    var active = buttons\n      .filter(function(b) {\n        return b.classList.contains('is-active');\n      })\n      .map(function(b) {\n        return b.dataset.filter;\n      });\n    var showAll = active.length === 0 || active.indexOf('all') !== -1;\n    return { active: active, showAll: showAll };\n  }\n\n  var baseLabels = {};\n  buttons.forEach(function(btn) {\n    baseLabels[btn.dataset.filter] = btn.textContent.trim();\n  });\n\n  function updateCounts() {\n    var categoryCounts = {};\n    var total = 0;\n\n    entries.forEach(function(entry) {\n      var category = entry.office.dataset.raceCategory;\n      var count = entry.office.querySelectorAll('.seat').length;\n      categoryCounts[category] = (categoryCounts[category] || 0) + count;\n      total += count;\n    });\n\n    buttons.forEach(function(btn) {\n      var filter = btn.dataset.filter;\n      var count = filter === 'all' ? total : categoryCounts[filter] || 0;\n      btn.textContent = baseLabels[filter] + ' (' + count + ')';\n    });\n  }\n  updateCounts();\n\n  var officeContainer = entries.length ? entries[0].office.parentElement : null;\n  var topLevelAds = officeContainer\n    ? Array.prototype.filter.call(officeContainer.children, function(el) {\n        return (\n          el.classList.contains('plugin') &&\n          el.classList.contains('plugin--centered')\n        );\n      })\n    : [];\n\n  var nestedAds = [];\n  function refreshNestedAds() {\n    var next = [];\n    entries.forEach(function(entry) {\n      Array.prototype.forEach.call(\n        entry.office.querySelectorAll('.contests .plugin.plugin--centered'),\n        function(el) {\n          next.push(el);\n        }\n      );\n    });\n    nestedAds = next;\n  }\n  refreshNestedAds();\n\n  function matchesSearch(entry, term) {\n    return !term || normalize(entry.title).indexOf(normalize(term)) !== -1;\n  }\n\n  function apply() {\n    var filter = getActiveFilter();\n    var active = filter.active;\n    var showAll = filter.showAll;\n    var term = searchInput ? searchInput.value.trim() : '';\n    var totalRaces = 0;\n    var visibleRaces = 0;\n\n    entries.forEach(function(entry) {\n      var seats = Array.prototype.slice.call(\n        entry.office.querySelectorAll('.seat')\n      );\n      totalRaces += seats.length;\n\n      var categoryShown = showAll || active.indexOf(entry.category) !== -1;\n\n      if (!categoryShown) {\n        entry.office.hidden = true;\n        return;\n      }\n\n      if (!term || matchesSearch(entry, term) || !seats.length) {\n        entry.office.hidden = false;\n        seats.forEach(function(seat) {\n          seat.hidden = false;\n        });\n        visibleRaces += seats.length;\n        return;\n      }\n\n      var anySeatMatches = false;\n      seats.forEach(function(seat) {\n        var titleEl = seat.querySelector('.seat__title');\n        var seatTitle = titleEl ? titleEl.textContent.trim() : '';\n        var seatMatches =\n          !!seatTitle && normalize(seatTitle).indexOf(normalize(term)) !== -1;\n        seat.hidden = !seatMatches;\n        if (seatMatches) {\n          anySeatMatches = true;\n          visibleRaces++;\n        }\n      });\n      entry.office.hidden = !anySeatMatches;\n    });\n\n    var isFiltered = !showAll || !!term;\n    topLevelAds.forEach(function(ad) {\n      ad.hidden = isFiltered;\n    });\n    nestedAds.forEach(function(ad) {\n      ad.hidden = !!term;\n    });\n\n    if (resultsCount) {\n      resultsCount.innerHTML =\n        'Showing <strong>' +\n        visibleRaces +\n        '</strong> of <strong>' +\n        totalRaces +\n        '</strong> races. ';\n    }\n  }\n\n  var seatEntries = [];\n  function refreshSeatEntries() {\n    var next = [];\n    entries.forEach(function(entry) {\n      Array.prototype.forEach.call(\n        entry.office.querySelectorAll('.seat'),\n        function(seat) {\n          var titleEl = seat.querySelector('.seat__title');\n          var title = titleEl ? titleEl.textContent.trim() : '';\n          if (title) next.push({ title: title, category: entry.category });\n        }\n      );\n    });\n    seatEntries = next;\n  }\n  refreshSeatEntries();\n\n  var contestsContainers = document.querySelectorAll('.office .contests');\n  if (contestsContainers.length && window.MutationObserver) {\n    var seatObserver = new MutationObserver(function() {\n      refreshSeatEntries();\n      refreshNestedAds();\n      updateCounts();\n      apply();\n    });\n    Array.prototype.forEach.call(contestsContainers, function(container) {\n      seatObserver.observe(container, { childList: true, subtree: true });\n    });\n  }\n\n  function scrollToAllRacesTop() {\n    var heading = document.getElementById('all-races__heading');\n    if (heading) heading.scrollIntoView({ behavior: 'smooth', block: 'start' });\n  }\n\n  buttons.forEach(function(btn) {\n    btn.addEventListener('click', function() {\n      if (btn.dataset.filter === 'all') {\n        buttons.forEach(function(b) {\n          b.classList.remove('is-active');\n        });\n        btn.classList.add('is-active');\n      } else {\n        btn.classList.toggle('is-active');\n        var allBtn = buttons.filter(function(b) {\n          return b.dataset.filter === 'all';\n        })[0];\n        allBtn.classList.remove('is-active');\n\n        var anyActive = buttons.some(function(b) {\n          return (\n            b.dataset.filter !== 'all' && b.classList.contains('is-active')\n          );\n        });\n        if (!anyActive) allBtn.classList.add('is-active');\n      }\n      apply();\n\n      scrollToAllRacesTop();\n    });\n  });\n\n  if (searchInput && searchList) {\n    var highlightedIndex = -1;\n    var MAX_SUGGESTIONS = 8;\n\n    function currentMatches() {\n      var term = searchInput.value.trim();\n      if (!term) return [];\n      var filter = getActiveFilter();\n      return entries\n        .concat(seatEntries)\n        .filter(function(entry) {\n          return (\n            (filter.showAll || filter.active.indexOf(entry.category) !== -1) &&\n            matchesSearch(entry, term)\n          );\n        })\n        .slice(0, MAX_SUGGESTIONS);\n    }\n\n    function renderList() {\n      var matches = currentMatches();\n      searchList.innerHTML = '';\n\n      matches.forEach(function(entry, idx) {\n        var li = document.createElement('li');\n        li.className =\n          'listbox__item' +\n          (idx === highlightedIndex ? ' listbox__item--highlighted' : '');\n        li.textContent = entry.title;\n        li.addEventListener(\n          'touchstart',\n          function(event) {\n            event.preventDefault();\n            selectEntry(entry);\n          },\n          { passive: false }\n        );\n        li.addEventListener('mousedown', function(event) {\n          event.preventDefault();\n          selectEntry(entry);\n        });\n        li.addEventListener('mouseenter', function() {\n          highlightedIndex = idx;\n          renderList();\n        });\n        searchList.appendChild(li);\n      });\n\n      searchList.hidden = matches.length === 0;\n      searchInput.setAttribute('aria-expanded', String(matches.length > 0));\n    }\n\n    function selectEntry(entry) {\n      searchInput.value = entry.title;\n      searchList.hidden = true;\n      highlightedIndex = -1;\n      updateClearButton();\n      apply();\n      scrollToAllRacesTop();\n    }\n\n    function updateClearButton() {\n      if (searchClear) searchClear.hidden = !searchInput.value;\n    }\n\n    if (searchClear) {\n      searchClear.addEventListener('click', function() {\n        searchInput.value = '';\n        searchList.hidden = true;\n        highlightedIndex = -1;\n        updateClearButton();\n        apply();\n        searchInput.focus();\n      });\n    }\n\n    searchInput.addEventListener('input', function() {\n      highlightedIndex = -1;\n      renderList();\n      updateClearButton();\n    });\n\n    updateClearButton();\n\n    searchInput.addEventListener('keydown', function(event) {\n      var count = currentMatches().length;\n\n      if (event.key === 'ArrowDown') {\n        event.preventDefault();\n        if (!count) return;\n        highlightedIndex = Math.min(highlightedIndex + 1, count - 1);\n        renderList();\n      } else if (event.key === 'ArrowUp') {\n        event.preventDefault();\n        if (!count) return;\n        highlightedIndex = Math.max(highlightedIndex - 1, 0);\n        renderList();\n      } else if (event.key === 'Enter') {\n        var matches = currentMatches();\n        if (highlightedIndex > -1 && matches[highlightedIndex]) {\n          event.preventDefault();\n          selectEntry(matches[highlightedIndex]);\n        }\n      } else if (event.key === 'Escape') {\n        searchList.hidden = true;\n        highlightedIndex = -1;\n      }\n    });\n\n    searchInput.addEventListener('blur', function() {\n      setTimeout(function() {\n        searchList.hidden = true;\n      }, 0);\n    });\n\n    searchInput.addEventListener('focus', function() {\n      if (searchInput.value.trim()) renderList();\n    });\n  }\n\n  apply();\n}\n\nvar jumpToPersonalizedLink = document.getElementById(\n  'jump-to-personalized-link'\n);\nif (jumpToPersonalizedLink) {\n  jumpToPersonalizedLink.addEventListener('click', function(event) {\n    event.preventDefault();\n    var heading = document.getElementById('your-races-promo__heading');\n    if (!heading) return;\n\n    heading.scrollIntoView({ behavior: 'smooth', block: 'start' });\n\n    var clearBodyOverflowLock = function() {\n      if (document.body.style.overflow) document.body.style.overflow = '';\n    };\n    if ('onscrollend' in window) {\n      window.addEventListener('scrollend', clearBodyOverflowLock, {\n        once: true,\n      });\n    } else {\n      setTimeout(clearBodyOverflowLock, 600);\n    }\n  });\n}\n","const hOP = Object.prototype.hasOwnProperty;\n\n/**\n * inlined Object.is polyfill to avoid requiring consumers ship their own\n * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is\n */\nfunction is(x: any, y: any): boolean {\n  // SameValue algorithm\n  if (x === y) {\n    // Steps 1-5, 7-10\n    // Steps 6.b-6.e: +0 != -0\n    // Added the nonzero y check to make Flow happy, but it is redundant\n    return x !== 0 || y !== 0 || 1 / x === 1 / y;\n  }\n  // Step 6.a: NaN == NaN\n  return x !== x && y !== y;\n}\n\n/**\n * Performs equality by iterating through keys on an object and returning false\n * when any key has values which are not strictly equal between the arguments.\n * Returns true when the values of all keys are strictly equal.\n */\nfunction shallowEqual(objA: object, objB: object): boolean {\n  if (is(objA, objB)) {\n    return true;\n  }\n\n  if (\n    typeof objA !== 'object' ||\n    objA === null ||\n    typeof objB !== 'object' ||\n    objB === null\n  ) {\n    return false;\n  }\n\n  const keysA = Object.keys(objA);\n  const keysB = Object.keys(objB);\n\n  if (keysA.length !== keysB.length) {\n    return false;\n  }\n\n  // Test for A's keys different from B.\n  for (let i = 0; i < keysA.length; i++) {\n    if (!hOP.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\nexport default shallowEqual;\n","// packages\nimport { Component } from 'preact';\n\n// internal\nimport shallowEqual from '../utils/shallow-equal';\n\nabstract class PureComponent<P = {}, S = {}> extends Component<P, S> {\n  shouldComponentUpdate(props, state) {\n    const check =\n      shallowEqual(props, this.props) && shallowEqual(state, this.state);\n    // if (props.projection)\n    //   console.log(\n    //     'projection check:',\n    //     props.projection === this.props.projection,\n    //     !check\n    //   );\n    return !check;\n  }\n}\n\nexport default PureComponent;\n"],"sourceRoot":""}