refactor(email): align templates with frontend design tokens from app.css

- @theme now mirrors all :root variables from app.css (background, foreground,
  card, muted, muted-foreground, border, primary, primary-foreground)
- Replaced all zinc-* utilities with semantic token classes (bg-background,
  bg-card, bg-muted, text-foreground, text-muted-foreground, border-border, etc.)
- Added Noto Sans via Google Fonts import (progressive enhancement — skips
  Tailwind processing via `plain` attribute)
- Font family @theme token set to Noto Sans with system-font fallbacks
- Button inline styles updated to use hex equivalent of --primary-foreground

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 10:49:23 +01:00
parent 60531771cf
commit a30692b1ac
3 changed files with 49 additions and 38 deletions

View File

@@ -9,28 +9,39 @@
<noscript><xml><o:OfficeDocumentSettings><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml></noscript> <noscript><xml><o:OfficeDocumentSettings><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml></noscript>
<![endif]--> <![endif]-->
<title>{{ page.title || 'sexy.pivoine.art' }}</title> <title>{{ page.title || 'sexy.pivoine.art' }}</title>
<!-- Noto Sans for clients that support web fonts (Gmail, Apple Mail) -->
<style plain>
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;600;700&display=swap');
</style>
<style> <style>
@import "@maizzle/tailwindcss"; @import "@maizzle/tailwindcss";
@theme { @theme {
/* Brand colors — match frontend app.css */ /* ── Design tokens — exact mirror of frontend app.css :root ── */
--color-brand: oklch(56.971% 0.27455 319.257); --color-background: oklch(0.98 0.01 320);
--color-brand-foreground: oklch(0.98 0.01 320); --color-foreground: oklch(0.08 0.02 280);
--color-brand-dark: oklch(48% 0.26 319); --color-card: oklch(0.99 0.005 320);
--color-card-foreground: oklch(0.08 0.02 280);
--color-muted: oklch(0.95 0.01 280);
--color-muted-foreground: oklch(0.4 0.02 280);
--color-border: oklch(0.85 0.02 280);
--color-primary: oklch(56.971% 0.27455 319.257);
--color-primary-foreground: oklch(0.98 0.01 320);
/* Surface */ /* ── Font ── */
--color-surface: oklch(0.98 0.01 320); --font-sans: 'Noto Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
--color-on-dark: oklch(0.98 0.01 280); Helvetica, Arial, sans-serif;
} }
</style> </style>
</head> </head>
<body class="bg-[oklch(0.95_0.01_310)] m-0 p-0 font-sans"> <body class="bg-background m-0 p-0 font-sans">
<!-- Preview text (hidden) --> <!-- Preview text (hidden) -->
<if condition="page.previewText || previewText"> <if condition="page.previewText || previewText">
<div class="hidden max-h-0 overflow-hidden"> <div class="hidden max-h-0 overflow-hidden">
{{ page.previewText || previewText }} {{ page.previewText || previewText }}
<!-- padding to push any trailing content out of preview -->
&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj; &nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;&nbsp;&zwnj;
</div> </div>
</if> </if>
@@ -38,31 +49,31 @@
<div class="py-8 px-4"> <div class="py-8 px-4">
<table class="w-full max-w-[600px] mx-auto" role="presentation" cellpadding="0" cellspacing="0" border="0"> <table class="w-full max-w-[600px] mx-auto" role="presentation" cellpadding="0" cellspacing="0" border="0">
<!-- Brand header --> <!-- Brand header — uses --foreground as dark bg -->
<tr> <tr>
<td class="bg-[oklch(0.08_0.02_280)] rounded-t-2xl px-8 py-6 text-center"> <td class="bg-foreground rounded-t-2xl px-8 py-6 text-center">
<a href="{{ baseUrl }}" style="text-decoration: none"> <a href="{{ baseUrl }}" style="text-decoration: none">
<span class="text-sm font-semibold tracking-[0.22em] uppercase text-on-dark"> <span class="text-sm font-semibold tracking-[0.22em] uppercase text-background">
sexy<span class="text-brand">.</span>pivoine<span class="text-brand">.</span>art sexy<span class="text-primary">.</span>pivoine<span class="text-primary">.</span>art
</span> </span>
</a> </a>
</td> </td>
</tr> </tr>
<!-- Body --> <!-- Card body -->
<tr> <tr>
<td class="bg-white px-8 py-10 text-[14px] text-zinc-700 leading-relaxed"> <td class="bg-card px-8 py-10 text-[14px] text-card-foreground leading-relaxed">
<yield /> <yield />
</td> </td>
</tr> </tr>
<!-- Footer --> <!-- Footer -->
<tr> <tr>
<td class="bg-zinc-50 border-t border-zinc-100 rounded-b-2xl px-8 py-6 text-center"> <td class="bg-muted border-t border-border rounded-b-2xl px-8 py-6 text-center">
<p class="text-[11px] text-zinc-400 m-0"> <p class="text-[11px] text-muted-foreground m-0">
&copy; {{ new Date().getFullYear() }} sexy.pivoine.art &mdash; For adults only (18+) &copy; {{ new Date().getFullYear() }} sexy.pivoine.art &mdash; For adults only (18+)
</p> </p>
<p class="text-[11px] text-zinc-400 mt-2 mb-0"> <p class="text-[11px] text-muted-foreground mt-2 mb-0">
If you did not request this email, you can safely ignore it. If you did not request this email, you can safely ignore it.
</p> </p>
</td> </td>

