S2 (a1): compliance + approval pack

- /responsible-gambling rebuilt sincerely: 21+, 1-800-GAMBLER primary,
  17-state resource list, warning signs, self-exclusion guidance, links
  to the existing /settings surfaces. No marketing adjacency.
- /terms + /privacy honest drafts with entity placeholders ([ENTITY NAME],
  [STATE OF FORMATION], [ARBITRATION VENUE], [CONTACT EMAIL]); privacy
  sub-processors match reality (adds Sentry, honest PostHog description).
- NEW /methodology: pipeline -> engine -> letter grades, refusals,
  VYNDR Originals, ledger settle + CLV + n>=20, why misses are public.
- /about audited to North Star framing (THE PROOF card, methodology link).
- Footer: 1-800-GAMBLER + Methodology link; compliance audit found zero
  pages suppressing the global footer.
- 5 Ghost seed articles in content/articles/ + docs/GHOST-PUBLISHING.md
  manual runbook (no Ghost access used).
- tests/unit/compliancePages.test.js (repo source-text style). 2429 tests
  green, web build exit 0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kev
2026-07-11 14:29:31 -04:00
parent e4d2e79f95
commit 4b262fdd65
15 changed files with 908 additions and 76 deletions
+32 -8
View File
@@ -1,9 +1,16 @@
import SectionHead from '@/components/vyndr/SectionHead';
import { Wordmark } from '@/components/vyndr';
export const metadata = { title: 'About' };
export const metadata = {
title: 'About',
description:
'VYNDR is a sports data intelligence platform built in Detroit. The Ledger is the public record — misses included.',
};
// Brand page in system voice (§3). Server component.
// Session 2 (A1 board) — audited against NORTH STAR v1.1: data intelligence
// platform, the Ledger as public proof, built in Detroit. VOICE v1.1 —
// deadpan, numbers first, no exclamation points.
export default function AboutPage() {
return (
<section style={{ maxWidth: 680, margin: '0 auto', padding: '40px 16px 96px' }}>
@@ -17,23 +24,40 @@ export default function AboutPage() {
<div style={{ display: 'flex', flexDirection: 'column', gap: 22 }}>
<p className="mono" style={{ fontSize: 14.5, color: 'var(--text-1)', lineHeight: 1.7 }}>
VYNDR is prop intelligence a proprietary terminal that reads the context the books hide.
Beyond the box score: form, matchup, usage, rest, the cascade when a star sits. Then a single
grade, earned across 40+ factors, that tells you whether the number is worth taking.
VYNDR is a sports data intelligence platform. The free layer is the complete picture
schedule, stats, game logs, streaks with the context they were built against, line
comparison across books always populated, always interpreted. The paid layer is the
read: a letter grade earned across the model&apos;s full feature pipeline, archetypes,
correlation-aware parlays, and closing-line intelligence.
</p>
<p className="mono" style={{ fontSize: 14.5, color: 'var(--text-1)', lineHeight: 1.7 }}>
We are an analytics tool, not a sportsbook. We don&apos;t take wagers. We hand you the read and
the kill conditions, and let you decide.
We are an analytics tool, not a sportsbook. We take no wagers and hold no funds. We hand
you the read and let you decide.
</p>
<div>
<SectionHead style={{ marginBottom: 12 }}>THE PROOF</SectionHead>
<div style={{ background: 'var(--bg-1)', border: '1px solid var(--border)', borderRadius: 10, padding: 18 }}>
<p className="mono" style={{ fontSize: 13.5, color: 'var(--text-1)', lineHeight: 1.65, margin: 0 }}>
Every grade the model produces is locked at grade time line, odds, timestamp and
settled against the real box score on{' '}
<a href="/ledger" style={{ color: 'var(--text-0)' }}>the Ledger</a>, misses included,
in the same format as the wins. No percentage renders until at least 20 grades have
settled. When the model has no projection, it refuses to grade rather than guess.
How all of it works is written down, in plain language, on{' '}
<a href="/methodology" style={{ color: 'var(--text-0)' }}>the methodology page</a>.
</p>
</div>
</div>
<div>
<SectionHead style={{ marginBottom: 12 }}>BUILT BY</SectionHead>
<div style={{ background: 'var(--bg-1)', border: '1px solid var(--border)', borderRadius: 10, padding: 18 }}>
<div style={{ fontSize: 17, fontWeight: 800 }}>Kevon Butler</div>
<div className="mono" style={{ fontSize: 12.5, color: 'var(--text-1)', marginTop: 4 }}>Founder · Detroit</div>
<p className="mono" style={{ fontSize: 13.5, color: 'var(--text-1)', lineHeight: 1.65, marginTop: 12 }}>
A glitch between a tech-genius mind and a love for sports. Built in Detroit, for everyone the
books count on staying in the dark.
The books employ floors full of quants. This is one terminal, built in Detroit, for
everyone the books count on staying in the dark. Seems fair.
</p>
</div>
</div>
+173
View File
@@ -0,0 +1,173 @@
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Methodology',
description:
'How VYNDR grades a prop, what archetypes are, how the Ledger settles, and why the misses are public. Plain language, no hype.',
};
// Session 2 (A1 board) — the approval-pack methodology page. Server component.
// Plain-language description of the real pipeline (feature vector → engine →
// letter grade → locked ledger entry → box-score settle → CLV). Every claim
// here matches the code; if the pipeline changes, change this page in the
// same commit.
const h2: React.CSSProperties = { fontSize: 20, fontWeight: 700, marginBottom: 12, color: 'var(--text-0)' };
const body: React.CSSProperties = { color: 'var(--text-1)', lineHeight: 1.75, fontSize: 15, marginBottom: 12 };
const card: React.CSSProperties = {
background: 'var(--bg-1)',
border: '1px solid var(--border)',
borderRadius: 10,
padding: '16px 18px',
};
function Mono({ children }: { children: React.ReactNode }) {
return <span className="mono" style={{ color: 'var(--text-0)' }}>{children}</span>;
}
export default function MethodologyPage() {
return (
<section style={{ maxWidth: 720, margin: '0 auto', padding: '48px 16px 120px' }}>
<header style={{ marginBottom: 32 }}>
<h1 style={{ fontSize: 36, fontWeight: 700, letterSpacing: '-0.03em', marginBottom: 8, color: 'var(--text-0)' }}>
How the grades work.
</h1>
<p className="mono" style={{ fontSize: 12, color: 'var(--text-2)', letterSpacing: '0.05em' }}>
METHODOLOGY · PLAIN LANGUAGE · NO HYPE
</p>
</header>
<p style={{ ...body, fontSize: 16 }}>
This page describes what actually happens between a sportsbook posting a line and a letter
grade appearing on VYNDR. It is written so a claim made here can be checked against the
Ledger. If a sentence on this page ever stops being true, the page is wrong and we fix it.
</p>
{/* ── The pipeline ─────────────────────────────────────────── */}
<section style={{ marginTop: 36 }}>
<h2 style={h2}>The pipeline</h2>
<p style={body}>
Grades are produced by a scheduled pipeline, not on demand. Several times a day the
system pulls the current prop lines from sportsbook feeds, then builds a feature vector
for each prop the numbers the model reasons over. Depending on the sport, that includes
recent form (last-5 and last-20 averages, variance), opponent strength against the exact
stat, pace, home or away, rest days, schedule density, batter-versus-pitcher history for
MLB, and per-90 rates with expected-goals context for soccer.
</p>
<p style={body}>
The engine compares the model&apos;s projection to the posted line in both directions.
It grades the over and the under separately and keeps whichever side it has more
conviction in. The output is an 11-step letter grade, <Mono>F</Mono> through{' '}
<Mono>A+</Mono>, with a confidence score behind it. The letter is a probabilistic
assessment of one side of one line. It is not a prediction and it is never a guarantee.
</p>
<div style={card}>
<p className="mono" style={{ fontSize: 12.5, color: 'var(--text-1)', lineHeight: 1.8, margin: 0 }}>
LINE FEED FEATURE VECTOR PROJECTION vs LINE (BOTH SIDES) LETTER GRADE LOCKED TO
THE LEDGER SETTLED vs THE BOX SCORE
</p>
</div>
</section>
{/* ── Refusals ─────────────────────────────────────────────── */}
<section style={{ marginTop: 36 }}>
<h2 style={h2}>When the model refuses</h2>
<p style={body}>
If the pipeline cannot build a real projection for a prop not enough recent games, no
per-90 baseline, a data source down the model refuses to grade it. No letter renders,
the prop shows an absent state, and a free read is not consumed. A refusal is not a
failure mode we hide; it is the design. A grade with nothing behind it would still look
like a grade, and that is worse than no grade.
</p>
<p style={body}>
The same rule applies to every number on the platform: market values (lines, odds,
closes) are real book numbers captured at a timestamp, never computed by us. Model values
are labeled as model output. Where data is missing, the surface says less.
Absent beats wrong.
</p>
</section>
{/* ── Archetypes ───────────────────────────────────────────── */}
<section style={{ marginTop: 36 }}>
<h2 style={h2}>Archetypes the VYNDR Originals</h2>
<p style={body}>
Archetypes are VYNDR&apos;s proprietary classification of how a player produces 41
originals across NBA, WNBA, MLB, and soccer, built by scoring each player&apos;s real
season statistics against production patterns. A <Mono>TORCH</Mono> is a high-usage,
shot-dependent scorer whose points track his touches. A <Mono>BOMBER</Mono> is a power
bat whose home-run and total-base props behave differently from a contact hitter&apos;s.
A <Mono>GHOST</Mono> beats you with speed. A <Mono>CONDUCTOR</Mono> creates for everyone
else first.
</p>
<p style={body}>
The point is practical, not decorative: different archetypes have different reliable and
volatile props. Points for a TORCH and assists for a CONDUCTOR are stable; the inverse
legs swing with game script. Each classification carries a primary archetype, an optional
secondary, and a weighted blend because most players are not one thing. The
classification comes from the same stats pipeline that feeds the grades, so an archetype
is re-earned from real numbers, not assigned once and left to rot.
</p>
</section>
{/* ── The Ledger ───────────────────────────────────────────── */}
<section style={{ marginTop: 36 }}>
<h2 style={h2}>How the Ledger settles</h2>
<p style={body}>
Every grade the pipeline produces is written to the Ledger at the moment it is made,
locked with the exact line, the odds, and a timestamp. That entry never changes. If the
line moves hard against a graded side later in the day, the system may re-grade at the
real new line and when it does, the original letter stays on the record, struck
through, next to the revision. Nothing is revised silently.
</p>
<p style={body}>
After the games end, entries settle against the real box score the stat the player
actually produced, from league data. Hit, miss, or push, recorded once, idempotently.
Alongside the result we record closing line value: the pipeline captures the closing
line for each graded prop (the last pre-game snapshot of the book&apos;s number) and
measures whether the market moved toward or away from the graded side between our
timestamp and the close. Beating the close consistently is the standard evidence that a
model is finding real edge rather than getting lucky, which is why we track it on every
entry instead of just counting wins.
</p>
<div style={card}>
<p className="mono" style={{ fontSize: 12.5, color: 'var(--text-1)', lineHeight: 1.8, margin: 0 }}>
THE n20 RULE no hit percentage or CLV percentage renders anywhere on VYNDR until at
least 20 grades have settled in that window. Below that, the surface says
RECORD BUILDING. A percentage on a small sample is a marketing number, and we do not publish
marketing numbers.
</p>
</div>
</section>
{/* ── Misses ───────────────────────────────────────────────── */}
<section style={{ marginTop: 36 }}>
<h2 style={h2}>Why the misses are public</h2>
<p style={body}>
Every settled miss stays on the Ledger, by name, in the same format and the same
placement as the wins, permanently. There are two reasons. The honest one: a record you
curate is not a record, and the entire value of this product rests on the record being
real. The practical one: nobody else in this industry can afford to do it, because their
numbers do not survive it. Ours are built to. The model is wrong regularly the Ledger
shows exactly how regularly, and that transparency is the product working as intended,
not a bug in it.
</p>
</section>
{/* ── What we never do ─────────────────────────────────────── */}
<section style={{ marginTop: 36 }}>
<h2 style={h2}>What we never do</h2>
<ul style={{ display: 'grid', gap: 8, ...body, paddingLeft: 18, listStyle: 'disc' }}>
<li>Fabricate a line, an odd, or a result. Market numbers are captured, never invented.</li>
<li>Ship a grade the model has no projection for.</li>
<li>Render a percentage on fewer than 20 settled grades.</li>
<li>Edit or delete a settled entry, win or miss.</li>
<li>Take a bet. VYNDR is an analytics tool, not a sportsbook.</li>
</ul>
<p style={{ ...body, marginTop: 8 }}>
The record is at <a href="/ledger" style={{ color: 'var(--text-0)' }}>vyndr.app/ledger</a>.
Draw your own conclusion.
</p>
</section>
</section>
);
}
+17 -11
View File
@@ -5,21 +5,25 @@ export const metadata: Metadata = {
description: 'How VYNDR handles your data. Plain English.',
};
// Session 2 (A1 board) — approval-pack draft. Entity details are placeholder
// tokens ([ENTITY NAME], [CONTACT EMAIL]) for Kev to fill before this ships
// as the legal document.
const SECTIONS: { title: string; body: string[]; emphasized?: boolean }[] = [
{
title: 'We never sell your personal data.',
body: [
'VYNDR Intelligence LLC does not sell, rent, or trade your personal data to anyone. Ever. Our business is a subscription to an analytics product — not a data resale operation.',
'[ENTITY NAME], the company that operates VYNDR, does not sell, rent, or trade your personal data to anyone. Our business is a subscription to an analytics product — not a data resale operation.',
],
emphasized: true,
},
{
title: 'Data we collect',
body: [
'Account data: email, password hash, age confirmation, signup timestamp.',
'Account data: email, password hash (managed by Supabase Auth — we never see your plaintext password), age confirmation, signup timestamp.',
'Usage data: reads you run (player, stat, line, sport, grade), parlays you build, page views.',
'Payment data: Stripe processes all card data — we never see or store your card number, CVC, or any other payment instrument detail. We retain a Stripe customer ID, Stripe subscription ID, and your subscription status (active, canceled, grace period, expired) so we can gate paid features and respond to renewal/cancellation events from Stripe webhooks.',
'Device data: IP address, browser type, basic device info (for fraud prevention and analytics).',
'Payment data: Stripe processes all card data — we never see or store your card number, CVC, or any other payment instrument detail. We retain a Stripe customer ID, Stripe subscription ID, and your subscription status (active, canceled, grace period, expired) so we can gate paid features and respond to renewal and cancellation events from Stripe webhooks.',
'Device data: IP address, browser type, basic device info (for fraud prevention, error monitoring, and analytics).',
],
},
{
@@ -27,7 +31,7 @@ const SECTIONS: { title: string; body: string[]; emphasized?: boolean }[] = [
body: [
'To provide the service: sign you in, gate reads by tier, deliver grades.',
'To improve the model: aggregate, anonymized read data helps calibration. Individual reads are never used to identify you to third parties.',
'Aggregate trend features: "Most Read Tonight" and "Most Parlayed Tonight" use anonymized counts across all users. Your individual reads are not exposed.',
'Aggregate trend features: surfaces like "Most Read Tonight" use anonymized counts across all users. Your individual reads are not exposed.',
'To communicate: account confirmation, payment receipts, renewal reminders, critical service notices.',
],
},
@@ -51,17 +55,18 @@ const SECTIONS: { title: string; body: string[]; emphasized?: boolean }[] = [
title: 'Cookies and analytics',
body: [
'Essential cookies: auth session, read counter (cannot be disabled — the service does not work without them).',
'Analytics: PostHog (anonymized IPs, no third-party trackers). You can opt out by setting your browser to "Do Not Track" or contacting us.',
'Analytics: PostHog, with autocapture disabled — we record only the product events we name (page views, feature usage), never keystrokes or form contents, and no third-party ad trackers. The cookie notice on first visit is a disclosure of this. To opt out of analytics entirely, contact us at [CONTACT EMAIL].',
],
},
{
title: 'Sub-processors',
body: [
'We rely on a small set of third-party processors. They handle data on our behalf under their own privacy commitments; we do not give them permission to use your data for their own purposes.',
'Stripe — payment processing and subscription management. Receives: name (if you provide), email, billing address (if you provide), and the card details you enter on their hosted checkout page. We never see your card number.',
'Stripe — payment processing and subscription management. Receives: name (if you provide it), email, billing address (if you provide it), and the card details you enter on their hosted checkout page. We never see your card number.',
'Supabase — authentication, database, and file storage. Receives: everything in the "Data we collect" section above. Supabase is our primary backend.',
'PostHog — product analytics. Receives: anonymized event data (page views, button clicks). IPs are anonymized before storage.',
'PostHog — product analytics. Receives: the named product events above (page views, feature usage) with basic device context. Autocapture is off.',
'Resend — transactional email (account confirmations, payment receipts, renewal reminders). Receives: your email address and the message contents.',
'Sentry — error monitoring. Receives: technical error reports (browser type, page, stack trace), which may include your IP address in transit. Used only to find and fix bugs.',
],
},
{
@@ -74,9 +79,10 @@ const SECTIONS: { title: string; body: string[]; emphasized?: boolean }[] = [
title: 'Your rights',
body: [
'Access: request a copy of your data at any time.',
'Deletion: request account and data deletion at privacy@vyndr.app — we comply within 30 days.',
'Deletion: request account and data deletion at [CONTACT EMAIL] — we comply within 30 days.',
'Correction: update your email and other profile data from the profile page.',
'Export: request a JSON export of your read history.',
'If you are in a jurisdiction with statutory privacy rights (for example the EEA, UK, or California), those rights apply to you and the requests above are how you exercise them with us.',
],
},
{
@@ -94,7 +100,7 @@ const SECTIONS: { title: string; body: string[]; emphasized?: boolean }[] = [
{
title: 'Contact',
body: [
'Privacy questions or data requests: privacy@vyndr.app',
'[ENTITY NAME]. Privacy questions or data requests: [CONTACT EMAIL].',
],
},
];
@@ -105,7 +111,7 @@ export default function PrivacyPage() {
<header style={{ marginBottom: 32 }}>
<h1 style={{ fontSize: 36, fontWeight: 700, letterSpacing: '-0.03em', marginBottom: 8 }}>Privacy Policy</h1>
<p className="mono" style={{ fontSize: 12, color: 'var(--text-tertiary)', letterSpacing: '0.05em' }}>
EFFECTIVE: MAY 2026
DRAFT: JULY 2026
</p>
</header>
{SECTIONS.map((s) => (
+182 -37
View File
@@ -2,70 +2,215 @@ import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Responsible Gambling',
description: 'VYNDR provides analytics, not bets. If gambling stops being fun, stop.',
description:
'VYNDR is an analytics tool, not a sportsbook. 21+. If gambling stops being fun, stop. Call or text 1-800-GAMBLER.',
};
// Session 2 (A1 board) — rebuilt sincerely per NORTH STAR v1.1: "Responsible
// gaming built sincerely. The company that lasts is the one users don't
// resent in five years." Server component. No marketing adjacency on this
// page — no pricing links, no upsell, no product pitch.
const STATE_RESOURCES: { state: string; phone: string; tel: string }[] = [
{ state: 'Arizona', phone: '1-800-NEXT-STEP', tel: '18006398783' },
{ state: 'Colorado', phone: '1-800-522-4700', tel: '18005224700' },
{ state: 'Illinois', phone: '1-800-GAMBLER', tel: '18004262537' },
{ state: 'Indiana', phone: '1-800-994-8448', tel: '18009948448' },
{ state: 'Kansas', phone: '1-800-522-4700', tel: '18005224700' },
{ state: 'Louisiana', phone: '1-877-770-7867', tel: '18777707867' },
{ state: 'Maryland', phone: '1-800-GAMBLER', tel: '18004262537' },
{ state: 'Massachusetts', phone: '1-800-327-5050', tel: '18003275050' },
{ state: 'Michigan', phone: '1-800-270-7117', tel: '18002707117' },
{ state: 'Nevada', phone: '1-800-522-4700', tel: '18005224700' },
{ state: 'New Jersey', phone: '1-800-GAMBLER', tel: '18004262537' },
{ state: 'New York', phone: '1-877-846-7369', tel: '18778467369' },
{ state: 'North Carolina', phone: '1-877-718-5543', tel: '18777185543' },
{ state: 'Ohio', phone: '1-800-589-9966', tel: '18005899966' },
{ state: 'Pennsylvania', phone: '1-800-GAMBLER', tel: '18004262537' },
{ state: 'Tennessee', phone: '1-800-889-9789', tel: '18008899789' },
{ state: 'Virginia', phone: '1-888-532-3500', tel: '18885323500' },
];
const WARNING_SIGNS = [
'Betting more than you planned, or more than you can afford to lose.',
'Chasing losses — betting bigger to win back what you dropped.',
'Hiding bets, or lying about them, to people you care about.',
'Betting with money meant for rent, bills, or debts.',
'Feeling restless or irritable when you try to cut back.',
'Gambling to escape stress, anxiety, or a bad day.',
'Borrowing money to bet.',
];
const h2: React.CSSProperties = { fontSize: 18, fontWeight: 700, marginBottom: 12, color: 'var(--text-0)' };
const body: React.CSSProperties = { color: 'var(--text-1)', lineHeight: 1.7, fontSize: 15 };
export default function ResponsibleGamblingPage() {
return (
<section style={{ maxWidth: 680, margin: '0 auto', padding: '48px 16px 120px' }}>
<header style={{ marginBottom: 32 }}>
<h1 style={{ fontSize: 36, fontWeight: 700, letterSpacing: '-0.03em', marginBottom: 8 }}>
If gambling stops being fun, stop.
<header style={{ marginBottom: 28 }}>
<h1 style={{ fontSize: 36, fontWeight: 700, letterSpacing: '-0.03em', marginBottom: 8, color: 'var(--text-0)' }}>
If it stops being fun, stop.
</h1>
<p className="mono" style={{ fontSize: 12, color: 'var(--text-tertiary)', letterSpacing: '0.05em' }}>
RESPONSIBLE GAMBLING
<p className="mono" style={{ fontSize: 12, color: 'var(--text-2)', letterSpacing: '0.05em' }}>
RESPONSIBLE GAMBLING · 21+
</p>
</header>
<div style={{ color: 'var(--text-secondary)', fontSize: 16, lineHeight: 1.7 }}>
<div style={{ ...body, fontSize: 16 }}>
<p style={{ marginBottom: 16 }}>
VYNDR provides sports analysis for informational purposes only. We do not take bets, facilitate wagers, or encourage gambling. We exist to help bettors make more informed decisions including the decision to walk away.
VYNDR is a sports data intelligence platform. We do not take bets, hold funds, or pay out
winnings. We are not a sportsbook. You must be 21 or older to use this product, and nothing
on it is a promise that any bet wins. Our own ledger shows the model missing, in public,
every week.
</p>
<p style={{ marginBottom: 16 }}>
Sports betting is entertainment. It should never feel like a job, a financial plan, or an escape. If you find yourself chasing losses, hiding bets from people you love, or betting more than you can afford to lose, those are warning signs that gambling has stopped being fun.
Sports betting is entertainment with a real cost attached. It should never feel like a job,
an income plan, or an escape. If it has started to feel like any of those, the most useful
thing this page can do is get you to the right phone number.
</p>
</div>
<section className="surface diagonal-cut" style={{ padding: 24, marginTop: 32, borderColor: 'var(--grade-a)' }}>
<h2 style={{ fontSize: 18, fontWeight: 700, marginBottom: 12 }}>Get help</h2>
<ul style={{ display: 'grid', gap: 12, fontSize: 15 }}>
{/* National helpline — the load-bearing element of this page. */}
<section
style={{
padding: 24,
marginTop: 24,
background: 'var(--bg-1)',
border: '1px solid var(--border)',
borderLeft: '3px solid var(--amber)',
borderRadius: 10,
}}
>
<h2 style={h2}>Get help now</h2>
<p style={{ ...body, marginBottom: 14 }}>
The National Problem Gambling Helpline. Call or text, 24/7, free, confidential. It routes
to trained counselors in your state.
</p>
<a
href="tel:18004262537"
className="mono"
style={{ color: 'var(--amber)', fontSize: 28, fontWeight: 700, textDecoration: 'none', letterSpacing: '0.02em' }}
>
1-800-GAMBLER
</a>
<div className="mono" style={{ fontSize: 13, color: 'var(--text-1)', marginTop: 4 }}>
(1-800-426-2537)
</div>
<ul style={{ display: 'grid', gap: 10, fontSize: 14, marginTop: 18, color: 'var(--text-1)' }}>
<li>
<strong style={{ color: 'var(--text-primary)' }}>National Council on Problem Gambling Helpline</strong>
<br />
<a href="tel:18005224700" style={{ color: 'var(--grade-a)', fontSize: 24, fontWeight: 700, fontFamily: 'var(--mono)' }}>
1-800-522-4700
</a>
<br />
<span style={{ color: 'var(--text-secondary)', fontSize: 13 }}>24/7, free, confidential.</span>
</li>
<li>
<a href="https://www.ncpgambling.org" target="_blank" rel="noopener noreferrer" style={{ color: 'var(--text-primary)' }}>
<a href="https://www.ncpgambling.org" target="_blank" rel="noopener noreferrer" style={{ color: 'var(--text-0)' }}>
ncpgambling.org
</a>
<br />
<span style={{ color: 'var(--text-secondary)', fontSize: 13 }}>Resources, support groups, self-assessment tools.</span>
</a>{' '}
National Council on Problem Gambling. Screening tools, chat, treatment directory.
</li>
<li>
<a href="https://www.gamblersanonymous.org" target="_blank" rel="noopener noreferrer" style={{ color: 'var(--text-primary)' }}>
<a href="https://www.gamblersanonymous.org" target="_blank" rel="noopener noreferrer" style={{ color: 'var(--text-0)' }}>
gamblersanonymous.org
</a>
<br />
<span style={{ color: 'var(--text-secondary)', fontSize: 13 }}>Local meetings nationwide.</span>
</a>{' '}
free local meetings nationwide.
</li>
<li>
<a href="https://www.gamtalk.org" target="_blank" rel="noopener noreferrer" style={{ color: 'var(--text-0)' }}>
gamtalk.org
</a>{' '}
free, moderated peer support, no signup required.
</li>
</ul>
</section>
<section style={{ marginTop: 32 }}>
<h2 style={{ fontSize: 18, fontWeight: 700, marginBottom: 12 }}>Self-exclusion</h2>
<p style={{ color: 'var(--text-secondary)', lineHeight: 1.7, fontSize: 15 }}>
Most US sportsbooks support a "self-exclusion" registry. You can voluntarily ban yourself from accessing sportsbook accounts for a period of months or years. Your state's gaming control board can help — search "[your state] gaming control board self-exclusion" to start.
<section style={{ marginTop: 36 }}>
<h2 style={h2}>Warning signs</h2>
<p style={{ ...body, marginBottom: 12 }}>
None of these mean you are a bad person. They mean the odds have started working on you
instead of for you.
</p>
<ul style={{ display: 'grid', gap: 8, ...body, paddingLeft: 18, listStyle: 'disc' }}>
{WARNING_SIGNS.map((s) => (
<li key={s}>{s}</li>
))}
</ul>
<p style={{ ...body, marginTop: 12 }}>
If two or more of these sound familiar, call the number above. The call costs nothing and
commits you to nothing.
</p>
</section>
<section style={{ marginTop: 32 }}>
<h2 style={{ fontSize: 18, fontWeight: 700, marginBottom: 12 }}>Our position</h2>
<p style={{ color: 'var(--text-secondary)', lineHeight: 1.7, fontSize: 15 }}>
We built VYNDR because we believe sports bettors deserve better tools than the books give them. We do not believe gambling makes anyone&apos;s life better when it stops being fun. If you need to walk away from sports betting entirely, that&apos;s the right call. Cancel your subscription, delete the app, and reach out to one of the resources above.
<section style={{ marginTop: 36 }}>
<h2 style={h2}>State resources</h2>
<p style={{ ...body, marginBottom: 14 }}>
Every state with legal sports betting funds its own problem-gambling services. If your
state is not listed, 1-800-GAMBLER still routes you to the right place.
</p>
<div style={{ background: 'var(--bg-1)', border: '1px solid var(--border)', borderRadius: 10, overflow: 'hidden' }}>
{STATE_RESOURCES.map((r, i) => (
<div
key={r.state}
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
gap: 12,
padding: '10px 16px',
borderTop: i === 0 ? 'none' : '1px solid var(--border)',
}}
>
<span style={{ fontSize: 14, color: 'var(--text-0)' }}>{r.state}</span>
<a href={`tel:${r.tel}`} className="mono" style={{ fontSize: 13, color: 'var(--text-1)', textDecoration: 'none' }}>
{r.phone}
</a>
</div>
))}
</div>
</section>
<section style={{ marginTop: 36 }}>
<h2 style={h2}>Self-exclusion</h2>
<p style={{ ...body, marginBottom: 12 }}>
Self-exclusion is a voluntary, binding ban from sportsbooks for a period you choose
usually one to five years, sometimes for life. It is run by your state, not by the books,
which is why it works.
</p>
<ul style={{ display: 'grid', gap: 8, ...body, paddingLeft: 18, listStyle: 'disc' }}>
<li>
Your state gaming board runs the registry. Search &quot;[your state] gaming board
self-exclusion&quot; in Michigan it is the Michigan Gaming Control Board&apos;s
Responsible Gaming Database.
</li>
<li>
Every licensed sportsbook also offers account-level tools: deposit limits, wager limits,
time-outs, and permanent closure. They are in the account settings the books keep quiet.
</li>
</ul>
</section>
<section style={{ marginTop: 36 }}>
<h2 style={h2}>Tools on VYNDR</h2>
<p style={{ ...body, marginBottom: 12 }}>
We are an analytics product, so our levers are smaller than a sportsbook&apos;s but they
exist, and they are yours.
</p>
<ul style={{ display: 'grid', gap: 8, ...body, paddingLeft: 18, listStyle: 'disc' }}>
<li>
<a href="/settings" style={{ color: 'var(--text-0)' }}>Settings Responsible Play</a>
set a weekly time limit on your account, or step away for a while.
</li>
<li>
<a href="/settings" style={{ color: 'var(--text-0)' }}>Settings Danger Zone</a>
delete your account permanently. Cancellation of any paid plan takes effect immediately
with it.
</li>
</ul>
</section>
<section style={{ marginTop: 36 }}>
<h2 style={h2}>Our position</h2>
<p style={body}>
We publish every grade our model produces, misses included, because we think honesty is
the only durable way to run this business. The same honesty applies here: no analytics
tool makes gambling safe, and no grade makes a bet a sure thing. If you need to walk away
from sports betting entirely, that is the right call and we mean it. Cancel the
subscription, delete the account, and use the number at the top of this page. It will
still be here.
</p>
</section>
</section>
+40 -18
View File
@@ -5,70 +5,93 @@ export const metadata: Metadata = {
description: 'VYNDR terms of service. Plain English. No tricks.',
};
// Session 2 (A1 board) — approval-pack draft. Entity details are placeholder
// tokens ([ENTITY NAME], [STATE OF FORMATION], [ARBITRATION VENUE],
// [CONTACT EMAIL]) for Kev to fill before this ships as the legal document.
const SECTIONS: { title: string; body: string[]; emphasized?: boolean }[] = [
{
title: 'What this is',
title: 'What this is — and is not',
body: [
'VYNDR provides sports analysis for informational purposes only. VYNDR does not facilitate, process, or encourage any wagers. VYNDR is not a sportsbook.',
'VYNDR Intelligence LLC operates this product. We grade player props using statistical models, historical data, and contextual intelligence.',
'VYNDR is a sports data intelligence platform. We publish statistical analysis, grades, and context on player props for informational and entertainment purposes only.',
'VYNDR is not a sportsbook. We do not accept, place, facilitate, broker, or process wagers of any kind. We do not hold gambling funds, set odds for wagering, or pay out winnings. No money you send us is ever a bet.',
'These terms are a contract between you and [ENTITY NAME], the company that operates VYNDR ("we," "us"). By creating an account or using the service you accept them.',
],
emphasized: true,
},
{
title: 'Who can use this',
body: [
'You must be 21 years of age or older to create an account. You must use VYNDR only where sports betting and the use of sports analytics tools is legal in your jurisdiction. You are responsible for following your local laws.',
'You must be 21 years of age or older to create an account. You must use VYNDR only where the use of sports analytics tools is legal in your jurisdiction, and you are responsible for knowing and following your local laws. We may close accounts that misrepresent age or location.',
],
},
{
title: 'No guaranteed outcomes',
body: [
'A grade is a probabilistic assessment. An "A" grade is not a guarantee, prediction, or promise. The model is wrong all the time — we publish the ledger so you can see how often. Past performance does not guarantee future results. Do not bet what you cannot afford to lose.',
'A grade is a probabilistic assessment, not a prediction, promise, or guarantee. The model is wrong regularly — we publish the Ledger, misses included, so you can see exactly how often. When the model has no projection for a prop, it refuses to grade rather than guess. Past performance does not guarantee future results. Nothing on VYNDR is financial, investment, or gambling advice. Never bet money you cannot afford to lose.',
],
},
{
title: 'Data sources and accuracy',
body: [
'Odds, lines, schedules, and statistics are sourced from third-party providers and public league data. They can be delayed, incomplete, or wrong, and lines move constantly. Always confirm the current line at the sportsbook before acting on anything you see here. Where our data is missing we show nothing rather than a fabricated value; absence of a number is deliberate.',
],
},
{
title: 'Subscription terms',
body: [
'Paid tiers (Analyst, Desk) are billed monthly through Stripe, our payment processor. You may cancel at any time from your profile page. Cancellation takes effect at the end of the current billing period. We do not refund for partial months. If a payment fails, we honor a 48-hour grace period before reverting your account to the free tier.',
'Founder pricing ($14.99/mo Analyst, $44.99/mo Desk) is locked for the lifetime of your continuous subscription. Lapsed subscriptions revert to standard pricing ($24.99 Analyst, $49.99 Desk) on re-subscription. After the first 100 founder seats are taken, new subscribers pay standard pricing.',
'We may change regular pricing with 30 days notice. Founder pricing is locked.',
'Paid tiers (Analyst, Desk) are billed monthly through Stripe, our payment processor. You may cancel at any time from your profile page; cancellation takes effect at the end of the current billing period. We do not refund partial months. If a payment fails, we honor a 48-hour grace period before reverting your account to the free tier.',
'Founder pricing ($14.99/mo Analyst, $44.99/mo Desk) is locked for the lifetime of your continuous subscription. A lapsed subscription reverts to standard pricing ($24.99 Analyst, $49.99 Desk) on re-subscription. After the first 100 founder seats are taken, new subscribers pay standard pricing.',
'We may change standard pricing with 30 days notice. Founder pricing is locked.',
],
},
{
title: 'Acceptable use',
body: [
'Do not scrape, reverse engineer, or attempt to replicate the grading engine. Do not resell reads, share account credentials, or attempt to circumvent the read limit. Do not use the service to abuse, harass, or defraud others.',
'VYNDR does NOT offer API access at any tier. The grading engine is consumer-only — we do not provide programmatic access to grades, factor weights, model outputs, or any other engine surface, regardless of plan or pricing. Requests for API access will be declined.',
'Do not scrape, reverse engineer, or attempt to replicate the grading engine. Do not resell reads, share account credentials, or attempt to circumvent the read limit. Do not use the service to abuse, harass, or defraud others, and do not use it in connection with unlawful gambling.',
'VYNDR does not offer API access at any tier. The grading engine is consumer-only — we do not provide programmatic access to grades, factor weights, model outputs, or any other engine surface, regardless of plan or pricing. Requests for API access will be declined.',
],
},
{
title: 'Intellectual property',
body: [
'The grading engine, models, calibration data, factor weights, and surrounding analysis are proprietary to VYNDR Intelligence LLC. You are licensed to view grades for personal use. You are not licensed to redistribute, repackage, or sell VYNDR output.',
'The grading engine, models, calibration data, factor weights, archetype system, and surrounding analysis are proprietary to [ENTITY NAME]. You are licensed to view grades for personal use. You are not licensed to redistribute, repackage, or sell VYNDR output.',
],
},
{
title: 'Termination',
body: [
'You can delete your account at any time from Settings. We may suspend or terminate accounts that violate these terms, with notice where practical. On termination your license to use the service ends; provisions that should survive (intellectual property, liability limits, dispute terms) survive.',
],
},
{
title: 'Limitation of liability',
body: [
'VYNDR is not responsible for any financial losses you incur from sports betting decisions you make using our analytics. The service is provided "as is" with no warranty. Maximum liability is limited to what you paid us in the prior 12 months.',
'VYNDR is not responsible for any financial losses you incur from sports betting decisions, whether or not they were informed by our analytics. The service is provided "as is" and "as available," with no warranty of any kind. To the maximum extent permitted by law, our total liability is limited to the amount you paid us in the 12 months before the claim.',
],
},
{
title: 'Governing law',
title: 'Governing law and disputes',
body: [
'These terms are governed by the laws of the State of Michigan. Any disputes will be resolved through binding arbitration in Wayne County, Michigan.',
'These terms are governed by the laws of [STATE OF FORMATION]. Disputes will be resolved through binding arbitration in [ARBITRATION VENUE], except where the law gives you a non-waivable right to court.',
],
},
{
title: 'Responsible gambling',
body: [
'Sports betting can become a problem. If gambling stops being fun, stop. The National Council on Problem Gambling helpline is available 24/7, free and confidential: 1-800-522-4700. More resources at ncpgambling.org. See our Responsible Gambling page for self-exclusion guidance.',
'Sports betting can become a problem. If it stops being fun, stop. The National Problem Gambling Helpline is available 24/7, free and confidential — call or text 1-800-GAMBLER (1-800-426-2537). Our Responsible Gambling page lists state resources, warning signs, and self-exclusion guidance.',
],
},
{
title: 'Changes to these terms',
body: [
'If we make material changes, we will notify account holders by email at least 30 days before they take effect. Continued use after that date is acceptance of the new terms.',
],
},
{
title: 'Contact',
body: [
'VYNDR Intelligence LLC. Questions about these terms: legal@vyndr.app',
'[ENTITY NAME]. Questions about these terms: [CONTACT EMAIL].',
],
},
];
@@ -77,7 +100,7 @@ export default function TermsPage() {
return (
<LegalLayout
title="Terms of Service"
effective="Effective: May 2026"
effective="Draft: July 2026"
sections={SECTIONS}
/>
);
@@ -100,7 +123,6 @@ function LegalLayout({ title, effective, sections }: { title: string; effective:
...(s.emphasized
? {
borderLeft: '3px solid var(--grade-a)',
paddingLeft: 16,
background: 'rgba(0, 212, 160, 0.04)',
borderRadius: 4,
padding: '12px 16px',
+2 -1
View File
@@ -17,6 +17,7 @@ const COLUMNS: { head: string; links: { label: string; href: string }[] }[] = [
head: 'COMPANY',
links: [
{ label: 'About', href: '/about' },
{ label: 'Methodology', href: '/methodology' },
{ label: 'The Report', href: '/blog' },
{ label: 'Help & FAQ', href: '/help' },
],
@@ -77,7 +78,7 @@ export default function Footer() {
>
<div style={{ ...mono, fontSize: 11, color: 'var(--text-2)' }}>
VYNDR is an analytics tool, not a sportsbook. Not financial advice. Gamble responsibly. 21+ ·{' '}
<a href="tel:18005224700" style={{ color: 'var(--amber)', textDecoration: 'none' }}>1-800-522-4700</a>
<a href="tel:18004262537" style={{ color: 'var(--amber)', textDecoration: 'none' }}>1-800-GAMBLER</a>
</div>
<div style={{ ...mono, fontSize: 11, color: 'var(--text-2)' }}>
BUILT BY KEVON BUTLER · DETROIT · © 2026 VYNDR
+1
View File
@@ -41,6 +41,7 @@ const OPEN_ROUTES = [
'/responsible-gambling',
'/help',
'/about',
'/methodology',
'/terms',
'/privacy',
'/login',