292 lines
17 KiB
Cheetah
292 lines
17 KiB
Cheetah
{{- /*
|
|
The Vantage email shell.
|
|
|
|
Every colour in the email system lives in this file and nowhere else, in the
|
|
same way no component in web/, site/ or adminsite/ carries a hex. The values
|
|
are web/app/globals.css's tokens - an email is read before the recipient
|
|
clicks through to the control plane, so the two should not look like
|
|
different products. They are written as literal hex here because email
|
|
clients support neither var() nor a reliable prefers-color-scheme, so the
|
|
usual token indirection is not available: when you change a token in the
|
|
three globals.css files, change it here too.
|
|
|
|
--ground #071628 --rule #1e3855
|
|
--panel #0d2138 --accent #5b9be8
|
|
--panel-2 #102842 --up #4fb484
|
|
--ink #e4ecf6 --down #e2705a
|
|
--ink-2 #9fb3ca --pend #d6a63f
|
|
--ink-3 #71879f --well #04101f
|
|
|
|
Derived here only, never in a front end: each tone has a tint (15% over
|
|
--panel) for washes and a border (35% over --panel) for outlines.
|
|
|
|
up #173743 / #245452 pend #2b3539 / #534f3a
|
|
down #2d2d3d / #573d44 accent #193352 / #284b75
|
|
|
|
Layout is tables and inline styles throughout, which is not a stylistic
|
|
choice - it is the only thing Outlook renders predictably.
|
|
|
|
A message file overrides "title", "pill", "body", "category", "preheader"
|
|
and "why"; its txt file defines "subject" and "tone". The defaults below
|
|
exist so that a message needing no pill does not have to define one.
|
|
|
|
Colour choices that depend on a tone go through pick, which takes the tone
|
|
and one value per tone (up, down, pend, accent, anything else), so the hex
|
|
stays in this file while the branching stays out of it.
|
|
*/ -}}
|
|
{{- define "title"}}{{end -}}
|
|
{{- define "pill"}}{{end -}}
|
|
{{- define "body"}}{{end -}}
|
|
{{- define "category"}}Account{{end -}}
|
|
{{- define "preheader"}}{{end -}}
|
|
{{- define "why"}}it relates to your Vantage account.{{end -}}
|
|
|
|
{{- /* p renders one paragraph of body copy. */ -}}
|
|
{{- define "p" -}}
|
|
<p style="margin:0 0 16px;color:#9fb3ca;font-size:14px;line-height:1.65;">{{.}}</p>
|
|
{{- end -}}
|
|
|
|
{{- /* lead is the first paragraph: larger, brighter, sets the subject. */ -}}
|
|
{{- define "lead" -}}
|
|
<p style="margin:0 0 20px;color:#e4ecf6;font-size:16px;line-height:1.6;">{{.}}</p>
|
|
{{- end -}}
|
|
|
|
{{- /* small is fine print under a section. */ -}}
|
|
{{- define "small" -}}
|
|
<p style="margin:0 0 16px;color:#71879f;font-size:12px;line-height:1.6;">{{.}}</p>
|
|
{{- end -}}
|
|
|
|
{{- /* label is an eyebrow over the section that follows it. */ -}}
|
|
{{- define "label" -}}
|
|
<p style="margin:24px 0 10px;color:#71879f;font-size:11px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;">{{.}}</p>
|
|
{{- end -}}
|
|
|
|
{{- define "divider" -}}
|
|
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin:8px 0 20px;"><tr><td style="height:1px;line-height:1px;font-size:0;background:#1e3855;"> </td></tr></table>
|
|
{{- end -}}
|
|
|
|
{{- /* button takes dict "label" "…" "url" "…", and optionally "nofallback".
|
|
|
|
The bare URL is printed underneath on purpose: a plain-text-preferring
|
|
client, a stripped-styles inbox and a forwarded message all lose the
|
|
anchor, and a verification email whose link cannot be reached is a
|
|
support ticket. nofallback is for mailto: links, where it would be noise. */ -}}
|
|
{{- define "button" -}}
|
|
<table role="presentation" cellpadding="0" cellspacing="0" style="margin:4px 0 14px;">
|
|
<tr>
|
|
<td style="border-radius:6px;background:#5b9be8;">
|
|
<a href="{{.url}}" style="display:inline-block;padding:12px 24px;color:#04101f;font-size:14px;font-weight:700;text-decoration:none;border-radius:6px;">{{.label}} →</a>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
{{- if not .nofallback}}
|
|
<p style="margin:0 0 22px;color:#71879f;font-size:12px;line-height:1.5;word-break:break-all;">
|
|
Button not working? Paste this into your browser:<br>
|
|
<a href="{{.url}}" style="color:#5b9be8;text-decoration:none;">{{.url}}</a>
|
|
</p>
|
|
{{- end}}
|
|
{{- end -}}
|
|
|
|
{{- /* well shows machine output - a licence blob, an install ID. Mirrors
|
|
web/'s --well surface, the floor beneath the ground. */ -}}
|
|
{{- define "well" -}}
|
|
<pre style="margin:0 0 20px;padding:14px 16px;background:#04101f;border:1px solid #1e3855;border-radius:6px;color:#9fb3ca;font-family:ui-monospace,'Cascadia Mono','SF Mono',Menlo,Consolas,monospace;font-size:12px;line-height:1.55;white-space:pre-wrap;word-break:break-all;">{{.}}</pre>
|
|
{{- end -}}
|
|
|
|
{{- /* note is a quoted callout, used for a free-text message we did not
|
|
write ourselves. Line breaks are kept: it is somebody's own words. */ -}}
|
|
{{- define "note" -}}
|
|
<p style="margin:0 0 20px;padding:14px 16px;background:#102842;border:1px solid #1e3855;border-radius:6px;color:#e4ecf6;font-size:13px;line-height:1.65;white-space:pre-wrap;">{{.}}</p>
|
|
{{- end -}}
|
|
|
|
{{- /* rows takes a list of dict "k" "…" "v" "…", and renders them as one
|
|
panel of facts. */ -}}
|
|
{{- define "rows" -}}
|
|
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin:4px 0 20px;background:#102842;border:1px solid #1e3855;border-radius:6px;border-collapse:separate;">
|
|
{{- range $i, $r := .}}
|
|
<tr>
|
|
<td style="padding:11px 16px;{{if $i}}border-top:1px solid #172c44;{{end}}color:#71879f;font-size:13px;width:140px;vertical-align:top;">{{$r.k}}</td>
|
|
<td style="padding:11px 16px 11px 0;{{if $i}}border-top:1px solid #172c44;{{end}}color:#e4ecf6;font-size:13px;font-weight:600;word-break:break-word;">{{$r.v}}</td>
|
|
</tr>
|
|
{{- end}}
|
|
</table>
|
|
{{- end -}}
|
|
|
|
{{- /* chip takes dict "label" "…" "tone" "up|down|pend|accent|none". Tone is
|
|
never the only signal: the label spells the state out. */ -}}
|
|
{{- define "chip" -}}
|
|
{{- $fg := pick .tone "#4fb484" "#e2705a" "#d6a63f" "#5b9be8" "#9fb3ca"}}{{$bg := pick .tone "#173743" "#2d2d3d" "#2b3539" "#193352" "#102842"}}{{$bd := pick .tone "#245452" "#573d44" "#534f3a" "#284b75" "#1e3855" -}}
|
|
<span style="display:inline-block;padding:4px 11px;background:{{$bg}};border:1px solid {{$bd}};border-radius:9999px;color:{{$fg}};font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;white-space:nowrap;">{{.label}}</span>
|
|
{{- end -}}
|
|
|
|
{{- /* callout takes dict "tone" "…" "title" "…" "text" "…": one tinted panel
|
|
for the sentence the reader must not miss. */ -}}
|
|
{{- define "callout" -}}
|
|
{{- $fg := pick .tone "#4fb484" "#e2705a" "#d6a63f" "#5b9be8" "#9fb3ca"}}{{$bg := pick .tone "#173743" "#2d2d3d" "#2b3539" "#193352" "#102842"}}{{$bd := pick .tone "#245452" "#573d44" "#534f3a" "#284b75" "#1e3855" -}}
|
|
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin:4px 0 20px;background:{{$bg}};border:1px solid {{$bd}};border-radius:6px;border-collapse:separate;">
|
|
<tr>
|
|
<td style="padding:14px 16px;">
|
|
<p style="margin:0 0 4px;color:{{$fg}};font-size:13px;font-weight:700;">{{.title}}</p>
|
|
<p style="margin:0;color:#c3d1e1;font-size:13px;line-height:1.6;">{{.text}}</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
{{- end -}}
|
|
|
|
{{- /* steps takes a list of dict "t" "…" "d" "…". Numbered because the
|
|
content is always an order the reader follows. */ -}}
|
|
{{- define "steps" -}}
|
|
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin:0 0 20px;">
|
|
{{- range $i, $s := .}}
|
|
<tr>
|
|
<td width="28" style="width:28px;padding:0 12px 14px 0;vertical-align:top;">
|
|
<table role="presentation" cellpadding="0" cellspacing="0"><tr>
|
|
<td width="26" height="26" align="center" style="width:26px;height:26px;border-radius:9999px;background:#193352;border:1px solid #284b75;color:#7fb2f0;font-size:12px;font-weight:700;line-height:26px;text-align:center;">{{add $i 1}}</td>
|
|
</tr></table>
|
|
</td>
|
|
<td style="padding:3px 0 14px;vertical-align:top;">
|
|
<p style="margin:0 0 2px;color:#e4ecf6;font-size:14px;font-weight:600;line-height:1.4;">{{$s.t}}</p>
|
|
<p style="margin:0;color:#9fb3ca;font-size:13px;line-height:1.55;">{{$s.d}}</p>
|
|
</td>
|
|
</tr>
|
|
{{- end}}
|
|
</table>
|
|
{{- end -}}
|
|
|
|
{{- /* stats takes a list of dict "big" "…" "label" "…" "tone" "…": the
|
|
figures a message exists to state, such as days left. */ -}}
|
|
{{- define "stats" -}}
|
|
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin:0 0 20px;">
|
|
<tr>
|
|
{{- range $i, $s := .}}
|
|
{{- if $i}}<td width="10" style="width:10px;font-size:0;"> </td>{{end}}
|
|
<td style="padding:14px 16px;background:#102842;border:1px solid #1e3855;border-radius:6px;vertical-align:top;">
|
|
<p style="margin:0;color:{{pick $s.tone "#4fb484" "#e2705a" "#d6a63f" "#7fb2f0" "#e4ecf6"}};font-size:26px;font-weight:700;line-height:1.15;letter-spacing:-.01em;">{{$s.big}}</p>
|
|
<p style="margin:4px 0 0;color:#71879f;font-size:12px;line-height:1.4;">{{$s.label}}</p>
|
|
</td>
|
|
{{- end}}
|
|
</tr>
|
|
</table>
|
|
{{- end -}}
|
|
|
|
{{- /* timeline takes a list of dict "label" "…" "date" "…" "state"
|
|
"done|now|next" "tone" "…". It is the licence lifecycle, drawn as
|
|
segments so the reader sees where they are in it. */ -}}
|
|
{{- define "timeline" -}}
|
|
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin:4px 0 22px;table-layout:fixed;">
|
|
<tr>
|
|
{{- range $i, $s := .}}
|
|
{{- if $i}}<td width="6" style="width:6px;font-size:0;"> </td>{{end}}
|
|
<td style="vertical-align:top;">
|
|
<table role="presentation" width="100%" cellpadding="0" cellspacing="0"><tr><td style="height:4px;line-height:4px;font-size:0;border-radius:2px;background:{{if eq $s.state "now"}}{{pick $s.tone "#4fb484" "#e2705a" "#d6a63f" "#5b9be8" "#5b9be8"}}{{else if eq $s.state "done"}}#3d5673{{else}}#1e3855{{end}};"> </td></tr></table>
|
|
<p style="margin:10px 0 2px;color:{{if eq $s.state "now"}}{{pick $s.tone "#4fb484" "#e2705a" "#d6a63f" "#7fb2f0" "#7fb2f0"}}{{else}}#71879f{{end}};font-size:10px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;">{{$s.label}}</p>
|
|
<p style="margin:0;color:{{if eq $s.state "next"}}#9fb3ca{{else}}#e4ecf6{{end}};font-size:13px;font-weight:600;line-height:1.4;">{{$s.date}}</p>
|
|
</td>
|
|
{{- end}}
|
|
</tr>
|
|
</table>
|
|
{{- end -}}
|
|
|
|
{{- /* findings takes a list of VulnDigestRow: one line per finding, the
|
|
severity as a chip, the advisory linked when its ID says where it is. */ -}}
|
|
{{- define "findings" -}}
|
|
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin:0 0 16px;background:#102842;border:1px solid #1e3855;border-radius:6px;border-collapse:separate;">
|
|
{{- range $i, $r := .}}
|
|
<tr>
|
|
<td style="padding:12px 16px;{{if $i}}border-top:1px solid #172c44;{{end}}vertical-align:top;">
|
|
<p style="margin:0 0 6px;">{{template "chip" (dict "label" $r.Severity "tone" (sevTone $r.Severity))}} {{with advisoryURL $r.CVEID}}<a href="{{.}}" style="color:#7fb2f0;font-family:ui-monospace,'Cascadia Mono','SF Mono',Menlo,Consolas,monospace;font-size:13px;font-weight:700;text-decoration:none;">{{$r.CVEID}}</a>{{else}}<span style="color:#e4ecf6;font-family:ui-monospace,'Cascadia Mono','SF Mono',Menlo,Consolas,monospace;font-size:13px;font-weight:700;">{{$r.CVEID}}</span>{{end}}</p>
|
|
<p style="margin:0;color:#9fb3ca;font-size:13px;line-height:1.5;"><span style="color:#e4ecf6;font-weight:600;">{{$r.PackageName}}</span> on {{$r.ServerName}}</p>
|
|
</td>
|
|
<td align="right" style="padding:12px 16px 12px 0;{{if $i}}border-top:1px solid #172c44;{{end}}vertical-align:top;white-space:nowrap;font-size:12px;font-weight:600;">
|
|
{{- if $r.FixedIn}}<span style="color:#4fb484;">Fixed in {{$r.FixedIn}}</span>{{else}}<span style="color:#d6a63f;">No fix yet</span>{{end -}}
|
|
</td>
|
|
</tr>
|
|
{{- end}}
|
|
</table>
|
|
{{- end -}}
|
|
|
|
{{- $tone := tone -}}
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<meta name="color-scheme" content="dark">
|
|
<meta name="supported-color-schemes" content="dark">
|
|
<title>{{template "title" .}}</title>
|
|
</head>
|
|
<body style="margin:0;padding:0;background:#071628;" bgcolor="#071628">
|
|
<div style="display:none;max-height:0;overflow:hidden;opacity:0;color:#071628;font-size:1px;line-height:1px;">{{template "preheader" .}} ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏</div>
|
|
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" bgcolor="#071628" style="background:#071628;">
|
|
<tr>
|
|
<td align="center" style="padding:32px 12px 40px;">
|
|
<table role="presentation" width="560" cellpadding="0" cellspacing="0" style="max-width:560px;width:100%;font-family:ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;">
|
|
|
|
<tr>
|
|
<td style="padding:0 4px 16px;">
|
|
<table role="presentation" width="100%" cellpadding="0" cellspacing="0">
|
|
<tr>
|
|
<td style="vertical-align:middle;">
|
|
<table role="presentation" cellpadding="0" cellspacing="0"><tr>
|
|
<td width="28" height="28" align="center" style="width:28px;height:28px;border-radius:7px;background:#5b9be8;color:#04101f;font-size:15px;font-weight:800;line-height:28px;text-align:center;">V</td>
|
|
<td style="padding-left:10px;color:#e4ecf6;font-size:16px;font-weight:700;letter-spacing:-.01em;">Vantage</td>
|
|
</tr></table>
|
|
</td>
|
|
<td align="right" style="vertical-align:middle;color:#71879f;font-size:11px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;">{{template "category" .}}</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>
|
|
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background:#0d2138;border:1px solid #1e3855;border-radius:10px;border-collapse:separate;overflow:hidden;">
|
|
<tr><td style="height:4px;line-height:4px;font-size:0;background:{{pick $tone "#4fb484" "#e2705a" "#d6a63f" "#5b9be8" "#5b9be8"}};border-radius:10px 10px 0 0;"> </td></tr>
|
|
<tr>
|
|
<td style="padding:28px 32px 8px;background-color:#0d2138;background-image:linear-gradient(180deg,{{pick $tone "#173743" "#2d2d3d" "#2b3539" "#193352" "#193352"}} 0%,#0d2138 100%);">
|
|
<table role="presentation" cellpadding="0" cellspacing="0" style="margin:0 0 16px;"><tr>
|
|
<td width="40" height="40" align="center" style="width:40px;height:40px;border-radius:9999px;background:{{pick $tone "#173743" "#2d2d3d" "#2b3539" "#193352" "#193352"}};border:1px solid {{pick $tone "#245452" "#573d44" "#534f3a" "#284b75" "#284b75"}};color:{{pick $tone "#4fb484" "#e2705a" "#d6a63f" "#7fb2f0" "#7fb2f0"}};font-size:18px;font-weight:800;line-height:40px;text-align:center;">{{pick $tone "✓" "!" "!" "→" "→"}}</td>
|
|
<td style="padding-left:12px;vertical-align:middle;">{{template "pill" .}}</td>
|
|
</tr></table>
|
|
<h1 style="margin:0 0 6px;font-size:23px;font-weight:700;line-height:1.3;letter-spacing:-.01em;color:#e4ecf6;">{{template "title" .}}</h1>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding:12px 32px 12px;">
|
|
{{template "body" .}}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding:16px 32px 18px;border-top:1px solid #1e3855;background:#0a1c30;border-radius:0 0 10px 10px;">
|
|
<p style="margin:0;color:#71879f;font-size:12px;line-height:1.6;"><span style="color:#9fb3ca;font-weight:600;">Why you got this:</span> {{template "why" .}}</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td align="center" style="padding:22px 8px 0;">
|
|
{{- with hq}}
|
|
<p style="margin:0 0 10px;font-size:12px;line-height:1.6;">
|
|
<a href="{{.}}" style="color:#9fb3ca;text-decoration:none;font-weight:600;">Vantage HQ</a>
|
|
<span style="color:#3d5673;"> · </span>
|
|
<a href="{{.}}/instances" style="color:#9fb3ca;text-decoration:none;font-weight:600;">Instances</a>
|
|
<span style="color:#3d5673;"> · </span>
|
|
<a href="{{.}}/billing" style="color:#9fb3ca;text-decoration:none;font-weight:600;">Billing</a>
|
|
<span style="color:#3d5673;"> · </span>
|
|
<a href="{{.}}/settings" style="color:#9fb3ca;text-decoration:none;font-weight:600;">Settings</a>
|
|
</p>
|
|
{{- end}}
|
|
<p style="margin:0 0 4px;color:#71879f;font-size:12px;line-height:1.6;">Vantage · infrastructure control plane</p>
|
|
<p style="margin:0;color:#4f6680;font-size:11px;line-height:1.6;">© {{year}} Vantage. This is an automated message about your service.</p>
|
|
</td>
|
|
</tr>
|
|
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</body>
|
|
</html>
|