Initial commit: Astro speaker site with Forgejo Actions CI/CD
Some checks are pending
Build and Deploy to Storj / build-and-deploy (push) Waiting to run
Some checks are pending
Build and Deploy to Storj / build-and-deploy (push) Waiting to run
This commit is contained in:
commit
3705631510
41 changed files with 9096 additions and 0 deletions
31
.astro/collections/blog.schema.json
Normal file
31
.astro/collections/blog.schema.json
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"title": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"date": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"default": [],
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"$schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"title",
|
||||||
|
"description",
|
||||||
|
"date"
|
||||||
|
]
|
||||||
|
}
|
||||||
37
.astro/collections/talks.schema.json
Normal file
37
.astro/collections/talks.schema.json
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"title": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"premise": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"duration": {
|
||||||
|
"default": "45–60 min",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"audience": {
|
||||||
|
"default": [],
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"takeaways": {
|
||||||
|
"default": [],
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"$schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"title",
|
||||||
|
"premise"
|
||||||
|
]
|
||||||
|
}
|
||||||
1
.astro/content-assets.mjs
Normal file
1
.astro/content-assets.mjs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export default new Map();
|
||||||
1
.astro/content-modules.mjs
Normal file
1
.astro/content-modules.mjs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export default new Map();
|
||||||
170
.astro/content.d.ts
vendored
Normal file
170
.astro/content.d.ts
vendored
Normal file
|
|
@ -0,0 +1,170 @@
|
||||||
|
declare module 'astro:content' {
|
||||||
|
export interface RenderResult {
|
||||||
|
Content: import('astro/runtime/server/index.js').AstroComponentFactory;
|
||||||
|
headings: import('astro').MarkdownHeading[];
|
||||||
|
remarkPluginFrontmatter: Record<string, any>;
|
||||||
|
}
|
||||||
|
interface Render {
|
||||||
|
'.md': Promise<RenderResult>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RenderedContent {
|
||||||
|
html: string;
|
||||||
|
metadata?: {
|
||||||
|
imagePaths: Array<string>;
|
||||||
|
[key: string]: unknown;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
type Flatten<T> = T extends { [K: string]: infer U } ? U : never;
|
||||||
|
|
||||||
|
export type CollectionKey = keyof DataEntryMap;
|
||||||
|
export type CollectionEntry<C extends CollectionKey> = Flatten<DataEntryMap[C]>;
|
||||||
|
|
||||||
|
type AllValuesOf<T> = T extends any ? T[keyof T] : never;
|
||||||
|
|
||||||
|
export type ReferenceDataEntry<
|
||||||
|
C extends CollectionKey,
|
||||||
|
E extends keyof DataEntryMap[C] = string,
|
||||||
|
> = {
|
||||||
|
collection: C;
|
||||||
|
id: E;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ReferenceLiveEntry<C extends keyof LiveContentConfig['collections']> = {
|
||||||
|
collection: C;
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getCollection<C extends keyof DataEntryMap, E extends CollectionEntry<C>>(
|
||||||
|
collection: C,
|
||||||
|
filter?: (entry: CollectionEntry<C>) => entry is E,
|
||||||
|
): Promise<E[]>;
|
||||||
|
export function getCollection<C extends keyof DataEntryMap>(
|
||||||
|
collection: C,
|
||||||
|
filter?: (entry: CollectionEntry<C>) => unknown,
|
||||||
|
): Promise<CollectionEntry<C>[]>;
|
||||||
|
|
||||||
|
export function getLiveCollection<C extends keyof LiveContentConfig['collections']>(
|
||||||
|
collection: C,
|
||||||
|
filter?: LiveLoaderCollectionFilterType<C>,
|
||||||
|
): Promise<
|
||||||
|
import('astro').LiveDataCollectionResult<LiveLoaderDataType<C>, LiveLoaderErrorType<C>>
|
||||||
|
>;
|
||||||
|
|
||||||
|
export function getEntry<
|
||||||
|
C extends keyof DataEntryMap,
|
||||||
|
E extends keyof DataEntryMap[C] | (string & {}),
|
||||||
|
>(
|
||||||
|
entry: ReferenceDataEntry<C, E>,
|
||||||
|
): E extends keyof DataEntryMap[C]
|
||||||
|
? Promise<DataEntryMap[C][E]>
|
||||||
|
: Promise<CollectionEntry<C> | undefined>;
|
||||||
|
export function getEntry<
|
||||||
|
C extends keyof DataEntryMap,
|
||||||
|
E extends keyof DataEntryMap[C] | (string & {}),
|
||||||
|
>(
|
||||||
|
collection: C,
|
||||||
|
id: E,
|
||||||
|
): E extends keyof DataEntryMap[C]
|
||||||
|
? string extends keyof DataEntryMap[C]
|
||||||
|
? Promise<DataEntryMap[C][E]> | undefined
|
||||||
|
: Promise<DataEntryMap[C][E]>
|
||||||
|
: Promise<CollectionEntry<C> | undefined>;
|
||||||
|
export function getLiveEntry<C extends keyof LiveContentConfig['collections']>(
|
||||||
|
collection: C,
|
||||||
|
filter: string | LiveLoaderEntryFilterType<C>,
|
||||||
|
): Promise<import('astro').LiveDataEntryResult<LiveLoaderDataType<C>, LiveLoaderErrorType<C>>>;
|
||||||
|
|
||||||
|
/** Resolve an array of entry references from the same collection */
|
||||||
|
export function getEntries<C extends keyof DataEntryMap>(
|
||||||
|
entries: ReferenceDataEntry<C, keyof DataEntryMap[C]>[],
|
||||||
|
): Promise<CollectionEntry<C>[]>;
|
||||||
|
|
||||||
|
export function render<C extends keyof DataEntryMap>(
|
||||||
|
entry: DataEntryMap[C][string],
|
||||||
|
): Promise<RenderResult>;
|
||||||
|
|
||||||
|
export function reference<
|
||||||
|
C extends
|
||||||
|
| keyof DataEntryMap
|
||||||
|
// Allow generic `string` to avoid excessive type errors in the config
|
||||||
|
// if `dev` is not running to update as you edit.
|
||||||
|
// Invalid collection names will be caught at build time.
|
||||||
|
| (string & {}),
|
||||||
|
>(
|
||||||
|
collection: C,
|
||||||
|
): import('astro/zod').ZodPipe<
|
||||||
|
import('astro/zod').ZodString,
|
||||||
|
import('astro/zod').ZodTransform<
|
||||||
|
C extends keyof DataEntryMap
|
||||||
|
? {
|
||||||
|
collection: C;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
: never,
|
||||||
|
string
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
|
||||||
|
type ReturnTypeOrOriginal<T> = T extends (...args: any[]) => infer R ? R : T;
|
||||||
|
type InferEntrySchema<C extends keyof DataEntryMap> = import('astro/zod').infer<
|
||||||
|
ReturnTypeOrOriginal<Required<ContentConfig['collections'][C]>['schema']>
|
||||||
|
>;
|
||||||
|
type ExtractLoaderConfig<T> = T extends { loader: infer L } ? L : never;
|
||||||
|
type InferLoaderSchema<
|
||||||
|
C extends keyof DataEntryMap,
|
||||||
|
L = ExtractLoaderConfig<ContentConfig['collections'][C]>,
|
||||||
|
> = L extends { schema: import('astro/zod').ZodSchema }
|
||||||
|
? import('astro/zod').infer<L['schema']>
|
||||||
|
: any;
|
||||||
|
|
||||||
|
type DataEntryMap = {
|
||||||
|
"blog": Record<string, {
|
||||||
|
id: string;
|
||||||
|
body?: string;
|
||||||
|
collection: "blog";
|
||||||
|
data: InferEntrySchema<"blog">;
|
||||||
|
rendered?: RenderedContent;
|
||||||
|
filePath?: string;
|
||||||
|
}>;
|
||||||
|
"talks": Record<string, {
|
||||||
|
id: string;
|
||||||
|
body?: string;
|
||||||
|
collection: "talks";
|
||||||
|
data: InferEntrySchema<"talks">;
|
||||||
|
rendered?: RenderedContent;
|
||||||
|
filePath?: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
type ExtractLoaderTypes<T> = T extends import('astro/loaders').LiveLoader<
|
||||||
|
infer TData,
|
||||||
|
infer TEntryFilter,
|
||||||
|
infer TCollectionFilter,
|
||||||
|
infer TError
|
||||||
|
>
|
||||||
|
? { data: TData; entryFilter: TEntryFilter; collectionFilter: TCollectionFilter; error: TError }
|
||||||
|
: { data: never; entryFilter: never; collectionFilter: never; error: never };
|
||||||
|
type ExtractEntryFilterType<T> = ExtractLoaderTypes<T>['entryFilter'];
|
||||||
|
type ExtractCollectionFilterType<T> = ExtractLoaderTypes<T>['collectionFilter'];
|
||||||
|
type ExtractErrorType<T> = ExtractLoaderTypes<T>['error'];
|
||||||
|
|
||||||
|
type LiveLoaderDataType<C extends keyof LiveContentConfig['collections']> =
|
||||||
|
LiveContentConfig['collections'][C]['schema'] extends undefined
|
||||||
|
? ExtractDataType<LiveContentConfig['collections'][C]['loader']>
|
||||||
|
: import('astro/zod').infer<
|
||||||
|
Exclude<LiveContentConfig['collections'][C]['schema'], undefined>
|
||||||
|
>;
|
||||||
|
type LiveLoaderEntryFilterType<C extends keyof LiveContentConfig['collections']> =
|
||||||
|
ExtractEntryFilterType<LiveContentConfig['collections'][C]['loader']>;
|
||||||
|
type LiveLoaderCollectionFilterType<C extends keyof LiveContentConfig['collections']> =
|
||||||
|
ExtractCollectionFilterType<LiveContentConfig['collections'][C]['loader']>;
|
||||||
|
type LiveLoaderErrorType<C extends keyof LiveContentConfig['collections']> = ExtractErrorType<
|
||||||
|
LiveContentConfig['collections'][C]['loader']
|
||||||
|
>;
|
||||||
|
|
||||||
|
export type ContentConfig = typeof import("../src/content.config.js");
|
||||||
|
export type LiveContentConfig = never;
|
||||||
|
}
|
||||||
2
.astro/types.d.ts
vendored
Normal file
2
.astro/types.d.ts
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
/// <reference types="astro/client" />
|
||||||
|
/// <reference path="content.d.ts" />
|
||||||
46
.forgejo/workflows/deploy.yml
Normal file
46
.forgejo/workflows/deploy.yml
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
name: Build and Deploy to Storj
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Install rclone
|
||||||
|
run: |
|
||||||
|
curl https://rclone.org/install.sh | bash
|
||||||
|
|
||||||
|
- name: Configure rclone
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.config/rclone
|
||||||
|
cat > ~/.config/rclone/rclone.conf << 'EOF'
|
||||||
|
[storj]
|
||||||
|
type = s3
|
||||||
|
provider = Storj
|
||||||
|
access_key_id = ${{ secrets.STORJ_ACCESS_KEY }}
|
||||||
|
secret_access_key = ${{ secrets.STORJ_SECRET_KEY }}
|
||||||
|
endpoint = https://gateway.storjshare.io
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Deploy to Storj
|
||||||
|
run: |
|
||||||
|
rclone sync ./dist/ storj:${{ secrets.STORJ_BUCKET }}/ --progress
|
||||||
|
rclone sync ./public/downloads/ storj:${{ secrets.STORJ_BUCKET }}/downloads/ --progress
|
||||||
26
.gitignore
vendored
Normal file
26
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Build output
|
||||||
|
dist/
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
|
||||||
|
# PDF output (compiled from .typ)
|
||||||
|
one-sheet.pdf
|
||||||
0
EOF
Normal file
0
EOF
Normal file
64
README.md
Normal file
64
README.md
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
# Scott Scoble — Speaker Website
|
||||||
|
|
||||||
|
Professional speaker/consultant website for Scott Scoble.
|
||||||
|
|
||||||
|
## Stack
|
||||||
|
|
||||||
|
- **Framework:** Astro 5
|
||||||
|
- **Hosting:** Storj (S3-compatible static hosting)
|
||||||
|
- **Domain:** scott.scoble.me
|
||||||
|
- **CI/CD:** Forgejo Actions
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Output goes to `dist/`.
|
||||||
|
|
||||||
|
## Deploy
|
||||||
|
|
||||||
|
Deployment is automatic on push to `main` via Forgejo Actions.
|
||||||
|
|
||||||
|
### Manual Setup
|
||||||
|
|
||||||
|
1. Add secrets to Forgejo repo:
|
||||||
|
- `STORJ_ACCESS_KEY` — Storj S3 access key
|
||||||
|
- `STORJ_SECRET_KEY` — Storj S3 secret key
|
||||||
|
- `STORJ_BUCKET` — Bucket name (e.g., `brand-site`)
|
||||||
|
|
||||||
|
2. Ensure bucket exists in Storj with public access and custom domain configured.
|
||||||
|
|
||||||
|
## PDF Generation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nix-shell -p typst --run "typst compile one-sheet.typ one-sheet.pdf"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
components/ # Reusable Astro components
|
||||||
|
layouts/ # Page layouts
|
||||||
|
pages/ # Route pages
|
||||||
|
content/ # Content collections (future)
|
||||||
|
styles/ # Global CSS
|
||||||
|
public/
|
||||||
|
images/ # Static images
|
||||||
|
downloads/ # Downloadable files (PDFs)
|
||||||
|
.forgejo/
|
||||||
|
workflows/ # CI/CD workflows
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
11
astro.config.mjs
Normal file
11
astro.config.mjs
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
// @ts-check
|
||||||
|
import { defineConfig } from 'astro/config';
|
||||||
|
|
||||||
|
// https://astro.build/config
|
||||||
|
export default defineConfig({
|
||||||
|
site: 'https://scott.scoble.me',
|
||||||
|
output: 'static',
|
||||||
|
build: {
|
||||||
|
inlineStylesheets: 'auto',
|
||||||
|
},
|
||||||
|
});
|
||||||
132
one-sheet.typ
Normal file
132
one-sheet.typ
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
#set page(
|
||||||
|
width: 8.5in,
|
||||||
|
height: 11in,
|
||||||
|
margin: 0.75in,
|
||||||
|
)
|
||||||
|
|
||||||
|
#set text(
|
||||||
|
font: "Libertinus Serif",
|
||||||
|
size: 11pt,
|
||||||
|
fill: rgb(45, 42, 36),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Color palette
|
||||||
|
#let brown-dark = rgb(45, 42, 36)
|
||||||
|
#let brown = rgb(74, 68, 56)
|
||||||
|
#let green = rgb(61, 90, 62)
|
||||||
|
#let amber = rgb(200, 149, 46)
|
||||||
|
#let cream = rgb(250, 248, 245)
|
||||||
|
|
||||||
|
// Header
|
||||||
|
#align(center)[
|
||||||
|
#text(size: 28pt, weight: 600, fill: brown-dark)[Scott Scoble]
|
||||||
|
|
||||||
|
#v(6pt)
|
||||||
|
|
||||||
|
#text(size: 14pt, style: "italic", fill: brown)[
|
||||||
|
The human cultivation expert for the AI age
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(24pt)
|
||||||
|
|
||||||
|
// Two column layout
|
||||||
|
#grid(
|
||||||
|
columns: (1fr, 1.8fr),
|
||||||
|
gutter: 24pt,
|
||||||
|
[
|
||||||
|
// Left column - photo placeholder
|
||||||
|
#align(center)[
|
||||||
|
#box(
|
||||||
|
width: 100%,
|
||||||
|
height: 1.8in,
|
||||||
|
fill: rgb(230, 228, 225),
|
||||||
|
radius: 4pt,
|
||||||
|
align(center + horizon)[
|
||||||
|
#text(size: 10pt, fill: brown)[Photo placeholder]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
#v(16pt)
|
||||||
|
|
||||||
|
#text(size: 9pt, fill: brown)[
|
||||||
|
Keynote Speaker • Consultant • Author
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(12pt)
|
||||||
|
|
||||||
|
#text(size: 10pt, weight: 600, fill: green)[Booking]
|
||||||
|
#v(4pt)
|
||||||
|
#text(size: 9pt)[
|
||||||
|
scott.scoble.me
|
||||||
|
|
||||||
|
scott"@"scoble.me
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(12pt)
|
||||||
|
|
||||||
|
#text(size: 10pt, weight: 600, fill: green)[Audience]
|
||||||
|
#v(4pt)
|
||||||
|
#text(size: 9pt)[
|
||||||
|
Engineering leaders, CTOs, VP Engineering, People leaders
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(12pt)
|
||||||
|
|
||||||
|
#text(size: 10pt, weight: 600, fill: green)[Format]
|
||||||
|
#v(4pt)
|
||||||
|
#text(size: 9pt)[
|
||||||
|
Keynotes: 45–60 min
|
||||||
|
|
||||||
|
Workshops: Half-day or full-day
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
// Right column - talks
|
||||||
|
#text(size: 13pt, weight: 600, fill: brown-dark)[Signature Talks]
|
||||||
|
|
||||||
|
#v(12pt)
|
||||||
|
|
||||||
|
#text(size: 11pt, weight: 600, fill: brown)[50 First Dates with AI]
|
||||||
|
#v(2pt)
|
||||||
|
#text(size: 9.5pt, fill: brown)[
|
||||||
|
Current AI memory architecture is anterograde amnesia — and we're all Henry Roth, recording VHS tapes every night so our agent can wake up functional tomorrow. This talk covers why your AI's "memory" is actually just replay, not learning, and the three-layer architecture that actually compounds.
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(10pt)
|
||||||
|
|
||||||
|
#text(size: 11pt, weight: 600, fill: brown)[From Strip-Mining to Cultivation]
|
||||||
|
#v(2pt)
|
||||||
|
#text(size: 9.5pt, fill: brown)[
|
||||||
|
The shift from extraction to cultivation in AI-era teams. Why throughput optimization is killing your soil health. The most successful AI teams aren't the ones with the best models — they're the ones who stopped strip-mining their humans and started cultivating them.
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(10pt)
|
||||||
|
|
||||||
|
#text(size: 11pt, weight: 600, fill: brown)[The Soil Under Your Team]
|
||||||
|
#v(2pt)
|
||||||
|
#text(size: 9.5pt, fill: brown)[
|
||||||
|
Diagnose what's actually depleted before you fertilize. A diagnostic framework for team health. Most team interventions fail because they prescribe before diagnosing. This workshop gives you a cultivation assessment framework that finds what's actually depleted.
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(16pt)
|
||||||
|
|
||||||
|
#text(size: 11pt, weight: 600, fill: amber)[What People Say]
|
||||||
|
#v(6pt)
|
||||||
|
#text(size: 9pt, style: "italic", fill: brown)[
|
||||||
|
"Scott has a rare ability to diagnose team dynamics quickly and prescribe actionable solutions. His cultivation framework changed how we think about AI adoption."
|
||||||
|
]
|
||||||
|
#v(2pt)
|
||||||
|
#text(size: 8.5pt, fill: brown)[— Engineering Leader, Tech Company]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
#v(1fr)
|
||||||
|
|
||||||
|
// Footer
|
||||||
|
#align(center)[
|
||||||
|
#text(size: 8pt, fill: brown)[
|
||||||
|
scott.scoble.me • scott"@"scoble.me
|
||||||
|
]
|
||||||
|
]
|
||||||
4736
package-lock.json
generated
Normal file
4736
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
17
package.json
Normal file
17
package.json
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"name": "brand-site-astro",
|
||||||
|
"type": "module",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=22.12.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"dev": "astro dev",
|
||||||
|
"build": "astro build",
|
||||||
|
"preview": "astro preview",
|
||||||
|
"astro": "astro"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"astro": "^6.1.10"
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 655 B |
4
public/favicon.svg
Normal file
4
public/favicon.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||||
|
<rect width="100" height="100" rx="16" fill="#3d5a3e"/>
|
||||||
|
<text x="50" y="68" font-family="Georgia, serif" font-size="52" font-weight="bold" fill="#faf8f5" text-anchor="middle">S</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 258 B |
64
public/images/hero-speaker.svg
Normal file
64
public/images/hero-speaker.svg
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600" preserveAspectRatio="xMidYMid slice">
|
||||||
|
<!-- Simple dark background -->
|
||||||
|
<rect width="800" height="600" fill="#1a1815"/>
|
||||||
|
|
||||||
|
<!-- Subtle stage floor -->
|
||||||
|
<rect x="0" y="450" width="800" height="150" fill="#0d0c0b"/>
|
||||||
|
|
||||||
|
<!-- Spotlight circle on floor -->
|
||||||
|
<ellipse cx="400" cy="500" rx="180" ry="40" fill="#2a2620"/>
|
||||||
|
|
||||||
|
<!-- Audience silhouettes -- simple shapes -->
|
||||||
|
<g fill="#151412">
|
||||||
|
<!-- Row 1 -->
|
||||||
|
<circle cx="150" cy="420" r="20"/>
|
||||||
|
<circle cx="220" cy="415" r="22"/>
|
||||||
|
<circle cx="300" cy="418" r="21"/>
|
||||||
|
<circle cx="380" cy="412" r="23"/>
|
||||||
|
<circle cx="460" cy="416" r="22"/>
|
||||||
|
<circle cx="540" cy="419" r="21"/>
|
||||||
|
<circle cx="620" cy="422" r="20"/>
|
||||||
|
<circle cx="700" cy="425" r="19"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<g fill="#1c1915">
|
||||||
|
<!-- Row 2 (closer) -->
|
||||||
|
<circle cx="180" cy="380" r="24"/>
|
||||||
|
<circle cx="270" cy="375" r="26"/>
|
||||||
|
<circle cx="370" cy="372" r="27"/>
|
||||||
|
<circle cx="470" cy="376" r="26"/>
|
||||||
|
<circle cx="570" cy="380" r="25"/>
|
||||||
|
<circle cx="660" cy="384" r="24"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Speaker silhouette -->
|
||||||
|
<g fill="#0a0908">
|
||||||
|
<!-- Body/shoulders -->
|
||||||
|
<path d="M 340 520
|
||||||
|
L 340 420
|
||||||
|
Q 340 380, 360 350
|
||||||
|
L 360 320
|
||||||
|
Q 360 300, 380 290
|
||||||
|
L 420 290
|
||||||
|
Q 440 300, 440 320
|
||||||
|
L 440 350
|
||||||
|
Q 460 380, 460 420
|
||||||
|
L 460 520
|
||||||
|
Z"/>
|
||||||
|
|
||||||
|
<!-- Head -->
|
||||||
|
<ellipse cx="400" cy="260" rx="32" ry="38"/>
|
||||||
|
|
||||||
|
<!-- Left arm gesturing -->
|
||||||
|
<path d="M 360 330 Q 300 360 280 400" stroke="#0a0908" stroke-width="16" stroke-linecap="round" fill="none"/>
|
||||||
|
|
||||||
|
<!-- Right arm at side -->
|
||||||
|
<path d="M 440 330 Q 460 380 460 420" stroke="#0a0908" stroke-width="16" stroke-linecap="round" fill="none"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Simple spotlight from above -->
|
||||||
|
<polygon points="250,0 550,0 480,520 320,520" fill="#c8952e" opacity="0.08"/>
|
||||||
|
|
||||||
|
<!-- Subtle rim light on speaker -->
|
||||||
|
<ellipse cx="400" cy="520" rx="60" ry="15" fill="#c8952e" opacity="0.1"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2 KiB |
145
src/components/BookCard.astro
Normal file
145
src/components/BookCard.astro
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
---
|
||||||
|
// BookCard.astro — Book display card
|
||||||
|
export interface Props {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
status?: 'published' | 'forthcoming' | 'concept';
|
||||||
|
purchaseLinks?: Array<{ label: string; url: string }>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title, description, status = 'published', purchaseLinks = [] } = Astro.props;
|
||||||
|
|
||||||
|
const statusLabel: Record<string, string> = {
|
||||||
|
published: '',
|
||||||
|
forthcoming: 'Coming Soon',
|
||||||
|
concept: 'In Progress',
|
||||||
|
};
|
||||||
|
---
|
||||||
|
|
||||||
|
<article class="book-card card">
|
||||||
|
<div class="book-cover-placeholder" aria-hidden="true">
|
||||||
|
<span class="book-cover-title">{title}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="book-info">
|
||||||
|
<h3>{title}</h3>
|
||||||
|
{statusLabel[status] && (
|
||||||
|
<span class="book-status">{statusLabel[status]}</span>
|
||||||
|
)}
|
||||||
|
<p class="book-desc">{description}</p>
|
||||||
|
|
||||||
|
{purchaseLinks.length > 0 && (
|
||||||
|
<div class="book-links">
|
||||||
|
{purchaseLinks.map((link) => (
|
||||||
|
<a href={link.url} class="btn btn-outline" target="_blank" rel="noopener">{link.label}</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{status === 'forthcoming' && (
|
||||||
|
<form class="book-waitlist" action="https://formspree.io/f/placeholder" method="POST">
|
||||||
|
<input type="email" name="email" placeholder="Get notified when it's out" required aria-label="Email for waitlist" />
|
||||||
|
<button type="submit" class="btn btn-primary">Notify Me</button>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.book-card {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--space-xl);
|
||||||
|
align-items: flex-start;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-cover-placeholder {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 8rem;
|
||||||
|
height: 11rem;
|
||||||
|
background: var(--color-cream-warm);
|
||||||
|
border: 2px dashed var(--color-border);
|
||||||
|
border-radius: 4px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: var(--space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-cover-title {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: var(--size-sm);
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
text-align: center;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-info h3 {
|
||||||
|
margin-bottom: var(--space-xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-status {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: var(--size-xs);
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
color: var(--color-amber);
|
||||||
|
background: rgba(200, 149, 46, 0.1);
|
||||||
|
padding: 0.15em 0.5em;
|
||||||
|
border-radius: 3px;
|
||||||
|
margin-bottom: var(--space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-desc {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
font-size: var(--size-sm);
|
||||||
|
margin-bottom: var(--space-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-links {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--space-sm);
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-waitlist {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--space-sm);
|
||||||
|
margin-top: var(--space-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-waitlist input {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: 4px;
|
||||||
|
font-family: var(--font-body);
|
||||||
|
font-size: var(--size-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-waitlist input:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: var(--color-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 639px) {
|
||||||
|
.book-card {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-info {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-links {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-waitlist {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
52
src/components/ContactForm.astro
Normal file
52
src/components/ContactForm.astro
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
---
|
||||||
|
// ContactForm.astro — Reusable contact form
|
||||||
|
export interface Props {
|
||||||
|
formAction?: string;
|
||||||
|
showTopic?: boolean;
|
||||||
|
buttonLabel?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
formAction = 'https://formspree.io/f/placeholder',
|
||||||
|
showTopic = true,
|
||||||
|
buttonLabel = 'Send Message',
|
||||||
|
} = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<form class="contact-form" action={formAction} method="POST">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="contact-name">Name</label>
|
||||||
|
<input type="text" id="contact-name" name="name" required autocomplete="name" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="contact-email">Email</label>
|
||||||
|
<input type="email" id="contact-email" name="email" required autocomplete="email" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{showTopic && (
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="contact-topic">Topic</label>
|
||||||
|
<select id="contact-topic" name="topic">
|
||||||
|
<option value="">Select a topic</option>
|
||||||
|
<option value="speaking">Speaking Inquiry</option>
|
||||||
|
<option value="consulting">Consulting Inquiry</option>
|
||||||
|
<option value="general">General</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="contact-message">Message</label>
|
||||||
|
<textarea id="contact-message" name="message" rows="5" required></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary btn-large">{buttonLabel}</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.contact-form {
|
||||||
|
max-width: 36rem;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
155
src/components/Footer.astro
Normal file
155
src/components/Footer.astro
Normal file
|
|
@ -0,0 +1,155 @@
|
||||||
|
---
|
||||||
|
const currentYear = new Date().getFullYear();
|
||||||
|
---
|
||||||
|
|
||||||
|
<footer class="site-footer">
|
||||||
|
<div class="footer-container">
|
||||||
|
|
||||||
|
<div class="footer-main">
|
||||||
|
<div class="footer-brand">
|
||||||
|
<span class="footer-logo">Scott Scoble</span>
|
||||||
|
<p class="footer-tagline">The human cultivation expert for the AI age.</p>
|
||||||
|
<div class="footer-social">
|
||||||
|
<a href="https://linkedin.com/in/scottscoble" target="_blank" rel="noopener" aria-label="LinkedIn">
|
||||||
|
<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>
|
||||||
|
</a>
|
||||||
|
<a href="https://twitter.com/scottscoble" target="_blank" rel="noopener" aria-label="X/Twitter">
|
||||||
|
<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/sscoble" target="_blank" rel="noopener" aria-label="GitHub">
|
||||||
|
<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><path d="M12 0C5.374 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.605-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z"/></svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer-links">
|
||||||
|
<div class="footer-col">
|
||||||
|
<h4>Pages</h4>
|
||||||
|
<a href="/">Home</a>
|
||||||
|
<a href="/speaking">Speaking</a>
|
||||||
|
<a href="/consulting">Consulting</a>
|
||||||
|
<a href="/about">About</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer-col">
|
||||||
|
<h4>Resources</h4>
|
||||||
|
<a href="/books">Books</a>
|
||||||
|
<a href="/blog">Blog</a>
|
||||||
|
<a href="/contact">Contact</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer-bottom">
|
||||||
|
<p>© {currentYear} Scott Scoble. All rights reserved.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.site-footer {
|
||||||
|
background: var(--color-brown-dark);
|
||||||
|
color: var(--color-cream);
|
||||||
|
padding: 4rem 0 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-container {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-main {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 2fr 1fr;
|
||||||
|
gap: 4rem;
|
||||||
|
padding-bottom: 3rem;
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-logo {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: white;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-tagline {
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
margin: 0 0 1.5rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-social {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-social a {
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
transition: color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-social a:hover {
|
||||||
|
color: var(--color-amber);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-links {
|
||||||
|
display: flex;
|
||||||
|
gap: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-col {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-col h4 {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-col a {
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.9375rem;
|
||||||
|
transition: color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-col a:hover {
|
||||||
|
color: var(--color-amber);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-bottom {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.footer-main {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-links {
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-bottom {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
150
src/components/Nav.astro
Normal file
150
src/components/Nav.astro
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
---
|
||||||
|
const navLinks = [
|
||||||
|
{ href: '/speaking', label: 'Speaking' },
|
||||||
|
{ href: '/consulting', label: 'Consulting' },
|
||||||
|
{ href: '/about', label: 'About' },
|
||||||
|
{ href: '/books', label: 'Books' },
|
||||||
|
{ href: '/blog', label: 'Blog' },
|
||||||
|
];
|
||||||
|
---
|
||||||
|
|
||||||
|
<nav class="site-nav" aria-label="Main navigation">
|
||||||
|
<div class="nav-container">
|
||||||
|
<a href="/" class="nav-logo">
|
||||||
|
<span class="logo-text">Scott Scoble</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="nav-links">
|
||||||
|
{navLinks.map(link => (
|
||||||
|
<a href={link.href} class="nav-link">{link.label}</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a href="/speaking#book" class="nav-cta">Book Scott</a>
|
||||||
|
|
||||||
|
<button class="nav-menu-toggle" aria-label="Toggle menu" aria-expanded="false">
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
<span></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.site-nav {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: rgba(250, 248, 245, 0.95);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border-bottom: 1px solid var(--color-border-light);
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-container {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-logo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-text {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-links {
|
||||||
|
display: flex;
|
||||||
|
gap: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link {
|
||||||
|
color: var(--color-brown);
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 0.9375rem;
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
position: relative;
|
||||||
|
transition: color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 2px;
|
||||||
|
background: var(--color-amber);
|
||||||
|
transition: width 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link:hover {
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link:hover::after {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-cta {
|
||||||
|
background: var(--color-amber);
|
||||||
|
color: white;
|
||||||
|
padding: 0.625rem 1.5rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 0.9375rem;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-cta:hover {
|
||||||
|
background: var(--color-amber-light);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 4px 12px rgba(200, 149, 46, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-menu-toggle {
|
||||||
|
display: none;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
padding: 0.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-menu-toggle span {
|
||||||
|
display: block;
|
||||||
|
width: 24px;
|
||||||
|
height: 2px;
|
||||||
|
background: var(--color-brown-dark);
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.nav-links {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-cta {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-menu-toggle {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
69
src/components/NewsletterSignup.astro
Normal file
69
src/components/NewsletterSignup.astro
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
---
|
||||||
|
// NewsletterSignup.astro — Reusable newsletter signup block
|
||||||
|
export interface Props {
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
title = 'Stay Cultivated',
|
||||||
|
description = 'Sign up for the newsletter. No spam. No AI-generated content. Just the soil report.',
|
||||||
|
} = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="newsletter-block">
|
||||||
|
<h2>{title}</h2>
|
||||||
|
<p>{description}</p>
|
||||||
|
<form class="newsletter-form" action="https://formspree.io/f/placeholder" method="POST">
|
||||||
|
<label for="newsletter-email" class="sr-only">Email address</label>
|
||||||
|
<input id="newsletter-email" type="email" name="email" placeholder="your@email.com" required />
|
||||||
|
<button type="submit" class="btn btn-primary">Subscribe</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.newsletter-block {
|
||||||
|
text-align: center;
|
||||||
|
padding: var(--space-3xl) 0;
|
||||||
|
background: var(--color-cream-warm);
|
||||||
|
border-top: 1px solid var(--color-border-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.newsletter-block h2 {
|
||||||
|
margin-bottom: var(--space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.newsletter-block p {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
max-width: 28rem;
|
||||||
|
margin: 0 auto var(--space-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.newsletter-form {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--space-sm);
|
||||||
|
max-width: 24rem;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newsletter-form input {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: 4px;
|
||||||
|
font-family: var(--font-body);
|
||||||
|
font-size: var(--size-base);
|
||||||
|
}
|
||||||
|
|
||||||
|
.newsletter-form input:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: var(--color-green);
|
||||||
|
box-shadow: 0 0 0 3px rgba(61, 90, 62, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 639px) {
|
||||||
|
.newsletter-form {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
120
src/components/PackageCard.astro
Normal file
120
src/components/PackageCard.astro
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
---
|
||||||
|
// PackageCard.astro — Consulting package card
|
||||||
|
export interface Props {
|
||||||
|
title: string;
|
||||||
|
tagline: string;
|
||||||
|
description: string;
|
||||||
|
deliverables: string[];
|
||||||
|
priceRange: string;
|
||||||
|
idealFor?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title, tagline, description, deliverables, priceRange, idealFor } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<article class="package-card card">
|
||||||
|
<h3>{title}</h3>
|
||||||
|
<p class="package-tagline">{tagline}</p>
|
||||||
|
<p class="package-desc">{description}</p>
|
||||||
|
|
||||||
|
<div class="package-deliverables">
|
||||||
|
<h4>What You Get</h4>
|
||||||
|
<ul>
|
||||||
|
{deliverables.map((d) => <li>{d}</li>)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{idealFor && (
|
||||||
|
<div class="package-ideal-for">
|
||||||
|
<h4>Ideal For</h4>
|
||||||
|
<p>{idealFor}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div class="package-price">
|
||||||
|
<span>{priceRange}</span>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.package-card {
|
||||||
|
text-align: left;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-card h3 {
|
||||||
|
font-size: var(--size-xl);
|
||||||
|
margin-bottom: var(--space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-tagline {
|
||||||
|
color: var(--color-amber);
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: var(--size-sm);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.03em;
|
||||||
|
margin-bottom: var(--space-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-desc {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
font-size: var(--size-sm);
|
||||||
|
margin-bottom: var(--space-md);
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-deliverables {
|
||||||
|
margin-bottom: var(--space-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-deliverables h4 {
|
||||||
|
font-family: var(--font-body);
|
||||||
|
font-size: var(--size-sm);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
color: var(--color-green);
|
||||||
|
margin-bottom: var(--space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-deliverables ul {
|
||||||
|
padding-left: var(--space-lg);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-deliverables li {
|
||||||
|
font-size: var(--size-sm);
|
||||||
|
margin-bottom: var(--space-xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-ideal-for {
|
||||||
|
margin-bottom: var(--space-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-ideal-for h4 {
|
||||||
|
font-family: var(--font-body);
|
||||||
|
font-size: var(--size-sm);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
color: var(--color-amber);
|
||||||
|
margin-bottom: var(--space-xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-ideal-for p {
|
||||||
|
font-size: var(--size-sm);
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
font-style: italic;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-price {
|
||||||
|
text-align: center;
|
||||||
|
padding: var(--space-md);
|
||||||
|
background: var(--color-cream-warm);
|
||||||
|
border-radius: 6px;
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: var(--size-md);
|
||||||
|
color: var(--color-brown);
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
85
src/components/PillarCard.astro
Normal file
85
src/components/PillarCard.astro
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
---
|
||||||
|
// PillarCard.astro — Home page pillar value card
|
||||||
|
export interface Props {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
number: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title, description, number } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<article class="pillar-card">
|
||||||
|
<span class="pillar-number" aria-hidden="true">{String(number).padStart(2, '0')}</span>
|
||||||
|
<div class="pillar-content">
|
||||||
|
<h3>{title}</h3>
|
||||||
|
<p>{description}</p>
|
||||||
|
</div>
|
||||||
|
<div class="pillar-accent"></div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.pillar-card {
|
||||||
|
position: relative;
|
||||||
|
background: linear-gradient(135deg, #faf8f5 0%, #ffffff 100%);
|
||||||
|
border: 1px solid var(--color-border-light);
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 2.5rem;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pillar-card:hover {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.08);
|
||||||
|
border-color: var(--color-amber);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pillar-number {
|
||||||
|
position: absolute;
|
||||||
|
top: 1.5rem;
|
||||||
|
right: 1.5rem;
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 4rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--color-border);
|
||||||
|
opacity: 0.5;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pillar-content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pillar-card h3 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
padding-right: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pillar-card p {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.7;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pillar-accent {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 4px;
|
||||||
|
background: linear-gradient(90deg, var(--color-amber) 0%, var(--color-green) 100%);
|
||||||
|
transform: scaleX(0);
|
||||||
|
transform-origin: left;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pillar-card:hover .pillar-accent {
|
||||||
|
transform: scaleX(1);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
82
src/components/TalkCard.astro
Normal file
82
src/components/TalkCard.astro
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
---
|
||||||
|
// TalkCard.astro — Speaking page talk topic card
|
||||||
|
export interface Props {
|
||||||
|
title: string;
|
||||||
|
premise: string;
|
||||||
|
takeaways: string[];
|
||||||
|
audience: string;
|
||||||
|
slug?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title, premise, takeaways, audience } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<article class="talk-card card">
|
||||||
|
<h3>{title}</h3>
|
||||||
|
<p class="talk-premise">{premise}</p>
|
||||||
|
|
||||||
|
{takeaways.length > 0 && (
|
||||||
|
<div class="talk-takeaways">
|
||||||
|
<h4>Key Takeaways</h4>
|
||||||
|
<ul>
|
||||||
|
{takeaways.map((t) => <li>{t}</li>)}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div class="talk-audience">
|
||||||
|
<span class="talk-label">Ideal Audience:</span> {audience}
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.talk-card {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-card h3 {
|
||||||
|
font-size: var(--size-xl);
|
||||||
|
margin-bottom: var(--space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-premise {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
font-size: var(--size-md);
|
||||||
|
margin-bottom: var(--space-lg);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-takeaways {
|
||||||
|
margin-bottom: var(--space-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-takeaways h4 {
|
||||||
|
font-family: var(--font-body);
|
||||||
|
font-size: var(--size-sm);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
color: var(--color-green);
|
||||||
|
margin-bottom: var(--space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-takeaways ul {
|
||||||
|
padding-left: var(--space-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-takeaways li {
|
||||||
|
margin-bottom: var(--space-xs);
|
||||||
|
font-size: var(--size-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-audience {
|
||||||
|
padding-top: var(--space-md);
|
||||||
|
border-top: 1px solid var(--color-border-light);
|
||||||
|
font-size: var(--size-sm);
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-label {
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--color-brown);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
69
src/components/TestimonialCard.astro
Normal file
69
src/components/TestimonialCard.astro
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
---
|
||||||
|
// TestimonialCard.astro — Placeholder testimonial card
|
||||||
|
export interface Props {
|
||||||
|
quote: string;
|
||||||
|
name: string;
|
||||||
|
role: string;
|
||||||
|
organization?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { quote, name, role, organization } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<figure class="testimonial-card card">
|
||||||
|
<blockquote>
|
||||||
|
<p>“{quote}”</p>
|
||||||
|
</blockquote>
|
||||||
|
<figcaption>
|
||||||
|
<strong>{name}</strong>
|
||||||
|
<span>{role}{organization ? `, ${organization}` : ''}</span>
|
||||||
|
</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.testimonial-card {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.testimonial-card blockquote {
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 0 var(--space-md);
|
||||||
|
background: none;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.testimonial-card blockquote p {
|
||||||
|
font-size: var(--size-sm);
|
||||||
|
line-height: 1.7;
|
||||||
|
color: var(--color-text);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.testimonial-card blockquote p::before {
|
||||||
|
content: '"';
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: var(--size-2xl);
|
||||||
|
color: var(--color-amber);
|
||||||
|
position: absolute;
|
||||||
|
top: -0.25em;
|
||||||
|
left: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.testimonial-card figcaption {
|
||||||
|
border-top: 1px solid var(--color-border-light);
|
||||||
|
padding-top: var(--space-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.testimonial-card figcaption strong {
|
||||||
|
display: block;
|
||||||
|
font-size: var(--size-sm);
|
||||||
|
color: var(--color-brown);
|
||||||
|
}
|
||||||
|
|
||||||
|
.testimonial-card figcaption span {
|
||||||
|
display: block;
|
||||||
|
font-size: var(--size-xs);
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
25
src/content.config.ts
Normal file
25
src/content.config.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { defineCollection, z } from 'astro:content';
|
||||||
|
import { glob } from 'astro/loaders';
|
||||||
|
|
||||||
|
const blog = defineCollection({
|
||||||
|
loader: glob({ pattern: '**/*.md', base: './src/content/blog' }),
|
||||||
|
schema: z.object({
|
||||||
|
title: z.string(),
|
||||||
|
description: z.string(),
|
||||||
|
date: z.coerce.date(),
|
||||||
|
tags: z.array(z.string()).default([]),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const talks = defineCollection({
|
||||||
|
loader: glob({ pattern: '**/*.md', base: './src/content/talks' }),
|
||||||
|
schema: z.object({
|
||||||
|
title: z.string(),
|
||||||
|
premise: z.string(),
|
||||||
|
duration: z.string().default('45–60 min'),
|
||||||
|
audience: z.array(z.string()).default([]),
|
||||||
|
takeaways: z.array(z.string()).default([]),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const collections = { blog, talks };
|
||||||
112
src/layouts/BaseLayout.astro
Normal file
112
src/layouts/BaseLayout.astro
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
---
|
||||||
|
// BaseLayout.astro — Base layout with nav, footer, SEO meta
|
||||||
|
import '../styles/global.css';
|
||||||
|
import Nav from '../components/Nav.astro';
|
||||||
|
import Footer from '../components/Footer.astro';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
ogImage?: string;
|
||||||
|
ogType?: string;
|
||||||
|
canonicalUrl?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
ogImage = '/social-card.png',
|
||||||
|
ogType = 'website',
|
||||||
|
canonicalUrl,
|
||||||
|
} = Astro.props;
|
||||||
|
|
||||||
|
const siteTitle = 'Scott Scoble';
|
||||||
|
const fullTitle = title.includes(siteTitle) ? title : `${title} — ${siteTitle}`;
|
||||||
|
const siteUrl = 'https://scott.scoble.me';
|
||||||
|
const currentPath = canonicalUrl || Astro.url.pathname;
|
||||||
|
---
|
||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta name="generator" content={Astro.generator} />
|
||||||
|
|
||||||
|
<!-- Primary Meta -->
|
||||||
|
<title>{fullTitle}</title>
|
||||||
|
<meta name="description" content={description} />
|
||||||
|
<meta name="author" content="Scott Scoble" />
|
||||||
|
|
||||||
|
<!-- Open Graph -->
|
||||||
|
<meta property="og:title" content={fullTitle} />
|
||||||
|
<meta property="og:description" content={description} />
|
||||||
|
<meta property="og:type" content={ogType} />
|
||||||
|
<meta property="og:url" content={new URL(currentPath, siteUrl).href} />
|
||||||
|
<meta property="og:image" content={new URL(ogImage, siteUrl).href} />
|
||||||
|
<meta property="og:site_name" content="Scott Scoble" />
|
||||||
|
<meta property="og:locale" content="en_US" />
|
||||||
|
|
||||||
|
<!-- Twitter Card -->
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
<meta name="twitter:title" content={fullTitle} />
|
||||||
|
<meta name="twitter:description" content={description} />
|
||||||
|
<meta name="twitter:image" content={new URL(ogImage, siteUrl).href} />
|
||||||
|
|
||||||
|
<!-- Canonical -->
|
||||||
|
<link rel="canonical" href={new URL(currentPath, siteUrl).href} />
|
||||||
|
|
||||||
|
<!-- RSS -->
|
||||||
|
<link rel="alternate" type="application/rss+xml" title="Scott Scoble Blog" href="/rss.xml" />
|
||||||
|
|
||||||
|
<!-- Google Fonts -->
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500&display=swap" rel="stylesheet" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a href="#main-content" class="skip-link">Skip to main content</a>
|
||||||
|
|
||||||
|
<Nav currentPath={currentPath} />
|
||||||
|
|
||||||
|
<main id="main-content">
|
||||||
|
<slot />
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<Footer />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
<style is:global>
|
||||||
|
/* CSS Variables must be defined globally for all components to access */
|
||||||
|
:root {
|
||||||
|
--color-brown: #4a4438;
|
||||||
|
--color-brown-dark: #2d2a24;
|
||||||
|
--color-green: #3d5a3e;
|
||||||
|
--color-green-dark: #2d5a3e;
|
||||||
|
--color-cream: #faf8f5;
|
||||||
|
--color-cream-warm: #f5f0e8;
|
||||||
|
--color-amber: #c8952e;
|
||||||
|
--color-amber-light: #d4a94e;
|
||||||
|
--color-text: #2d2a24;
|
||||||
|
--color-text-muted: #6b6458;
|
||||||
|
--color-border: #e0dbd2;
|
||||||
|
--color-border-light: #ede9e2;
|
||||||
|
--color-bg: #faf8f5;
|
||||||
|
--color-bg-alt: #f5f0e8;
|
||||||
|
--font-heading: 'EB Garamond', Georgia, serif;
|
||||||
|
--font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
|
--size-xs: 0.75rem;
|
||||||
|
--size-sm: 0.875rem;
|
||||||
|
--size-base: 1rem;
|
||||||
|
--size-md: 1.125rem;
|
||||||
|
--size-lg: 1.25rem;
|
||||||
|
--size-xl: 1.5rem;
|
||||||
|
--size-2xl: 2rem;
|
||||||
|
--size-3xl: 2.5rem;
|
||||||
|
--size-4xl: 3rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
75
src/pages/404.astro
Normal file
75
src/pages/404.astro
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
---
|
||||||
|
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout
|
||||||
|
title="Page Not Found — Scott Scoble"
|
||||||
|
description="That page doesn't exist."
|
||||||
|
>
|
||||||
|
|
||||||
|
<section class="error-page">
|
||||||
|
<div class="error-content">
|
||||||
|
<span class="error-code">404</span>
|
||||||
|
<h1>Page not found</h1>
|
||||||
|
<p>That link doesn't lead anywhere. Maybe it moved, maybe it never existed.</p>
|
||||||
|
<a href="/" class="btn">Go home</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</BaseLayout>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.error-page {
|
||||||
|
min-height: 70vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
padding: 6rem 2rem;
|
||||||
|
background: var(--color-cream);
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-content {
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-code {
|
||||||
|
display: block;
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 6rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--color-amber);
|
||||||
|
opacity: 0.3;
|
||||||
|
line-height: 1;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-content h1 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 2rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-content p {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
margin: 0 0 2rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
display: inline-block;
|
||||||
|
background: var(--color-amber);
|
||||||
|
color: white;
|
||||||
|
padding: 0.875rem 2rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:hover {
|
||||||
|
background: var(--color-amber-light);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
221
src/pages/about.astro
Normal file
221
src/pages/about.astro
Normal file
|
|
@ -0,0 +1,221 @@
|
||||||
|
---
|
||||||
|
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout
|
||||||
|
title="About — Scott Scoble"
|
||||||
|
description="Scott Scoble is a builder, writer, and speaker focused on the human side of AI systems. Author of The Soil Beneath the Code and A Walk in Mentoring."
|
||||||
|
>
|
||||||
|
|
||||||
|
<section class="hero">
|
||||||
|
<div class="hero-content">
|
||||||
|
<h1>About</h1>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="bio-section">
|
||||||
|
<div class="section-container">
|
||||||
|
|
||||||
|
<div class="bio-content">
|
||||||
|
<p class="bio-lead">
|
||||||
|
Scott Scoble is a builder, writer, and speaker focused on the human side of AI systems.
|
||||||
|
He's the author of <em>The Soil Beneath the Code</em> and <em>A Walk in Mentoring</em>,
|
||||||
|
and creator of Speckl — a dark provenance system for agentic engineering.
|
||||||
|
He advises engineering leaders on how to build AI systems that cultivate human capability
|
||||||
|
instead of strip-mining it.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>The Cultivation Framework</h2>
|
||||||
|
|
||||||
|
<div class="framework-grid">
|
||||||
|
<div class="framework-item">
|
||||||
|
<h3>Soil Assessment</h3>
|
||||||
|
<p>Diagnose before prescribing. Know what's actually depleted before you fertilize.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="framework-item">
|
||||||
|
<h3>Formation</h3>
|
||||||
|
<p>Cultivate capability, don't extract output. Build systems that get stronger with use.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="framework-item">
|
||||||
|
<h3>Accountability</h3>
|
||||||
|
<p>Hold the line on human infrastructure. Dark provenance for every agent output.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="photo-placeholder">
|
||||||
|
<p>📷 Photo coming soon</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="books-section">
|
||||||
|
<div class="section-container">
|
||||||
|
<h2>Books</h2>
|
||||||
|
|
||||||
|
<div class="books-grid">
|
||||||
|
|
||||||
|
<article class="book-card">
|
||||||
|
<h3>The Soil Beneath the Code</h3>
|
||||||
|
<p class="book-status">Published</p>
|
||||||
|
<p>What engineering teams can learn from farmers about sustainable systems.</p>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="book-card">
|
||||||
|
<h3>A Walk in Mentoring</h3>
|
||||||
|
<p class="book-status">Published</p>
|
||||||
|
<p>Three questions that change how people learn.</p>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="book-card">
|
||||||
|
<h3>Dark Provenance</h3>
|
||||||
|
<p class="book-status">Coming 2026</p>
|
||||||
|
<p>Formal verification for the AI age. How to audit what your AI actually did.</p>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</BaseLayout>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.hero {
|
||||||
|
background: var(--color-cream);
|
||||||
|
padding: 4rem 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: clamp(2rem, 5vw, 3rem);
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-container {
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 4rem 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio-section {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio-section .section-container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 2fr 1fr;
|
||||||
|
gap: 3rem;
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.bio-section .section-container {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio-lead {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
line-height: 1.7;
|
||||||
|
color: var(--color-brown);
|
||||||
|
margin: 0 0 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio-lead em {
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio-content h2 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
margin: 2rem 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.framework-grid {
|
||||||
|
display: grid;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.framework-item {
|
||||||
|
padding: 1.5rem;
|
||||||
|
background: var(--color-cream);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.framework-item h3 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 1.125rem;
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.framework-item p {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-placeholder {
|
||||||
|
background: var(--color-cream-warm);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 4rem 2rem;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo-placeholder p {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.books-section {
|
||||||
|
background: var(--color-cream);
|
||||||
|
}
|
||||||
|
|
||||||
|
.books-section h2 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0 0 2rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.books-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-card {
|
||||||
|
background: white;
|
||||||
|
padding: 2rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-card h3 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 1.25rem;
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-status {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--color-green);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
margin: 0 0 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-card p:last-child {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
148
src/pages/blog.astro
Normal file
148
src/pages/blog.astro
Normal file
|
|
@ -0,0 +1,148 @@
|
||||||
|
---
|
||||||
|
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout
|
||||||
|
title="Blog — Scott Scoble"
|
||||||
|
description="Articles on AI, leadership, cultivation, and the human side of technology."
|
||||||
|
>
|
||||||
|
|
||||||
|
<section class="hero">
|
||||||
|
<div class="hero-content">
|
||||||
|
<p class="hero-kicker">Writing</p>
|
||||||
|
<h1>Blog</h1>
|
||||||
|
<p class="hero-description">
|
||||||
|
Articles on AI, leadership, cultivation, and the human side of technology.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="posts">
|
||||||
|
<div class="posts-container">
|
||||||
|
|
||||||
|
<article class="post-card">
|
||||||
|
<div class="post-meta">
|
||||||
|
<span class="post-date">Coming soon</span>
|
||||||
|
<span class="post-tag">AI</span>
|
||||||
|
</div>
|
||||||
|
<h2>The Memory Problem Nobody Talks About</h2>
|
||||||
|
<p class="post-excerpt">
|
||||||
|
Why your AI's "memory" is actually just replay, not learning — and what to do about it.
|
||||||
|
</p>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="post-card">
|
||||||
|
<div class="post-meta">
|
||||||
|
<span class="post-date">Coming soon</span>
|
||||||
|
<span class="post-tag">Leadership</span>
|
||||||
|
</div>
|
||||||
|
<h2>Three Questions That Change Everything</h2>
|
||||||
|
<p class="post-excerpt">
|
||||||
|
The simple mentoring framework that actually gets used.
|
||||||
|
</p>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="post-card">
|
||||||
|
<div class="post-meta">
|
||||||
|
<span class="post-date">Coming soon</span>
|
||||||
|
<span class="post-tag">Teams</span>
|
||||||
|
</div>
|
||||||
|
<h2>Strip-Mining vs Cultivation</h2>
|
||||||
|
<p class="post-excerpt">
|
||||||
|
The mindset shift that separates thriving teams from burned-out ones.
|
||||||
|
</p>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</BaseLayout>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.hero {
|
||||||
|
padding: 8rem 2rem 4rem;
|
||||||
|
text-align: center;
|
||||||
|
background: var(--color-cream);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-content {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-kicker {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.15em;
|
||||||
|
color: var(--color-green);
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: clamp(2.5rem, 5vw, 4rem);
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-description {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.posts {
|
||||||
|
padding: 4rem 2rem 6rem;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.posts-container {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-card {
|
||||||
|
padding: 2rem;
|
||||||
|
border: 1px solid var(--color-border-light);
|
||||||
|
border-radius: 12px;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-card:hover {
|
||||||
|
border-color: var(--color-amber);
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-meta {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-date {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-tag {
|
||||||
|
color: var(--color-amber);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-card h2 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
margin: 0 0 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-excerpt {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
180
src/pages/books.astro
Normal file
180
src/pages/books.astro
Normal file
|
|
@ -0,0 +1,180 @@
|
||||||
|
---
|
||||||
|
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout
|
||||||
|
title="Books — Scott Scoble"
|
||||||
|
description="Published works on cultivation, mentoring, and the human side of AI."
|
||||||
|
>
|
||||||
|
|
||||||
|
<section class="hero">
|
||||||
|
<div class="hero-content">
|
||||||
|
<h1>Books</h1>
|
||||||
|
<p>Published works on cultivation, mentoring, and the human side of AI.</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="books-section">
|
||||||
|
<div class="section-container">
|
||||||
|
|
||||||
|
<div class="books-grid">
|
||||||
|
|
||||||
|
<article class="book-card">
|
||||||
|
<div class="book-cover">
|
||||||
|
<span>📚</span>
|
||||||
|
</div>
|
||||||
|
<h2>The Soil Beneath the Code</h2>
|
||||||
|
<p class="book-meta">Published 2023</p>
|
||||||
|
<p class="book-description">What engineering teams can learn from farmers about sustainable systems.</p>
|
||||||
|
<p class="book-quote">"A cultivation playbook for technical leaders who are tired of strip-mining their teams."</p>
|
||||||
|
|
||||||
|
<div class="book-links">
|
||||||
|
<a href="#" class="book-link">Amazon</a>
|
||||||
|
<a href="#" class="book-link">Publisher</a>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="book-card">
|
||||||
|
<div class="book-cover">
|
||||||
|
<span>🚶</span>
|
||||||
|
</div>
|
||||||
|
<h2>A Walk in Mentoring</h2>
|
||||||
|
<p class="book-meta">Published 2024</p>
|
||||||
|
<p class="book-description">Three questions that change how people learn.</p>
|
||||||
|
<p class="book-quote">"The simplest mentoring framework you'll actually use."</p>
|
||||||
|
|
||||||
|
<div class="book-links">
|
||||||
|
<a href="#" class="book-link">Amazon</a>
|
||||||
|
<a href="#" class="book-link">Publisher</a>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="book-card coming-soon">
|
||||||
|
<div class="book-cover">
|
||||||
|
<span>🔍</span>
|
||||||
|
</div>
|
||||||
|
<h2>Dark Provenance</h2>
|
||||||
|
<p class="book-meta">Coming 2026</p>
|
||||||
|
<p class="book-description">Formal verification for the AI age. How to audit what your AI actually did.</p>
|
||||||
|
<p class="book-quote">"Speckl and the dark provenance system. A new approach to AI accountability."</p>
|
||||||
|
|
||||||
|
<a href="#" class="waitlist-btn">Join Waitlist</a>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</BaseLayout>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.hero {
|
||||||
|
background: var(--color-cream);
|
||||||
|
padding: 4rem 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: clamp(2rem, 5vw, 3rem);
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero p {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.books-section {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-container {
|
||||||
|
max-width: 1100px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 4rem 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.books-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
|
gap: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-card {
|
||||||
|
background: var(--color-cream);
|
||||||
|
padding: 2.5rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-card.coming-soon {
|
||||||
|
background: var(--color-cream-warm);
|
||||||
|
border: 2px dashed var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-cover {
|
||||||
|
font-size: 4rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-card h2 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-meta {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--color-green);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-description {
|
||||||
|
color: var(--color-brown);
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-quote {
|
||||||
|
font-style: italic;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
margin: 0 0 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-links {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-link {
|
||||||
|
color: var(--color-green);
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-link:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.waitlist-btn {
|
||||||
|
display: inline-block;
|
||||||
|
background: var(--color-brown);
|
||||||
|
color: white;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.waitlist-btn:hover {
|
||||||
|
background: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
229
src/pages/consulting.astro
Normal file
229
src/pages/consulting.astro
Normal file
|
|
@ -0,0 +1,229 @@
|
||||||
|
---
|
||||||
|
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||||
|
import PackageCard from '../components/PackageCard.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout
|
||||||
|
title="Consulting — Scott Scoble"
|
||||||
|
description="Consulting packages for engineering leaders: Soil Assessment, Cultivation Workshop, and Fractional CTO services."
|
||||||
|
>
|
||||||
|
|
||||||
|
<section class="hero">
|
||||||
|
<div class="hero-content">
|
||||||
|
<h1>Consulting</h1>
|
||||||
|
<p>Diagnose, cultivate, and build systems that make humans and AI work together.</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="packages-section">
|
||||||
|
<div class="section-container">
|
||||||
|
<h2>Three Ways to Engage</h2>
|
||||||
|
|
||||||
|
<div class="packages-grid">
|
||||||
|
|
||||||
|
<PackageCard
|
||||||
|
title="Soil Assessment"
|
||||||
|
tagline="DIAGNOSTIC"
|
||||||
|
description="Diagnose your team's soil health. Find what's actually depleted, not what's loudest."
|
||||||
|
deliverables={[
|
||||||
|
"2-hour diagnostic interview with leadership team",
|
||||||
|
"Soil health report: what to cultivate, what to prune",
|
||||||
|
"90-day cultivation roadmap",
|
||||||
|
"Follow-up recommendations"
|
||||||
|
]}
|
||||||
|
priceRange="Starting at $5,000"
|
||||||
|
idealFor="Teams adopting AI but losing human coordination"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<PackageCard
|
||||||
|
title="Cultivation Workshop"
|
||||||
|
tagline="INTERVENTION"
|
||||||
|
description="Turn retrospectives into structural insights, not blame sessions."
|
||||||
|
deliverables={[
|
||||||
|
"Full-day facilitated workshop with your team",
|
||||||
|
"Three-question mentoring framework training",
|
||||||
|
"Accountability mandate and cultivation practices",
|
||||||
|
"Follow-up coaching session"
|
||||||
|
]}
|
||||||
|
priceRange="Starting at $15,000"
|
||||||
|
idealFor="Teams stuck in reactive mode, need structural change"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<PackageCard
|
||||||
|
title="Fractional CTO"
|
||||||
|
tagline="ONGOING PARTNERSHIP"
|
||||||
|
description="Ongoing advisory for agentic systems. Hold the line on human infrastructure."
|
||||||
|
deliverables={[
|
||||||
|
"Weekly advisory calls",
|
||||||
|
"Code review and architecture guidance",
|
||||||
|
"Speckl dark provenance audit",
|
||||||
|
"Team mentoring and development"
|
||||||
|
]}
|
||||||
|
priceRange="$8,000/month"
|
||||||
|
idealFor="Startups and mid-size companies building agentic systems"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="faq-section">
|
||||||
|
<div class="section-container">
|
||||||
|
<h2>Frequently Asked Questions</h2>
|
||||||
|
|
||||||
|
<dl class="faq-list">
|
||||||
|
<div class="faq-item">
|
||||||
|
<dt>What's the difference between the packages?</dt>
|
||||||
|
<dd>Assessment is diagnostic — we figure out what's going on. Workshop is intervention — we change how the team operates. Fractional is ongoing partnership — I embed with your team over time.</dd>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="faq-item">
|
||||||
|
<dt>How do we know which one we need?</dt>
|
||||||
|
<dd>Start with a call. I don't sell packages — I solve problems. We'll figure out the right engagement based on your actual situation.</dd>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="faq-item">
|
||||||
|
<dt>Do you work with remote teams?</dt>
|
||||||
|
<dd>Yes. Most of my work is remote-first. I have async practices that work across time zones.</dd>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="faq-item">
|
||||||
|
<dt>What's your typical engagement timeline?</dt>
|
||||||
|
<dd>Assessment: 2 weeks. Workshop: 1 week planning + 1 day delivery + 2 weeks follow-up. Fractional: 3–6 month minimum.</dd>
|
||||||
|
</div>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="cta-section">
|
||||||
|
<div class="section-container">
|
||||||
|
<h2>Ready to cultivate your team?</h2>
|
||||||
|
<p>Schedule a discovery call. We'll talk about your situation and figure out the right engagement.</p>
|
||||||
|
<a href="/contact" class="cta-button">Schedule Discovery Call</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</BaseLayout>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.hero {
|
||||||
|
background: var(--color-cream);
|
||||||
|
padding: 4rem 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: clamp(2rem, 5vw, 3rem);
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero p {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
margin: 0;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-container {
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 4rem 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.packages-section {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.packages-section h2 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0 0 3rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.packages-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
|
gap: 2rem;
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-section {
|
||||||
|
background: var(--color-cream-warm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-section h2 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0 0 3rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-list {
|
||||||
|
max-width: 700px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-item {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
padding-bottom: 2rem;
|
||||||
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-item dt {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1.125rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-item dd {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-section {
|
||||||
|
background: var(--color-brown-dark);
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-section h2 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 2rem;
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-section p {
|
||||||
|
color: rgba(255,255,255,0.8);
|
||||||
|
margin: 0 0 2rem;
|
||||||
|
max-width: 600px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-button {
|
||||||
|
display: inline-block;
|
||||||
|
background: var(--color-amber);
|
||||||
|
color: white;
|
||||||
|
padding: 0.875rem 2rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1.0625rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-button:hover {
|
||||||
|
background: var(--color-amber-light);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
204
src/pages/contact.astro
Normal file
204
src/pages/contact.astro
Normal file
|
|
@ -0,0 +1,204 @@
|
||||||
|
---
|
||||||
|
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout
|
||||||
|
title="Contact — Scott Scoble"
|
||||||
|
description="Get in touch about speaking, consulting, or just to say hello."
|
||||||
|
>
|
||||||
|
|
||||||
|
<section class="hero">
|
||||||
|
<div class="hero-content">
|
||||||
|
<h1>Contact</h1>
|
||||||
|
<p>Let's talk about your event, your team, or your AI systems.</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="contact-section">
|
||||||
|
<div class="section-container">
|
||||||
|
<div class="contact-grid">
|
||||||
|
|
||||||
|
<!-- Contact Form -->
|
||||||
|
<div class="contact-form-wrapper">
|
||||||
|
<h2>Send a Message</h2>
|
||||||
|
|
||||||
|
<form action="https://formspree.io/f/PLACEHOLDER" method="POST">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="name">Name *</label>
|
||||||
|
<input type="text" id="name" name="name" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="email">Email *</label>
|
||||||
|
<input type="email" id="email" name="email" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="topic">Topic</label>
|
||||||
|
<select id="topic" name="topic">
|
||||||
|
<option value="">Select...</option>
|
||||||
|
<option value="speaking">Speaking Inquiry</option>
|
||||||
|
<option value="consulting">Consulting Inquiry</option>
|
||||||
|
<option value="general">General</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="message">Message *</label>
|
||||||
|
<textarea id="message" name="message" rows="5" required></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="submit-btn">Send Message</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Alternative Contact -->
|
||||||
|
<div class="contact-alternatives">
|
||||||
|
<h2>Other Ways to Reach Me</h2>
|
||||||
|
|
||||||
|
<div class="contact-option">
|
||||||
|
<h3>📧 Email</h3>
|
||||||
|
<p><a href="mailto:scott@scoble.me">scott@scoble.me</a></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="contact-option">
|
||||||
|
<h3>📅 Discovery Call</h3>
|
||||||
|
<p><a href="#">Schedule a 20-min call</a> (Calendly link coming soon)</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="contact-option">
|
||||||
|
<h3>🐦 Social</h3>
|
||||||
|
<p>
|
||||||
|
<a href="https://linkedin.com/in/scottscoble" target="_blank" rel="noopener">LinkedIn</a> •
|
||||||
|
<a href="https://twitter.com/scottscoble" target="_blank" rel="noopener">X/Twitter</a> •
|
||||||
|
<a href="https://github.com/sscoble" target="_blank" rel="noopener">GitHub</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</BaseLayout>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.hero {
|
||||||
|
background: var(--color-cream);
|
||||||
|
padding: 4rem 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: clamp(2rem, 5vw, 3rem);
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero p {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-container {
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 4rem 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-section {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.contact-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-form-wrapper h2,
|
||||||
|
.contact-alternatives h2 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin: 0 0 1.5rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group label {
|
||||||
|
display: block;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 0.375rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group input,
|
||||||
|
.form-group select,
|
||||||
|
.form-group textarea {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.625rem;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group input:focus,
|
||||||
|
.form-group select:focus,
|
||||||
|
.form-group textarea:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: var(--color-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
background: var(--color-amber);
|
||||||
|
color: white;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn:hover {
|
||||||
|
background: var(--color-amber-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-option {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-option h3 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 1.125rem;
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-option p {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-option a {
|
||||||
|
color: var(--color-green);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-option a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
572
src/pages/index.astro
Normal file
572
src/pages/index.astro
Normal file
|
|
@ -0,0 +1,572 @@
|
||||||
|
---
|
||||||
|
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||||
|
import PillarCard from '../components/PillarCard.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout
|
||||||
|
title="Scott Scoble — Human Cultivation Expert for the AI Age"
|
||||||
|
description="Keynote speaker and consultant helping leaders build AI systems that cultivate humans instead of strip-mining them. Author of The Soil Beneath the Code."
|
||||||
|
>
|
||||||
|
<!-- Hero Section -->
|
||||||
|
<section class="hero">
|
||||||
|
<div class="hero-bg">
|
||||||
|
<img src="/images/hero-speaker.svg" alt="" class="hero-image" />
|
||||||
|
<div class="hero-overlay"></div>
|
||||||
|
</div>
|
||||||
|
<div class="hero-content">
|
||||||
|
<p class="hero-kicker">Keynote Speaker · Consultant · Author</p>
|
||||||
|
<h1>
|
||||||
|
<span class="line">The human</span>
|
||||||
|
<span class="line accent">cultivation</span>
|
||||||
|
<span class="line">expert for the AI age.</span>
|
||||||
|
</h1>
|
||||||
|
<p class="hero-description">
|
||||||
|
Keynotes and workshops for leaders building AI systems that don't strip-mine their humans.
|
||||||
|
</p>
|
||||||
|
<div class="hero-actions">
|
||||||
|
<a href="/speaking#book" class="btn btn-primary">Book Scott for Your Event</a>
|
||||||
|
<a href="/speaking" class="btn btn-outline">Watch the Reel</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Three Pillars -->
|
||||||
|
<section class="pillars">
|
||||||
|
<div class="section-header">
|
||||||
|
<p class="section-kicker">Three Pillars</p>
|
||||||
|
<h2>How I Help Teams Thrive</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pillar-grid">
|
||||||
|
<PillarCard
|
||||||
|
number={1}
|
||||||
|
title="Cultivation Over Strip Mining"
|
||||||
|
description="Build AI systems that cultivate human capability, not extract it. Assessment, diagnosis, and cultivation practices for engineering teams."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<PillarCard
|
||||||
|
number={2}
|
||||||
|
title="Simple Mentoring"
|
||||||
|
description="Three questions that change how people learn. The mentoring framework that actually gets used. Workshop delivery and team training."
|
||||||
|
/>
|
||||||
|
|
||||||
|
<PillarCard
|
||||||
|
number={3}
|
||||||
|
title="Human Side of AI"
|
||||||
|
description="Maximize the people dimension in AI-augmented work. Keynotes and workshops on the human infrastructure for agentic systems."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Featured Talks -->
|
||||||
|
<section class="featured-talks">
|
||||||
|
<div class="section-header">
|
||||||
|
<p class="section-kicker">Signature Talks</p>
|
||||||
|
<h2>What I Speak About</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="talks-list">
|
||||||
|
<article class="talk-card">
|
||||||
|
<div class="talk-meta">
|
||||||
|
<span class="talk-type">Keynote</span>
|
||||||
|
<span class="talk-duration">45–60 min</span>
|
||||||
|
</div>
|
||||||
|
<h3>50 First Dates with AI</h3>
|
||||||
|
<p class="talk-hook">Every morning, your AI wakes up and doesn't remember yesterday. Here's how to fix that.</p>
|
||||||
|
<p class="talk-desc">Current AI memory architecture is anterograde amnesia — and we're all Henry Roth, recording VHS tapes every night so our agent can wake up functional tomorrow.</p>
|
||||||
|
<a href="/speaking" class="talk-link">Learn more →</a>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="talk-card featured">
|
||||||
|
<div class="talk-meta">
|
||||||
|
<span class="talk-type">Keynote</span>
|
||||||
|
<span class="talk-duration">45–60 min</span>
|
||||||
|
</div>
|
||||||
|
<h3>From Strip-Mining to Cultivation</h3>
|
||||||
|
<p class="talk-hook">The shift from extraction to cultivation in AI-era teams. Why throughput optimization is killing your soil health.</p>
|
||||||
|
<p class="talk-desc">The most successful AI teams aren't the ones with the best models. They're the ones who stopped strip-mining their humans and started cultivating them.</p>
|
||||||
|
<a href="/speaking" class="talk-link">Learn more →</a>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="talk-card">
|
||||||
|
<div class="talk-meta">
|
||||||
|
<span class="talk-type">Workshop</span>
|
||||||
|
<span class="talk-duration">Half-day</span>
|
||||||
|
</div>
|
||||||
|
<h3>The Soil Under Your Team</h3>
|
||||||
|
<p class="talk-hook">Diagnose what's actually depleted before you fertilize. A diagnostic framework for team health.</p>
|
||||||
|
<p class="talk-desc">Most team interventions fail because they prescribe before diagnosing. This workshop gives you a cultivation assessment framework that finds what's actually depleted.</p>
|
||||||
|
<a href="/speaking" class="talk-link">Learn more →</a>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Trust Bar -->
|
||||||
|
<section class="trust-bar">
|
||||||
|
<p class="trust-label">Trusted by leaders at</p>
|
||||||
|
<div class="trust-logos">
|
||||||
|
<span class="logo-placeholder">[Client logos coming soon]</span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Testimonials -->
|
||||||
|
<section class="testimonials">
|
||||||
|
<div class="section-header">
|
||||||
|
<p class="section-kicker">Testimonials</p>
|
||||||
|
<h2>What People Say</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="testimonial-grid">
|
||||||
|
<blockquote class="testimonial-card">
|
||||||
|
<p class="testimonial-quote">"Scott has a rare ability to diagnose team dynamics quickly and prescribe actionable solutions. His cultivation framework changed how we think about AI adoption."</p>
|
||||||
|
<footer class="testimonial-author">
|
||||||
|
<strong>Engineering Leader</strong>
|
||||||
|
<span>Tech Company</span>
|
||||||
|
</footer>
|
||||||
|
</blockquote>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- CTA Section -->
|
||||||
|
<section class="cta-section">
|
||||||
|
<div class="cta-visual"></div>
|
||||||
|
<div class="cta-content">
|
||||||
|
<p class="cta-kicker">Ready to get started?</p>
|
||||||
|
<h2>Let's cultivate your team.</h2>
|
||||||
|
<p class="cta-desc">Book a keynote, workshop, or discovery call. Let's talk about your event or your team's soil health.</p>
|
||||||
|
<a href="/speaking#book" class="btn btn-primary btn-large">Book Scott</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</BaseLayout>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* ===== HERO ===== */
|
||||||
|
.hero {
|
||||||
|
position: relative;
|
||||||
|
min-height: 90vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
padding: 6rem 2rem;
|
||||||
|
background: var(--color-cream);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-bg {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
object-position: center 30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-overlay {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgba(250, 248, 245, 0.7) 0%,
|
||||||
|
rgba(250, 248, 245, 0.5) 40%,
|
||||||
|
rgba(250, 248, 245, 0.8) 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-content {
|
||||||
|
position: relative;
|
||||||
|
max-width: 800px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-kicker {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.15em;
|
||||||
|
color: var(--color-green);
|
||||||
|
margin: 0 0 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: clamp(2.5rem, 6vw, 5rem);
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.1;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
margin: 0 0 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 .line {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 .accent {
|
||||||
|
color: var(--color-amber);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-description {
|
||||||
|
font-size: clamp(1.125rem, 2vw, 1.375rem);
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
margin: 0 0 2.5rem;
|
||||||
|
line-height: 1.7;
|
||||||
|
max-width: 600px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== BUTTONS ===== */
|
||||||
|
.btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0.875rem 2rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 6px;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background: var(--color-amber);
|
||||||
|
color: white;
|
||||||
|
border-color: var(--color-amber);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover {
|
||||||
|
background: var(--color-amber-light);
|
||||||
|
border-color: var(--color-amber-light);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 4px 12px rgba(200, 149, 46, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline {
|
||||||
|
background: transparent;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
border-color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline:hover {
|
||||||
|
background: var(--color-brown-dark);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-large {
|
||||||
|
padding: 1rem 2.5rem;
|
||||||
|
font-size: 1.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== SECTIONS ===== */
|
||||||
|
.section-header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 4rem;
|
||||||
|
padding: 0 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-kicker {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.15em;
|
||||||
|
color: var(--color-amber);
|
||||||
|
margin: 0 0 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header h2 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: clamp(2rem, 4vw, 3rem);
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== PILLARS ===== */
|
||||||
|
.pillars {
|
||||||
|
padding: 6rem 2rem;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pillar-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
||||||
|
gap: 2rem;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== TALKS ===== */
|
||||||
|
.featured-talks {
|
||||||
|
padding: 6rem 2rem;
|
||||||
|
background: linear-gradient(180deg, #f5f0e8 0%, #faf8f5 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.talks-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2rem;
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-card {
|
||||||
|
background: white;
|
||||||
|
padding: 2.5rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
border: 1px solid var(--color-border-light);
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-card:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-card.featured {
|
||||||
|
border-left: 4px solid var(--color-amber);
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-meta {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-type,
|
||||||
|
.talk-duration {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
padding: 0.25rem 0.75rem;
|
||||||
|
border-radius: 20px;
|
||||||
|
background: var(--color-cream-warm);
|
||||||
|
color: var(--color-brown);
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-card h3 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 1.75rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
margin: 0 0 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-hook {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--color-green);
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-desc {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
margin: 0 0 1.5rem;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-link {
|
||||||
|
color: var(--color-amber);
|
||||||
|
font-weight: 600;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-link:hover {
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== TRUST BAR ===== */
|
||||||
|
.trust-bar {
|
||||||
|
padding: 3rem 2rem;
|
||||||
|
background: var(--color-brown-dark);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trust-label {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 500;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
margin: 0 0 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trust-logos {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 3rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-placeholder {
|
||||||
|
color: rgba(255, 255, 255, 0.4);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== TESTIMONIALS ===== */
|
||||||
|
.testimonials {
|
||||||
|
padding: 6rem 2rem;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.testimonial-grid {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.testimonial-card {
|
||||||
|
background: linear-gradient(135deg, #faf8f5 0%, #f5f0e8 100%);
|
||||||
|
padding: 3rem;
|
||||||
|
border-radius: 16px;
|
||||||
|
border: none;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.testimonial-card::before {
|
||||||
|
content: '"';
|
||||||
|
position: absolute;
|
||||||
|
top: 1rem;
|
||||||
|
left: 1.5rem;
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 6rem;
|
||||||
|
color: var(--color-amber);
|
||||||
|
opacity: 0.3;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.testimonial-quote {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-style: italic;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
margin: 0 0 1.5rem;
|
||||||
|
line-height: 1.7;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.testimonial-author {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.testimonial-author strong {
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.testimonial-author span {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
font-size: 0.9375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== CTA SECTION ===== */
|
||||||
|
.cta-section {
|
||||||
|
position: relative;
|
||||||
|
padding: 6rem 2rem;
|
||||||
|
background: var(--color-green);
|
||||||
|
text-align: center;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-visual {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: linear-gradient(135deg, rgba(61, 90, 62, 0.95) 0%, rgba(45, 90, 62, 0.98) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-visual::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: -50%;
|
||||||
|
right: -20%;
|
||||||
|
width: 600px;
|
||||||
|
height: 600px;
|
||||||
|
background: radial-gradient(circle, rgba(200, 149, 46, 0.2) 0%, transparent 60%);
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-kicker {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.15em;
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-content h2 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: clamp(2rem, 4vw, 3rem);
|
||||||
|
color: white;
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-desc {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
color: rgba(255, 255, 255, 0.85);
|
||||||
|
margin: 0 0 2rem;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-section .btn-primary {
|
||||||
|
background: var(--color-amber);
|
||||||
|
border-color: var(--color-amber);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-section .btn-primary:hover {
|
||||||
|
background: var(--color-amber-light);
|
||||||
|
border-color: var(--color-amber-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.hero {
|
||||||
|
min-height: auto;
|
||||||
|
padding: 4rem 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header {
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pillars,
|
||||||
|
.featured-talks,
|
||||||
|
.testimonials,
|
||||||
|
.cta-section {
|
||||||
|
padding: 4rem 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-card {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.testimonial-card {
|
||||||
|
padding: 2rem 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
82
src/pages/privacy.astro
Normal file
82
src/pages/privacy.astro
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
---
|
||||||
|
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout
|
||||||
|
title="Privacy Policy — Scott Scoble"
|
||||||
|
description="Privacy policy for scott.scoble.me"
|
||||||
|
>
|
||||||
|
|
||||||
|
<section class="page-header">
|
||||||
|
<div class="container">
|
||||||
|
<h1>Privacy Policy</h1>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="content">
|
||||||
|
<div class="container">
|
||||||
|
<p>Last updated: April 28, 2026</p>
|
||||||
|
|
||||||
|
<h2>Overview</h2>
|
||||||
|
<p>This website collects minimal data. Here's what you should know:</p>
|
||||||
|
|
||||||
|
<h2>Contact Forms</h2>
|
||||||
|
<p>If you submit a contact form, your email and message are sent to me directly. I don't share this information with third parties.</p>
|
||||||
|
|
||||||
|
<h2>Analytics</h2>
|
||||||
|
<p>This site does not use Google Analytics or other tracking scripts.</p>
|
||||||
|
|
||||||
|
<h2>Cookies</h2>
|
||||||
|
<p>No cookies are set by this site.</p>
|
||||||
|
|
||||||
|
<h2>Hosting</h2>
|
||||||
|
<p>This site is hosted on Storj. Their privacy policy applies to infrastructure-level logging.</p>
|
||||||
|
|
||||||
|
<h2>Contact</h2>
|
||||||
|
<p>Questions? Email <a href="mailto:scott@scoble.me">scott@scoble.me</a>.</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</BaseLayout>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.page-header {
|
||||||
|
padding: 8rem 2rem 2rem;
|
||||||
|
text-align: center;
|
||||||
|
background: var(--color-cream);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header h1 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: clamp(2rem, 5vw, 3rem);
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 4rem 2rem 6rem;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 700px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content h2 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
margin: 2rem 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content p {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
line-height: 1.7;
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content a {
|
||||||
|
color: var(--color-green);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
392
src/pages/speaking.astro
Normal file
392
src/pages/speaking.astro
Normal file
|
|
@ -0,0 +1,392 @@
|
||||||
|
---
|
||||||
|
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||||
|
import TalkCard from '../components/TalkCard.astro';
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout
|
||||||
|
title="Speaking — Scott Scoble"
|
||||||
|
description="Keynote speaker on AI, leadership, and human cultivation. Book Scott for your next conference or corporate event."
|
||||||
|
>
|
||||||
|
|
||||||
|
<!-- Hero -->
|
||||||
|
<section class="hero">
|
||||||
|
<div class="hero-content">
|
||||||
|
<p class="hero-kicker">Keynote Speaker</p>
|
||||||
|
<h1>Helping leaders build AI systems that cultivate humans instead of strip-mining them.</h1>
|
||||||
|
|
||||||
|
<a href="#book" class="hero-cta">Book Scott for Your Event</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Speaker Reel -->
|
||||||
|
<section class="reel-section">
|
||||||
|
<div class="section-container">
|
||||||
|
<h2>Watch the Reel</h2>
|
||||||
|
|
||||||
|
<div class="video-container">
|
||||||
|
<div class="video-placeholder">
|
||||||
|
<p>🎬 Speaker reel in production</p>
|
||||||
|
<p>Coming soon — 3-minute highlight reel from keynotes and workshops.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Signature Talks -->
|
||||||
|
<section class="talks-section">
|
||||||
|
<div class="section-container">
|
||||||
|
<h2>Signature Talks</h2>
|
||||||
|
|
||||||
|
<div class="talks-list">
|
||||||
|
|
||||||
|
<TalkCard
|
||||||
|
title="50 First Dates with AI"
|
||||||
|
premise="Current AI memory architecture is anterograde amnesia — and we're all Henry Roth, recording VHS tapes every night so our agent can wake up functional tomorrow."
|
||||||
|
idealFor="Engineering leaders, AI product teams, CTOs implementing agentic systems"
|
||||||
|
takeaways={[
|
||||||
|
"Why your AI's 'memory' is actually just replay, not learning",
|
||||||
|
"The three-layer memory architecture that actually compounds",
|
||||||
|
"How to move from VHS tapes to persistent, evolving agents"
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TalkCard
|
||||||
|
title="From Strip-Mining to Cultivation"
|
||||||
|
premise="The shift from extraction to cultivation in AI-era teams. Why throughput optimization is killing your soil health."
|
||||||
|
idealFor="CTOs, VP Engineering, people leaders, engineering managers"
|
||||||
|
takeaways={[
|
||||||
|
"The difference between strip-mining and cultivation mindsets",
|
||||||
|
"How to assess your team's soil health",
|
||||||
|
"Practices that cultivate instead of extract"
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TalkCard
|
||||||
|
title="The Soil Under Your Team"
|
||||||
|
premise="Diagnose what's actually depleted before you fertilize. A diagnostic framework for team health in AI-augmented work."
|
||||||
|
idealFor="Team leads, managers, engineering directors, founders"
|
||||||
|
takeaways={[
|
||||||
|
"The four soil nutrients every team needs",
|
||||||
|
"How to run a cultivation assessment",
|
||||||
|
"From diagnosis to cultivation roadmap"
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Past Events -->
|
||||||
|
<section class="events-section">
|
||||||
|
<div class="section-container">
|
||||||
|
<h2>Past Events</h2>
|
||||||
|
|
||||||
|
<div class="events-list">
|
||||||
|
<article class="event-item">
|
||||||
|
<h3>Game Changers Summit 2026</h3>
|
||||||
|
<p>Featured Speaker — "From Strip-Mining to Cultivation"</p>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="event-item">
|
||||||
|
<h3>AI Engineering Leadership Forum</h3>
|
||||||
|
<p>Keynote — "50 First Dates with AI"</p>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Book Scott Section -->
|
||||||
|
<section id="book" class="book-section">
|
||||||
|
<div class="section-container">
|
||||||
|
<h2>Book Scott</h2>
|
||||||
|
|
||||||
|
<div class="book-grid">
|
||||||
|
|
||||||
|
<!-- Booking Form -->
|
||||||
|
<div class="book-form">
|
||||||
|
<h3>Inquiry Form</h3>
|
||||||
|
|
||||||
|
<form action="https://formspree.io/f/PLACEHOLDER" method="POST">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="name">Name *</label>
|
||||||
|
<input type="text" id="name" name="name" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="email">Email *</label>
|
||||||
|
<input type="email" id="email" name="email" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="event-date">Event Date</label>
|
||||||
|
<input type="date" id="event-date" name="event-date" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="event-type">Event Type</label>
|
||||||
|
<select id="event-type" name="event-type">
|
||||||
|
<option value="">Select...</option>
|
||||||
|
<option value="conference">Conference</option>
|
||||||
|
<option value="corporate">Corporate Event</option>
|
||||||
|
<option value="workshop">Workshop</option>
|
||||||
|
<option value="other">Other</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="message">Message *</label>
|
||||||
|
<textarea id="message" name="message" rows="4" required></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="submit-btn">Send Inquiry</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- One Sheet & Quick Info -->
|
||||||
|
<div class="book-info">
|
||||||
|
<h3>Quick Info</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><strong>Keynote length:</strong> 45–60 minutes</li>
|
||||||
|
<li><strong>Workshop length:</strong> Half-day or full-day</li>
|
||||||
|
<li><strong>Topics:</strong> AI, leadership, team cultivation, mentoring</li>
|
||||||
|
<li><strong>Audience:</strong> Engineering leaders, CTOs, people managers</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<a href="/downloads/Scott-Scoble-Human-Cultivation-Expert-Speaker-Profile.pdf" class="download-btn" download>📄 Download Speaker Profile (PDF)</a>
|
||||||
|
|
||||||
|
<p class="contact-alt">Or email: <a href="mailto:scott@scoble.me">scott@scoble.me</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</BaseLayout>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.hero {
|
||||||
|
background: var(--color-cream);
|
||||||
|
padding: 5rem 2rem 4rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-content {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-kicker {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
color: var(--color-green);
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: clamp(1.75rem, 4vw, 2.5rem);
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
margin: 0 0 2rem;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-cta {
|
||||||
|
display: inline-block;
|
||||||
|
background: var(--color-amber);
|
||||||
|
color: white;
|
||||||
|
padding: 0.875rem 2rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-container {
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 4rem 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
section h2 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: 2rem;
|
||||||
|
margin: 0 0 2rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reel-section {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-container {
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
|
background: var(--color-cream-warm);
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-placeholder {
|
||||||
|
text-align: center;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-placeholder p:first-child {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.talks-section {
|
||||||
|
background: var(--color-cream);
|
||||||
|
}
|
||||||
|
|
||||||
|
.talks-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.events-section {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.events-list {
|
||||||
|
display: grid;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-item {
|
||||||
|
padding: 1.5rem;
|
||||||
|
background: var(--color-cream);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-item h3 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-item p {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-section {
|
||||||
|
background: var(--color-brown-dark);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-section h2 {
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.book-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-form {
|
||||||
|
background: white;
|
||||||
|
color: var(--color-text);
|
||||||
|
padding: 2rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-form h3 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
margin: 0 0 1.5rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group label {
|
||||||
|
display: block;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 0.375rem;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group input,
|
||||||
|
.form-group select,
|
||||||
|
.form-group textarea {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.625rem;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group input:focus,
|
||||||
|
.form-group select:focus,
|
||||||
|
.form-group textarea:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: var(--color-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
background: var(--color-amber);
|
||||||
|
color: white;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn:hover {
|
||||||
|
background: var(--color-amber-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-info h3 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
margin: 0 0 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-info ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 0 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-info li {
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-btn {
|
||||||
|
display: block;
|
||||||
|
background: var(--color-amber);
|
||||||
|
color: white;
|
||||||
|
padding: 0.75rem 1.25rem;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-alt {
|
||||||
|
color: rgba(255,255,255,0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-alt a {
|
||||||
|
color: var(--color-amber-light);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
103
src/pages/wp-admin.astro
Normal file
103
src/pages/wp-admin.astro
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
---
|
||||||
|
// Honeypot page — static version, logs via client-side
|
||||||
|
const honeypotLog = {
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
message: 'Honeypot page accessed'
|
||||||
|
};
|
||||||
|
---
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>WordPress › Login</title>
|
||||||
|
<meta name="robots" content="noindex,nofollow">
|
||||||
|
<style>
|
||||||
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||||
|
background: #f0f0f1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
.login-form {
|
||||||
|
background: #fff;
|
||||||
|
padding: 40px;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
||||||
|
width: 320px;
|
||||||
|
}
|
||||||
|
.login-form h1 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
color: #1d2327;
|
||||||
|
}
|
||||||
|
.login-form input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
border: 1px solid #8c8f94;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.login-form button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
background: #2271b1;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.login-form button:hover {
|
||||||
|
background: #135e96;
|
||||||
|
}
|
||||||
|
.login-form .message {
|
||||||
|
margin-top: 15px;
|
||||||
|
padding: 10px;
|
||||||
|
background: #fcf3e8;
|
||||||
|
border-left: 4px solid #dba617;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #3c434a;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="login-form">
|
||||||
|
<h1>WordPress</h1>
|
||||||
|
<form method="post" action="/wp-admin">
|
||||||
|
<input type="text" name="log" placeholder="Username or Email Address" autocomplete="off" >
|
||||||
|
<input type="password" name="pwd" placeholder="Password" >
|
||||||
|
<button type="submit" id="submit-btn">Log In</button>
|
||||||
|
</form>
|
||||||
|
<div class="message" id="message" style="display:none;">
|
||||||
|
<strong>ERROR:</strong> Incorrect username or password. Please try again.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Waste their time with fake loading
|
||||||
|
document.querySelector('form').addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var btn = document.getElementById('submit-btn');
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.textContent = 'Logging in...';
|
||||||
|
|
||||||
|
// 3 second fake delay, then error
|
||||||
|
setTimeout(function() {
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.textContent = 'Log In';
|
||||||
|
document.getElementById('message').style.display = 'block';
|
||||||
|
|
||||||
|
// Clear the form so they try again
|
||||||
|
document.querySelector('[name="log"]').value = '';
|
||||||
|
document.querySelector('[name="pwd"]').value = '';
|
||||||
|
document.querySelector('[name="log"]').focus();
|
||||||
|
}, 3000);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
479
src/styles/global.css
Normal file
479
src/styles/global.css
Normal file
|
|
@ -0,0 +1,479 @@
|
||||||
|
/* ==========================================================================
|
||||||
|
Brand Site — Global Styles
|
||||||
|
Design System: "Cultivation Aesthetic"
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/* --- Google Fonts (EB Garamond) --- */
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500&display=swap');
|
||||||
|
|
||||||
|
/* --- CSS Variables (Design Tokens) --- */
|
||||||
|
:root {
|
||||||
|
/* Colors */
|
||||||
|
--color-brown: #4a4438;
|
||||||
|
--color-brown-dark: #2d2a24;
|
||||||
|
--color-green: #3d5a3e;
|
||||||
|
--color-green-dark: #2d5a3e;
|
||||||
|
--color-cream: #faf8f5;
|
||||||
|
--color-cream-warm: #f5f0e8;
|
||||||
|
--color-amber: #c8952e;
|
||||||
|
--color-amber-light: #d4a94e;
|
||||||
|
--color-text: #2d2a24;
|
||||||
|
--color-text-muted: #6b6458;
|
||||||
|
--color-border: #e0dbd2;
|
||||||
|
--color-border-light: #ede9e2;
|
||||||
|
--color-bg: #faf8f5;
|
||||||
|
--color-bg-alt: #f5f0e8;
|
||||||
|
--color-focus: #3d5a3e;
|
||||||
|
|
||||||
|
/* Typography */
|
||||||
|
--font-heading: 'EB Garamond', Georgia, 'Times New Roman', serif;
|
||||||
|
--font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||||
|
--font-mono: 'SF Mono', 'Fira Code', 'Fira Mono', 'Roboto Mono', monospace;
|
||||||
|
|
||||||
|
/* Sizes */
|
||||||
|
--size-xs: 0.75rem; /* 12px */
|
||||||
|
--size-sm: 0.875rem; /* 14px */
|
||||||
|
--size-base: 1rem; /* 16px */
|
||||||
|
--size-md: 1.125rem; /* 18px */
|
||||||
|
--size-lg: 1.25rem; /* 20px */
|
||||||
|
--size-xl: 1.5rem; /* 24px */
|
||||||
|
--size-2xl: 2rem; /* 32px */
|
||||||
|
--size-3xl: 2.5rem; /* 40px */
|
||||||
|
--size-4xl: 3rem; /* 48px */
|
||||||
|
|
||||||
|
/* Spacing */
|
||||||
|
--space-xs: 0.25rem;
|
||||||
|
--space-sm: 0.5rem;
|
||||||
|
--space-md: 1rem;
|
||||||
|
--space-lg: 1.5rem;
|
||||||
|
--space-xl: 2rem;
|
||||||
|
--space-2xl: 3rem;
|
||||||
|
--space-3xl: 4rem;
|
||||||
|
--space-4xl: 6rem;
|
||||||
|
|
||||||
|
/* Layout */
|
||||||
|
--max-width-prose: 44rem; /* ~704px */
|
||||||
|
--max-width-wide: 68rem; /* ~1088px */
|
||||||
|
--nav-height: 4rem;
|
||||||
|
|
||||||
|
/* Transitions */
|
||||||
|
--transition-fast: 150ms ease;
|
||||||
|
--transition-base: 250ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Reset & Base --- */
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
scroll-padding-top: var(--nav-height);
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: var(--font-body);
|
||||||
|
font-size: var(--size-base);
|
||||||
|
line-height: 1.7;
|
||||||
|
color: var(--color-text);
|
||||||
|
background-color: var(--color-bg);
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Typography --- */
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.2;
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 { font-size: var(--size-4xl); letter-spacing: -0.02em; }
|
||||||
|
h2 { font-size: var(--size-2xl); }
|
||||||
|
h3 { font-size: var(--size-xl); }
|
||||||
|
h4 { font-size: var(--size-lg); }
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-bottom: var(--space-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--color-green);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover,
|
||||||
|
a:focus-visible {
|
||||||
|
color: var(--color-amber);
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul, ol {
|
||||||
|
margin-bottom: var(--space-md);
|
||||||
|
padding-left: var(--space-xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-bottom: var(--space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 3px solid var(--color-amber);
|
||||||
|
padding: var(--space-md) var(--space-lg);
|
||||||
|
margin: var(--space-lg) 0;
|
||||||
|
background: var(--color-cream-warm);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid var(--color-border);
|
||||||
|
margin: var(--space-2xl) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.9em;
|
||||||
|
padding: 0.1em 0.3em;
|
||||||
|
background: var(--color-cream-warm);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Skip to Content --- */
|
||||||
|
.skip-link {
|
||||||
|
position: absolute;
|
||||||
|
top: -100%;
|
||||||
|
left: var(--space-md);
|
||||||
|
padding: var(--space-sm) var(--space-md);
|
||||||
|
background: var(--color-green);
|
||||||
|
color: white;
|
||||||
|
font-weight: 600;
|
||||||
|
border-radius: 4px;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-link:focus {
|
||||||
|
top: var(--space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Focus Styles --- */
|
||||||
|
:focus-visible {
|
||||||
|
outline: 2px solid var(--color-focus);
|
||||||
|
outline-offset: 2px;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Utility Classes --- */
|
||||||
|
.sr-only {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
padding: 0;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
white-space: nowrap;
|
||||||
|
border-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
max-width: var(--max-width-wide);
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 var(--space-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-narrow {
|
||||||
|
max-width: var(--max-width-prose);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Buttons --- */
|
||||||
|
.btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0.625rem 1.5rem;
|
||||||
|
font-family: var(--font-body);
|
||||||
|
font-size: var(--size-sm);
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.5;
|
||||||
|
text-decoration: none;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background: var(--color-amber);
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
border-color: var(--color-amber);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover,
|
||||||
|
.btn-primary:focus-visible {
|
||||||
|
background: var(--color-amber-light);
|
||||||
|
border-color: var(--color-amber-light);
|
||||||
|
color: var(--color-brown-dark);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline {
|
||||||
|
background: transparent;
|
||||||
|
color: var(--color-green);
|
||||||
|
border-color: var(--color-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-outline:hover,
|
||||||
|
.btn-outline:focus-visible {
|
||||||
|
background: var(--color-green);
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-large {
|
||||||
|
padding: 0.75rem 2rem;
|
||||||
|
font-size: var(--size-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Page Sections --- */
|
||||||
|
.section {
|
||||||
|
padding: var(--space-4xl) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: var(--space-3xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header h2 {
|
||||||
|
margin-bottom: var(--space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header .section-subtitle {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
font-size: var(--size-md);
|
||||||
|
max-width: 36rem;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Cards (shared) --- */
|
||||||
|
.card {
|
||||||
|
background: white;
|
||||||
|
border: 1px solid var(--color-border-light);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: var(--space-xl);
|
||||||
|
transition: box-shadow var(--transition-base) var(--transition-base);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover {
|
||||||
|
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.07);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-grid {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--space-xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.card-grid { grid-template-columns: repeat(2, 1fr); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.card-grid { grid-template-columns: repeat(3, 1fr); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Hero (shared) --- */
|
||||||
|
.hero {
|
||||||
|
padding: var(--space-4xl) 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 {
|
||||||
|
margin-bottom: var(--space-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero .hero-subtitle {
|
||||||
|
font-size: var(--size-xl);
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
max-width: var(--max-width-prose);
|
||||||
|
margin: 0 auto var(--space-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero .hero-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--space-md);
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Forms --- */
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: var(--space-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: var(--space-xs);
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: var(--size-sm);
|
||||||
|
color: var(--color-brown);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group input,
|
||||||
|
.form-group select,
|
||||||
|
.form-group textarea {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.625rem 0.75rem;
|
||||||
|
font-family: var(--font-body);
|
||||||
|
font-size: var(--size-base);
|
||||||
|
line-height: 1.5;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: 4px;
|
||||||
|
background: white;
|
||||||
|
color: var(--color-text);
|
||||||
|
transition: border-color var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group input:focus,
|
||||||
|
.form-group select:focus,
|
||||||
|
.form-group textarea:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: var(--color-green);
|
||||||
|
box-shadow: 0 0 0 3px rgba(61, 90, 62, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group textarea {
|
||||||
|
min-height: 8rem;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Featured / As Seen In --- */
|
||||||
|
.featured-logos {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: var(--space-2xl);
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: var(--space-2xl) 0;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.featured-logo {
|
||||||
|
font-family: var(--font-heading);
|
||||||
|
font-size: var(--size-lg);
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Testimonials --- */
|
||||||
|
.testimonials-grid {
|
||||||
|
display: grid;
|
||||||
|
gap: var(--space-xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.testimonials-grid {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.testimonials-grid {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Page Header (non-hero pages) --- */
|
||||||
|
.page-header {
|
||||||
|
padding: var(--space-3xl) 0 var(--space-2xl);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header h1 {
|
||||||
|
margin-bottom: var(--space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header p {
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
font-size: var(--size-md);
|
||||||
|
max-width: var(--max-width-prose);
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Prose --- */
|
||||||
|
.prose {
|
||||||
|
max-width: var(--max-width-prose);
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose h2 {
|
||||||
|
margin-top: var(--space-2xl);
|
||||||
|
margin-bottom: var(--space-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose h3 {
|
||||||
|
margin-top: var(--space-xl);
|
||||||
|
margin-bottom: var(--space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose p {
|
||||||
|
margin-bottom: var(--space-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose ul {
|
||||||
|
margin-bottom: var(--space-md);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Footer --- */
|
||||||
|
.site-footer {
|
||||||
|
background: var(--color-brown-dark);
|
||||||
|
color: var(--color-cream);
|
||||||
|
padding: var(--space-3xl) 0 var(--space-xl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-footer a {
|
||||||
|
color: var(--color-amber);
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-footer a:hover {
|
||||||
|
color: var(--color-amber-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Responsive --- */
|
||||||
|
@media (max-width: 639px) {
|
||||||
|
:root {
|
||||||
|
--size-4xl: 2.25rem;
|
||||||
|
--size-2xl: 1.5rem;
|
||||||
|
--size-xl: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
padding: var(--space-2xl) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero {
|
||||||
|
padding: var(--space-2xl) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
padding: 0 var(--space-md);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 640px) and (max-width: 1023px) {
|
||||||
|
:root {
|
||||||
|
--size-4xl: 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
5
tsconfig.json
Normal file
5
tsconfig.json
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"extends": "astro/tsconfigs/strict",
|
||||||
|
"include": [".astro/types.d.ts", "**/*"],
|
||||||
|
"exclude": ["dist"]
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue