@albionlabs/brochure-templates 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -0
- package/dist/assets/favicon.svg +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/registry.d.ts +4 -0
- package/dist/registry.js +16 -0
- package/dist/shared/styles/print-base.css +12 -0
- package/dist/templates/investor-pitch/InvestorPitchRenderer.svelte +101 -0
- package/dist/templates/investor-pitch/InvestorPitchRenderer.svelte.d.ts +7 -0
- package/dist/templates/investor-pitch/components/AssetLocation.svelte +143 -0
- package/dist/templates/investor-pitch/components/AssetLocation.svelte.d.ts +9 -0
- package/dist/templates/investor-pitch/components/DevelopmentTimeline.svelte +88 -0
- package/dist/templates/investor-pitch/components/DevelopmentTimeline.svelte.d.ts +8 -0
- package/dist/templates/investor-pitch/components/Footer.svelte +46 -0
- package/dist/templates/investor-pitch/components/Footer.svelte.d.ts +8 -0
- package/dist/templates/investor-pitch/components/Header.svelte +86 -0
- package/dist/templates/investor-pitch/components/Header.svelte.d.ts +9 -0
- package/dist/templates/investor-pitch/components/InvestmentThesis.svelte +43 -0
- package/dist/templates/investor-pitch/components/InvestmentThesis.svelte.d.ts +7 -0
- package/dist/templates/investor-pitch/components/KeyPartners.svelte +69 -0
- package/dist/templates/investor-pitch/components/KeyPartners.svelte.d.ts +8 -0
- package/dist/templates/investor-pitch/components/KeyRisks.svelte +48 -0
- package/dist/templates/investor-pitch/components/KeyRisks.svelte.d.ts +7 -0
- package/dist/templates/investor-pitch/components/PortfolioValueChart.svelte +150 -0
- package/dist/templates/investor-pitch/components/PortfolioValueChart.svelte.d.ts +11 -0
- package/dist/templates/investor-pitch/components/SensitivitySection.svelte +214 -0
- package/dist/templates/investor-pitch/components/SensitivitySection.svelte.d.ts +7 -0
- package/dist/templates/investor-pitch/components/ValuePropositions.svelte +71 -0
- package/dist/templates/investor-pitch/components/ValuePropositions.svelte.d.ts +8 -0
- package/dist/templates/investor-pitch/index.d.ts +5 -0
- package/dist/templates/investor-pitch/index.js +4 -0
- package/dist/templates/investor-pitch/meta.d.ts +2 -0
- package/dist/templates/investor-pitch/meta.js +7 -0
- package/dist/templates/investor-pitch/print.css +12 -0
- package/dist/templates/investor-pitch/sample.json +159 -0
- package/dist/templates/investor-pitch/schema.json +360 -0
- package/dist/templates/investor-pitch/types.d.ts +118 -0
- package/dist/templates/investor-pitch/types.js +1 -0
- package/dist/types.d.ts +16 -0
- package/dist/types.js +1 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# sv
|
|
2
|
+
|
|
3
|
+
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
|
|
4
|
+
|
|
5
|
+
## Creating a project
|
|
6
|
+
|
|
7
|
+
If you're seeing this, you've probably already done this step. Congrats!
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
# create a new project
|
|
11
|
+
npx sv create my-app
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
To recreate this project with the same configuration:
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
# recreate this project
|
|
18
|
+
npx sv create --template minimal --types ts --no-install investor-pitch
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Developing
|
|
22
|
+
|
|
23
|
+
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
npm run dev
|
|
27
|
+
|
|
28
|
+
# or start the server and open the app in a new browser tab
|
|
29
|
+
npm run dev -- --open
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Building
|
|
33
|
+
|
|
34
|
+
To create a production version of your app:
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
npm run build
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
You can preview the production build with `npm run preview`.
|
|
41
|
+
|
|
42
|
+
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="107" height="128" viewBox="0 0 107 128"><title>svelte-logo</title><path d="M94.157 22.819c-10.4-14.885-30.94-19.297-45.792-9.835L22.282 29.608A29.92 29.92 0 0 0 8.764 49.65a31.5 31.5 0 0 0 3.108 20.231 30 30 0 0 0-4.477 11.183 31.9 31.9 0 0 0 5.448 24.116c10.402 14.887 30.942 19.297 45.791 9.835l26.083-16.624A29.92 29.92 0 0 0 98.235 78.35a31.53 31.53 0 0 0-3.105-20.232 30 30 0 0 0 4.474-11.182 31.88 31.88 0 0 0-5.447-24.116" style="fill:#ff3e00"/><path d="M45.817 106.582a20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.503 18 18 0 0 1 .624-2.435l.49-1.498 1.337.981a33.6 33.6 0 0 0 10.203 5.098l.97.294-.09.968a5.85 5.85 0 0 0 1.052 3.878 6.24 6.24 0 0 0 6.695 2.485 5.8 5.8 0 0 0 1.603-.704L69.27 76.28a5.43 5.43 0 0 0 2.45-3.631 5.8 5.8 0 0 0-.987-4.371 6.24 6.24 0 0 0-6.698-2.487 5.7 5.7 0 0 0-1.6.704l-9.953 6.345a19 19 0 0 1-5.296 2.326 20.72 20.72 0 0 1-22.237-8.243 19.17 19.17 0 0 1-3.277-14.502 17.99 17.99 0 0 1 8.13-12.052l26.081-16.623a19 19 0 0 1 5.3-2.329 20.72 20.72 0 0 1 22.237 8.243 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-.624 2.435l-.49 1.498-1.337-.98a33.6 33.6 0 0 0-10.203-5.1l-.97-.294.09-.968a5.86 5.86 0 0 0-1.052-3.878 6.24 6.24 0 0 0-6.696-2.485 5.8 5.8 0 0 0-1.602.704L37.73 51.72a5.42 5.42 0 0 0-2.449 3.63 5.79 5.79 0 0 0 .986 4.372 6.24 6.24 0 0 0 6.698 2.486 5.8 5.8 0 0 0 1.602-.704l9.952-6.342a19 19 0 0 1 5.295-2.328 20.72 20.72 0 0 1 22.237 8.242 19.17 19.17 0 0 1 3.277 14.503 18 18 0 0 1-8.13 12.053l-26.081 16.622a19 19 0 0 1-5.3 2.328" style="fill:#fff"/></svg>
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { templateRegistry, getTemplate, listTemplates } from './registry.js';
|
|
2
|
+
export type { TemplateMeta, TemplateDefinition } from './types.js';
|
|
3
|
+
export { InvestorPitchRenderer, investorPitchMeta, investorPitchSchema, investorPitchSampleData } from './templates/investor-pitch/index.js';
|
|
4
|
+
export type { InvestorPitch } from './templates/investor-pitch/types.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { TemplateDefinition } from './types.js';
|
|
2
|
+
export declare const templateRegistry: Map<string, TemplateDefinition<any>>;
|
|
3
|
+
export declare function getTemplate(id: string): TemplateDefinition | undefined;
|
|
4
|
+
export declare function listTemplates(): TemplateDefinition[];
|
package/dist/registry.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { InvestorPitchRenderer, investorPitchMeta, investorPitchSchema, investorPitchSampleData } from './templates/investor-pitch/index.js';
|
|
2
|
+
const investorPitchTemplate = {
|
|
3
|
+
meta: investorPitchMeta,
|
|
4
|
+
renderer: InvestorPitchRenderer,
|
|
5
|
+
schema: investorPitchSchema,
|
|
6
|
+
sampleData: investorPitchSampleData
|
|
7
|
+
};
|
|
8
|
+
export const templateRegistry = new Map([
|
|
9
|
+
['investor-pitch', investorPitchTemplate]
|
|
10
|
+
]);
|
|
11
|
+
export function getTemplate(id) {
|
|
12
|
+
return templateRegistry.get(id);
|
|
13
|
+
}
|
|
14
|
+
export function listTemplates() {
|
|
15
|
+
return Array.from(templateRegistry.values());
|
|
16
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { InvestorPitch } from './types.js';
|
|
3
|
+
import Header from './components/Header.svelte';
|
|
4
|
+
import InvestmentThesis from './components/InvestmentThesis.svelte';
|
|
5
|
+
import ValuePropositions from './components/ValuePropositions.svelte';
|
|
6
|
+
import AssetLocation from './components/AssetLocation.svelte';
|
|
7
|
+
import PortfolioValueChart from './components/PortfolioValueChart.svelte';
|
|
8
|
+
import SensitivitySection from './components/SensitivitySection.svelte';
|
|
9
|
+
import DevelopmentTimeline from './components/DevelopmentTimeline.svelte';
|
|
10
|
+
import KeyPartners from './components/KeyPartners.svelte';
|
|
11
|
+
import KeyRisks from './components/KeyRisks.svelte';
|
|
12
|
+
import Footer from './components/Footer.svelte';
|
|
13
|
+
|
|
14
|
+
interface Props {
|
|
15
|
+
data: InvestorPitch;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let { data }: Props = $props();
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<div class="pitch-page">
|
|
22
|
+
<Header
|
|
23
|
+
companyName={data.company.name}
|
|
24
|
+
subtitle={data.company.subtitle}
|
|
25
|
+
metrics={data.keyMetrics}
|
|
26
|
+
/>
|
|
27
|
+
|
|
28
|
+
<div class="content-grid">
|
|
29
|
+
<!-- Left Column -->
|
|
30
|
+
<div class="col-left">
|
|
31
|
+
<InvestmentThesis
|
|
32
|
+
title={data.investmentThesis.title}
|
|
33
|
+
content={data.investmentThesis.content}
|
|
34
|
+
/>
|
|
35
|
+
<ValuePropositions
|
|
36
|
+
title={data.valuePropositions.title}
|
|
37
|
+
items={data.valuePropositions.items}
|
|
38
|
+
/>
|
|
39
|
+
<AssetLocation
|
|
40
|
+
title={data.assetLocation.title}
|
|
41
|
+
assetLabels={data.assetLocation.assetLabels}
|
|
42
|
+
stats={data.assetLocation.stats}
|
|
43
|
+
/>
|
|
44
|
+
<PortfolioValueChart
|
|
45
|
+
title={data.portfolioValue.title}
|
|
46
|
+
assets={data.portfolioValue.assets}
|
|
47
|
+
maxValue={data.portfolioValue.maxValue}
|
|
48
|
+
gridLines={data.portfolioValue.gridLines}
|
|
49
|
+
developmentProbabilities={data.portfolioValue.developmentProbabilities}
|
|
50
|
+
/>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<!-- Right Column -->
|
|
54
|
+
<div class="col-right">
|
|
55
|
+
<SensitivitySection data={data.priceSensitivity} />
|
|
56
|
+
<DevelopmentTimeline
|
|
57
|
+
title={data.developmentTimeline.title}
|
|
58
|
+
milestones={data.developmentTimeline.milestones}
|
|
59
|
+
/>
|
|
60
|
+
<KeyPartners
|
|
61
|
+
title={data.keyPartners.title}
|
|
62
|
+
partners={data.keyPartners.partners}
|
|
63
|
+
/>
|
|
64
|
+
<KeyRisks title={data.keyRisks.title} risks={data.keyRisks.risks} />
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<Footer items={data.footer.items} disclaimer={data.footer.disclaimer} />
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<style>
|
|
72
|
+
@import '../../shared/styles/print-base.css';
|
|
73
|
+
@import '../investor-pitch/print.css';
|
|
74
|
+
|
|
75
|
+
.pitch-page {
|
|
76
|
+
width: 100%;
|
|
77
|
+
max-width: 1060px;
|
|
78
|
+
background: #fff;
|
|
79
|
+
border-radius: 8px;
|
|
80
|
+
overflow: hidden;
|
|
81
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06), 0 4px 16px rgba(0, 0, 0, 0.04);
|
|
82
|
+
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
83
|
+
color: #0f172a;
|
|
84
|
+
-webkit-font-smoothing: antialiased;
|
|
85
|
+
-moz-osx-font-smoothing: grayscale;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.content-grid {
|
|
89
|
+
display: grid;
|
|
90
|
+
grid-template-columns: 1fr 1fr;
|
|
91
|
+
gap: 16px;
|
|
92
|
+
padding: 16px 24px;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.col-left,
|
|
96
|
+
.col-right {
|
|
97
|
+
display: flex;
|
|
98
|
+
flex-direction: column;
|
|
99
|
+
gap: 16px;
|
|
100
|
+
}
|
|
101
|
+
</style>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { InvestorPitch } from './types.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
data: InvestorPitch;
|
|
4
|
+
}
|
|
5
|
+
declare const InvestorPitchRenderer: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type InvestorPitchRenderer = ReturnType<typeof InvestorPitchRenderer>;
|
|
7
|
+
export default InvestorPitchRenderer;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { AssetLabel, AssetStat } from '../types.js';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
title: string;
|
|
6
|
+
assetLabels: AssetLabel[];
|
|
7
|
+
stats: AssetStat[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let { title, assetLabels, stats }: Props = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<section class="card">
|
|
14
|
+
<h2 class="section-title">{title}</h2>
|
|
15
|
+
<div class="location-grid">
|
|
16
|
+
<div class="map-container">
|
|
17
|
+
<svg viewBox="0 0 100 100" class="map-svg" xmlns="http://www.w3.org/2000/svg">
|
|
18
|
+
<!-- Simplified UK outline -->
|
|
19
|
+
<path
|
|
20
|
+
d="M 30,85 C 28,80 26,76 27,72 C 28,68 30,65 29,60 C 28,56 27,52 28,48
|
|
21
|
+
C 29,44 30,40 31,36 C 32,32 31,28 32,24 C 33,20 34,16 36,14
|
|
22
|
+
C 38,12 40,10 42,9 C 44,8 46,7 48,8 C 50,9 51,11 52,10
|
|
23
|
+
C 53,9 54,7 56,8 C 58,9 57,12 56,14 C 55,16 54,18 55,20
|
|
24
|
+
C 56,22 58,23 57,26 C 56,29 54,30 53,32 C 52,34 53,36 52,38
|
|
25
|
+
C 51,40 50,41 49,43 C 48,45 49,48 48,50 C 47,52 45,53 44,55
|
|
26
|
+
C 43,57 44,60 43,62 C 42,64 40,65 39,67 C 38,69 39,72 38,74
|
|
27
|
+
C 37,76 35,78 34,80 C 33,82 32,84 30,85 Z"
|
|
28
|
+
fill="#e2e8f0"
|
|
29
|
+
stroke="#94a3b8"
|
|
30
|
+
stroke-width="0.5"
|
|
31
|
+
/>
|
|
32
|
+
<!-- Scotland top -->
|
|
33
|
+
<path
|
|
34
|
+
d="M 36,14 C 34,12 33,10 35,8 C 37,6 39,5 41,6 C 43,7 42,9 42,9"
|
|
35
|
+
fill="#e2e8f0"
|
|
36
|
+
stroke="#94a3b8"
|
|
37
|
+
stroke-width="0.5"
|
|
38
|
+
/>
|
|
39
|
+
<!-- UKCS dashed rectangle -->
|
|
40
|
+
<rect
|
|
41
|
+
x="48"
|
|
42
|
+
y="12"
|
|
43
|
+
width="35"
|
|
44
|
+
height="42"
|
|
45
|
+
fill="none"
|
|
46
|
+
stroke="#94a3b8"
|
|
47
|
+
stroke-width="0.6"
|
|
48
|
+
stroke-dasharray="2,1.5"
|
|
49
|
+
rx="1"
|
|
50
|
+
/>
|
|
51
|
+
<text x="52" y="17" font-size="4.5" fill="#64748b" font-weight="600">UKCS</text>
|
|
52
|
+
|
|
53
|
+
<!-- Asset markers -->
|
|
54
|
+
{#each assetLabels as asset}
|
|
55
|
+
<circle cx={asset.x} cy={asset.y} r="2" fill="#0d9488" opacity="0.8" />
|
|
56
|
+
<text
|
|
57
|
+
x={asset.x + 3}
|
|
58
|
+
y={asset.y + 1.5}
|
|
59
|
+
font-size="4"
|
|
60
|
+
fill="#374151"
|
|
61
|
+
font-weight="500">{asset.name}</text
|
|
62
|
+
>
|
|
63
|
+
{/each}
|
|
64
|
+
</svg>
|
|
65
|
+
</div>
|
|
66
|
+
<div class="stats-grid">
|
|
67
|
+
{#each stats as stat}
|
|
68
|
+
<div class="stat-item">
|
|
69
|
+
<span class="stat-label">{stat.label}</span>
|
|
70
|
+
<span class="stat-value">{stat.value}</span>
|
|
71
|
+
<span class="stat-desc">{stat.description}</span>
|
|
72
|
+
</div>
|
|
73
|
+
{/each}
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
</section>
|
|
77
|
+
|
|
78
|
+
<style>
|
|
79
|
+
.card {
|
|
80
|
+
background: #fff;
|
|
81
|
+
border: 1px solid #e2e8f0;
|
|
82
|
+
border-radius: 8px;
|
|
83
|
+
padding: 20px 24px;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.section-title {
|
|
87
|
+
font-size: 14px;
|
|
88
|
+
font-weight: 700;
|
|
89
|
+
color: #0f172a;
|
|
90
|
+
letter-spacing: 0.5px;
|
|
91
|
+
text-transform: uppercase;
|
|
92
|
+
margin: 0 0 14px;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.location-grid {
|
|
96
|
+
display: grid;
|
|
97
|
+
grid-template-columns: 1fr 1fr;
|
|
98
|
+
gap: 16px;
|
|
99
|
+
align-items: start;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.map-container {
|
|
103
|
+
display: flex;
|
|
104
|
+
justify-content: center;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.map-svg {
|
|
108
|
+
width: 100%;
|
|
109
|
+
max-width: 180px;
|
|
110
|
+
height: auto;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.stats-grid {
|
|
114
|
+
display: grid;
|
|
115
|
+
grid-template-columns: 1fr 1fr;
|
|
116
|
+
gap: 16px;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.stat-item {
|
|
120
|
+
display: flex;
|
|
121
|
+
flex-direction: column;
|
|
122
|
+
align-items: center;
|
|
123
|
+
text-align: center;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.stat-label {
|
|
127
|
+
font-size: 11px;
|
|
128
|
+
color: #64748b;
|
|
129
|
+
font-weight: 500;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.stat-value {
|
|
133
|
+
font-size: 28px;
|
|
134
|
+
font-weight: 700;
|
|
135
|
+
color: #0f172a;
|
|
136
|
+
line-height: 1.2;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.stat-desc {
|
|
140
|
+
font-size: 11px;
|
|
141
|
+
color: #64748b;
|
|
142
|
+
}
|
|
143
|
+
</style>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AssetLabel, AssetStat } from '../types.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
title: string;
|
|
4
|
+
assetLabels: AssetLabel[];
|
|
5
|
+
stats: AssetStat[];
|
|
6
|
+
}
|
|
7
|
+
declare const AssetLocation: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type AssetLocation = ReturnType<typeof AssetLocation>;
|
|
9
|
+
export default AssetLocation;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { TimelineMilestone } from '../types.js';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
title: string;
|
|
6
|
+
milestones: TimelineMilestone[];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let { title, milestones }: Props = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<section class="card">
|
|
13
|
+
<h2 class="section-title">{title}</h2>
|
|
14
|
+
<div class="timeline">
|
|
15
|
+
<div class="timeline-track"></div>
|
|
16
|
+
{#each milestones as milestone, i}
|
|
17
|
+
<div class="milestone" style="left: {(i / (milestones.length - 1)) * 100}%">
|
|
18
|
+
<div class="dot" style="background: {milestone.color}"></div>
|
|
19
|
+
<div class="milestone-year">{milestone.year}</div>
|
|
20
|
+
<div class="milestone-label">{milestone.label}</div>
|
|
21
|
+
</div>
|
|
22
|
+
{/each}
|
|
23
|
+
</div>
|
|
24
|
+
</section>
|
|
25
|
+
|
|
26
|
+
<style>
|
|
27
|
+
.card {
|
|
28
|
+
background: #fff;
|
|
29
|
+
border: 1px solid #e2e8f0;
|
|
30
|
+
border-radius: 8px;
|
|
31
|
+
padding: 20px 24px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.section-title {
|
|
35
|
+
font-size: 14px;
|
|
36
|
+
font-weight: 700;
|
|
37
|
+
color: #0f172a;
|
|
38
|
+
letter-spacing: 0.5px;
|
|
39
|
+
text-transform: uppercase;
|
|
40
|
+
margin: 0 0 20px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.timeline {
|
|
44
|
+
position: relative;
|
|
45
|
+
height: 80px;
|
|
46
|
+
margin: 0 20px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.timeline-track {
|
|
50
|
+
position: absolute;
|
|
51
|
+
top: 8px;
|
|
52
|
+
left: 0;
|
|
53
|
+
right: 0;
|
|
54
|
+
height: 2px;
|
|
55
|
+
background: #e2e8f0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.milestone {
|
|
59
|
+
position: absolute;
|
|
60
|
+
transform: translateX(-50%);
|
|
61
|
+
display: flex;
|
|
62
|
+
flex-direction: column;
|
|
63
|
+
align-items: center;
|
|
64
|
+
width: max-content;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.dot {
|
|
68
|
+
width: 16px;
|
|
69
|
+
height: 16px;
|
|
70
|
+
border-radius: 50%;
|
|
71
|
+
flex-shrink: 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.milestone-year {
|
|
75
|
+
font-size: 14px;
|
|
76
|
+
font-weight: 700;
|
|
77
|
+
color: #0f172a;
|
|
78
|
+
margin-top: 8px;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.milestone-label {
|
|
82
|
+
font-size: 10.5px;
|
|
83
|
+
color: #64748b;
|
|
84
|
+
text-align: center;
|
|
85
|
+
line-height: 1.3;
|
|
86
|
+
white-space: pre-line;
|
|
87
|
+
}
|
|
88
|
+
</style>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TimelineMilestone } from '../types.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
title: string;
|
|
4
|
+
milestones: TimelineMilestone[];
|
|
5
|
+
}
|
|
6
|
+
declare const DevelopmentTimeline: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type DevelopmentTimeline = ReturnType<typeof DevelopmentTimeline>;
|
|
8
|
+
export default DevelopmentTimeline;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { FooterItem } from '../types.js';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
items: FooterItem[];
|
|
6
|
+
disclaimer: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let { items, disclaimer }: Props = $props();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<footer class="footer">
|
|
13
|
+
<p class="footer-meta">
|
|
14
|
+
{#each items as item, i}{#if i > 0}<span class="sep"> | </span>{/if}<strong>{item.label}:</strong> {item.value}{/each}
|
|
15
|
+
</p>
|
|
16
|
+
<p class="footer-disclaimer">{disclaimer}</p>
|
|
17
|
+
</footer>
|
|
18
|
+
|
|
19
|
+
<style>
|
|
20
|
+
.footer {
|
|
21
|
+
text-align: center;
|
|
22
|
+
padding: 20px 24px 16px;
|
|
23
|
+
border-top: 1px solid #e2e8f0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.footer-meta {
|
|
27
|
+
font-size: 12px;
|
|
28
|
+
color: #374151;
|
|
29
|
+
margin: 0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.footer-meta strong {
|
|
33
|
+
font-weight: 700;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.sep {
|
|
37
|
+
color: #94a3b8;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.footer-disclaimer {
|
|
41
|
+
font-size: 10.5px;
|
|
42
|
+
color: #94a3b8;
|
|
43
|
+
margin: 6px 0 0;
|
|
44
|
+
font-style: italic;
|
|
45
|
+
}
|
|
46
|
+
</style>
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { KeyMetric } from '../types.js';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
companyName: string;
|
|
6
|
+
subtitle: string;
|
|
7
|
+
metrics: KeyMetric[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let { companyName, subtitle, metrics }: Props = $props();
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<header class="header">
|
|
14
|
+
<h1 class="company-name">{companyName}</h1>
|
|
15
|
+
<p class="subtitle">{subtitle}</p>
|
|
16
|
+
</header>
|
|
17
|
+
|
|
18
|
+
<div class="metrics-bar">
|
|
19
|
+
{#each metrics as metric}
|
|
20
|
+
<div class="metric">
|
|
21
|
+
<span class="metric-label">{metric.label}</span>
|
|
22
|
+
<span class="metric-value" class:highlight={metric.highlight}>{metric.value}</span>
|
|
23
|
+
</div>
|
|
24
|
+
{/each}
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<style>
|
|
28
|
+
.header {
|
|
29
|
+
background: #1a2332;
|
|
30
|
+
padding: 24px 32px 20px;
|
|
31
|
+
text-align: center;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.company-name {
|
|
35
|
+
color: #fff;
|
|
36
|
+
font-size: 28px;
|
|
37
|
+
font-weight: 800;
|
|
38
|
+
letter-spacing: 1.5px;
|
|
39
|
+
margin: 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.subtitle {
|
|
43
|
+
color: #94a3b8;
|
|
44
|
+
font-size: 13px;
|
|
45
|
+
margin: 6px 0 0;
|
|
46
|
+
letter-spacing: 0.3px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.metrics-bar {
|
|
50
|
+
display: grid;
|
|
51
|
+
grid-template-columns: repeat(6, 1fr);
|
|
52
|
+
gap: 0;
|
|
53
|
+
padding: 16px 24px;
|
|
54
|
+
background: #fff;
|
|
55
|
+
border-bottom: 1px solid #e2e8f0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.metric {
|
|
59
|
+
display: flex;
|
|
60
|
+
flex-direction: column;
|
|
61
|
+
align-items: center;
|
|
62
|
+
padding: 8px 12px;
|
|
63
|
+
border: 1px solid #e2e8f0;
|
|
64
|
+
border-radius: 8px;
|
|
65
|
+
margin: 0 4px;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.metric-label {
|
|
69
|
+
font-size: 10px;
|
|
70
|
+
font-weight: 500;
|
|
71
|
+
color: #64748b;
|
|
72
|
+
letter-spacing: 0.5px;
|
|
73
|
+
text-transform: uppercase;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.metric-value {
|
|
77
|
+
font-size: 22px;
|
|
78
|
+
font-weight: 700;
|
|
79
|
+
color: #0f172a;
|
|
80
|
+
margin-top: 2px;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.metric-value.highlight {
|
|
84
|
+
color: #10b981;
|
|
85
|
+
}
|
|
86
|
+
</style>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { KeyMetric } from '../types.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
companyName: string;
|
|
4
|
+
subtitle: string;
|
|
5
|
+
metrics: KeyMetric[];
|
|
6
|
+
}
|
|
7
|
+
declare const Header: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type Header = ReturnType<typeof Header>;
|
|
9
|
+
export default Header;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
title: string;
|
|
4
|
+
content: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
let { title, content }: Props = $props();
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<section class="card">
|
|
11
|
+
<h2 class="section-title">{title}</h2>
|
|
12
|
+
<p class="thesis-content">{@html content}</p>
|
|
13
|
+
</section>
|
|
14
|
+
|
|
15
|
+
<style>
|
|
16
|
+
.card {
|
|
17
|
+
background: #fff;
|
|
18
|
+
border: 1px solid #e2e8f0;
|
|
19
|
+
border-radius: 8px;
|
|
20
|
+
padding: 20px 24px;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.section-title {
|
|
24
|
+
font-size: 14px;
|
|
25
|
+
font-weight: 700;
|
|
26
|
+
color: #0f172a;
|
|
27
|
+
letter-spacing: 0.5px;
|
|
28
|
+
text-transform: uppercase;
|
|
29
|
+
margin: 0 0 14px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.thesis-content {
|
|
33
|
+
font-size: 14px;
|
|
34
|
+
line-height: 1.6;
|
|
35
|
+
color: #374151;
|
|
36
|
+
margin: 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.thesis-content :global(strong) {
|
|
40
|
+
color: #0f172a;
|
|
41
|
+
font-weight: 700;
|
|
42
|
+
}
|
|
43
|
+
</style>
|