View File

@@ -5,38 +5,38 @@ previewText: "You requested a password reset. Use the link below to set a new on
<x-main> <x-main>
<h1 class="text-[22px] font-semibold text-zinc-900 m-0 mb-2"> <h1 class="text-[22px] font-semibold text-foreground m-0 mb-2">
Reset your password Reset your password
</h1> </h1>
<p class="text-zinc-500 m-0 mb-6"> <p class="text-muted-foreground m-0 mb-6">
We received a request to reset the password for your account. Click the button below to choose a new one. We received a request to reset the password for your account. Click the button below to choose a new one.
</p> </p>
<!-- CTA button --> <!-- CTA button — inline style needed for Outlook -->
<table role="presentation" cellpadding="0" cellspacing="0" border="0" class="mb-6"> <table role="presentation" cellpadding="0" cellspacing="0" border="0" class="mb-6">
<tr> <tr>
<td class="rounded-lg" style="background: #b700d9"> <td class="rounded-lg" style="background: #b700d9">
<a href="{{ url }}" <a href="{{ url }}"
class="inline-block px-8 py-[14px] text-[14px] font-semibold text-white no-underline rounded-lg" class="inline-block px-8 py-[14px] text-[14px] font-semibold text-primary-foreground no-underline rounded-lg"
style="background: #b700d9"> style="background: #b700d9; color: #faf4fb">
Reset my password Reset my password
</a> </a>
</td> </td>
</tr> </tr>
</table> </table>
<p class="text-[13px] text-zinc-500 m-0 mb-6"> <p class="text-[13px] text-muted-foreground m-0 mb-6">
This link expires in <strong class="text-zinc-700">1 hour</strong>. This link expires in <strong class="text-foreground">1 hour</strong>.
If you did not request a password reset, no action is needed — your account remains secure. If you did not request a password reset, no action is needed — your account remains secure.
</p> </p>
<hr class="border-0 border-t border-zinc-100 my-6" /> <hr class="border-0 border-t border-border my-6" />
<p class="text-[12px] text-zinc-400 m-0"> <p class="text-[12px] text-muted-foreground m-0">
Button not working? Copy and paste this link into your browser: Button not working? Copy and paste this link into your browser:
</p> </p>
<p class="text-[12px] m-0 mt-1"> <p class="text-[12px] m-0 mt-1">
<a href="{{ url }}" class="text-brand break-all" style="color: #b700d9"> <a href="{{ url }}" class="text-primary break-all" style="color: #b700d9">
{{ url }} {{ url }}
</a> </a>
</p> </p>

View File

@@ -5,37 +5,37 @@ previewText: "Almost there — confirm your email address to activate your accou
<x-main> <x-main>
<h1 class="text-[22px] font-semibold text-zinc-900 m-0 mb-2"> <h1 class="text-[22px] font-semibold text-foreground m-0 mb-2">
Verify your email address Verify your email address
</h1> </h1>
<p class="text-zinc-500 m-0 mb-6"> <p class="text-muted-foreground m-0 mb-6">
Thanks for signing up! Click the button below to confirm your email address and activate your account. Thanks for signing up! Click the button below to confirm your email address and activate your account.
</p> </p>
<!-- CTA button --> <!-- CTA button — inline style needed for Outlook -->
<table role="presentation" cellpadding="0" cellspacing="0" border="0" class="mb-6"> <table role="presentation" cellpadding="0" cellspacing="0" border="0" class="mb-6">
<tr> <tr>
<td class="rounded-lg" style="background: #b700d9"> <td class="rounded-lg" style="background: #b700d9">
<a href="{{ url }}" <a href="{{ url }}"
class="inline-block px-8 py-[14px] text-[14px] font-semibold text-white no-underline rounded-lg" class="inline-block px-8 py-[14px] text-[14px] font-semibold text-primary-foreground no-underline rounded-lg"
style="background: #b700d9"> style="background: #b700d9; color: #faf4fb">
Verify my email Verify my email
</a> </a>
</td> </td>
</tr> </tr>
</table> </table>
<p class="text-[13px] text-zinc-500 m-0 mb-6"> <p class="text-[13px] text-muted-foreground m-0 mb-6">
This link expires in <strong class="text-zinc-700">24 hours</strong>. This link expires in <strong class="text-foreground">24 hours</strong>.
</p> </p>
<hr class="border-0 border-t border-zinc-100 my-6" /> <hr class="border-0 border-t border-border my-6" />
<p class="text-[12px] text-zinc-400 m-0"> <p class="text-[12px] text-muted-foreground m-0">
Button not working? Copy and paste this link into your browser: Button not working? Copy and paste this link into your browser:
</p> </p>
<p class="text-[12px] m-0 mt-1"> <p class="text-[12px] m-0 mt-1">
<a href="{{ url }}" class="text-brand break-all" style="color: #b700d9"> <a href="{{ url }}" class="text-primary break-all" style="color: #b700d9">
{{ url }} {{ url }}
</a> </a>
</p> </p>