216 lines
7.2 KiB
Svelte
216 lines
7.2 KiB
Svelte
<script lang="ts">
|
|
import Navigation from '$lib/components/Navigation.svelte';
|
|
import { privacyPolicy } from '$lib/data/privacy-policy';
|
|
import type { LegalSectionLink } from '$lib/data/privacy-policy';
|
|
|
|
const navItems = [{ label: 'Home', href: '/', umamiEventLabel: 'home' }];
|
|
|
|
type BodySegment = string | { type: 'link'; href: string; label: string };
|
|
|
|
/** Splits a paragraph by link URLs and returns text/link segments for rendering. */
|
|
function linkify(para: string, links: LegalSectionLink[]): BodySegment[] {
|
|
const matches: { index: number; link: LegalSectionLink }[] = [];
|
|
for (const link of links) {
|
|
const idx = para.indexOf(link.href);
|
|
if (idx !== -1) matches.push({ index: idx, link });
|
|
}
|
|
matches.sort((a, b) => a.index - b.index);
|
|
const result: BodySegment[] = [];
|
|
let last = 0;
|
|
for (const { index, link } of matches) {
|
|
if (index > last) result.push(para.slice(last, index));
|
|
result.push({ type: 'link', href: link.href, label: link.label });
|
|
last = index + link.href.length;
|
|
}
|
|
if (last < para.length) result.push(para.slice(last));
|
|
return result.length ? result : [para];
|
|
}
|
|
</script>
|
|
|
|
<Navigation items={navItems} page="privacy-policy" />
|
|
|
|
<main id="main" class="legal-page">
|
|
<div class="container narrow">
|
|
<header id="header" class="legal-header">
|
|
<h1>{privacyPolicy.title}</h1>
|
|
<p class="legal-last-updated">Last updated: {privacyPolicy.lastUpdated}</p>
|
|
</header>
|
|
|
|
<div class="legal-content">
|
|
{#each privacyPolicy.intro as para}
|
|
<p>{para}</p>
|
|
{/each}
|
|
|
|
{#each privacyPolicy.sections as section (section.id)}
|
|
<section
|
|
id={section.id}
|
|
class="legal-section"
|
|
aria-labelledby={`${section.id}-heading`}
|
|
>
|
|
<h2 id={`${section.id}-heading`}>{section.heading}</h2>
|
|
{#each section.body as para}
|
|
<p>
|
|
{#if section.id === 'contact' && para === 'mifi Ventures LLC'}
|
|
<strong>{para}</strong>
|
|
{:else if section.id === 'contact' && para === 'legal@mifi.ventures'}
|
|
<a href="mailto:legal@mifi.ventures"
|
|
>legal@mifi.ventures</a
|
|
>
|
|
{:else if section.id === 'contact' && para === 'https://mifi.ventures'}
|
|
<a href="https://mifi.ventures" rel="noopener noreferrer"
|
|
>https://mifi.ventures</a
|
|
>
|
|
{:else if section.links}
|
|
{#each linkify(para, section.links) as segment}
|
|
{#if typeof segment === 'string'}
|
|
{segment}
|
|
{:else}
|
|
<a href={segment.href} rel="noopener noreferrer"
|
|
>{segment.label}</a
|
|
>
|
|
{/if}
|
|
{/each}
|
|
{:else}
|
|
{para}
|
|
{/if}
|
|
</p>
|
|
{/each}
|
|
{#if section.list}
|
|
<ul>
|
|
{#each section.list as item}
|
|
<li>{item}</li>
|
|
{/each}
|
|
</ul>
|
|
{/if}
|
|
{#if section.subsections}
|
|
{#each section.subsections as sub (sub.title)}
|
|
<div class="legal-subsection">
|
|
<h3>{sub.title}</h3>
|
|
{#each sub.body as para}
|
|
<p>{para}</p>
|
|
{/each}
|
|
{#if sub.list}
|
|
<ul>
|
|
{#each sub.list as item}
|
|
<li>{item}</li>
|
|
{/each}
|
|
</ul>
|
|
{/if}
|
|
</div>
|
|
{/each}
|
|
{/if}
|
|
</section>
|
|
{/each}
|
|
</div>
|
|
|
|
<nav class="legal-cross-links" aria-label="Related legal pages">
|
|
<a href="/terms-of-service">Terms of Service</a>
|
|
</nav>
|
|
</div>
|
|
</main>
|
|
|
|
<style>
|
|
.legal-page {
|
|
padding: var(--space-xxl) 0;
|
|
background-color: var(--color-bg);
|
|
}
|
|
|
|
.narrow {
|
|
max-width: var(--max-narrow-width);
|
|
margin: 0 auto;
|
|
padding: 0 var(--space-md);
|
|
}
|
|
|
|
.legal-header {
|
|
margin-bottom: var(--space-xl);
|
|
}
|
|
|
|
.legal-header h1 {
|
|
font-family: var(--font-family-heading);
|
|
font-size: var(--font-size-xxl);
|
|
font-weight: var(--font-weight-bold);
|
|
line-height: var(--line-height-heading);
|
|
color: var(--color-text);
|
|
margin: 0 0 var(--space-sm) 0;
|
|
}
|
|
|
|
.legal-last-updated {
|
|
font-size: var(--font-size-medium);
|
|
color: var(--color-text-tertiary);
|
|
margin: 0;
|
|
}
|
|
|
|
.legal-content {
|
|
font-size: var(--font-size-base);
|
|
line-height: var(--line-height-base);
|
|
color: var(--color-text);
|
|
}
|
|
|
|
.legal-content p {
|
|
margin: 0 0 var(--space-md) 0;
|
|
}
|
|
|
|
.legal-content a {
|
|
color: var(--color-primary);
|
|
text-decoration: underline;
|
|
text-underline-offset: 0.2em;
|
|
}
|
|
|
|
.legal-content a:hover {
|
|
color: var(--color-primary-hover);
|
|
}
|
|
|
|
.legal-section {
|
|
margin-bottom: var(--space-xl);
|
|
}
|
|
|
|
.legal-section h2 {
|
|
font-family: var(--font-family-heading);
|
|
font-size: var(--font-size-xl);
|
|
font-weight: var(--font-weight-semibold);
|
|
line-height: var(--line-height-tight);
|
|
color: var(--color-text);
|
|
margin: 0 0 var(--space-md) 0;
|
|
}
|
|
|
|
.legal-subsection {
|
|
margin-top: var(--space-lg);
|
|
}
|
|
|
|
.legal-subsection h3 {
|
|
font-family: var(--font-family-heading);
|
|
font-size: var(--font-size-large);
|
|
font-weight: var(--font-weight-semibold);
|
|
line-height: var(--line-height-tight);
|
|
color: var(--color-text);
|
|
margin: 0 0 var(--space-sm) 0;
|
|
}
|
|
|
|
.legal-section ul,
|
|
.legal-subsection ul {
|
|
margin: 0 0 var(--space-md) 0;
|
|
padding-left: var(--space-lg);
|
|
}
|
|
|
|
.legal-section li,
|
|
.legal-subsection li {
|
|
margin-bottom: var(--space-xs);
|
|
}
|
|
|
|
.legal-cross-links {
|
|
margin-top: var(--space-xxl);
|
|
padding-top: var(--space-xl);
|
|
border-top: 1px solid var(--color-border);
|
|
}
|
|
|
|
.legal-cross-links a {
|
|
color: var(--color-primary);
|
|
text-decoration: underline;
|
|
text-underline-offset: 0.2em;
|
|
}
|
|
|
|
.legal-cross-links a:hover {
|
|
color: var(--color-primary-hover);
|
|
}
|
|
</style>
|