Design System · email module · v1.0 · may 2026

The system, ported
to inbox.

Modulo email-specific del Design System de Nostalgic. Fallbacks reales para clientes que no leen Geist ni rgba ni flexbox. Templates por flow (welcome, cart, post, winback, drop) con copy on-brand y productos reales. Listo para drop-in en crowdence-email-flows.

dominio envionotify.nostalgicapparel.com espResend (drop-in Postmark) fuentetokens.css v1.0 extraido2026-05-18 flows activoswelcome (4) · cart (3) · post (3) · winback (3) mantenedoradrian / claude

§01Foundations email

Lo que cambia cuando el render pasa del navegador al cliente de correo. Tipografia, color, ancho. Reglas duras antes de tocar componentes.

1.1 Por que Geist no llega — y como sobrevive

Outlook (Word engine) y la mayoria de clientes desktop NO cargan webfonts via @import ni <link>. Apple Mail / iOS Mail / Gmail web SI las cargan. Solucion: declarar Geist con un fallback stack agresivo. Cuando Geist no esta, cae a Inter → Helvetica Neue → Helvetica → Arial. La diferencia visual es minima: Inter es geometrica como Geist, Helvetica/Arial mantienen el aire neutral.

font-family: 'Geist', 'Inter', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-family: 'Geist Mono', 'SF Mono', Menlo, Consolas, 'Courier New', monospace;

si en email

  • Stack tipografico con fallbacks reales (5 fuentes minimo)
  • Inline-styles para clientes mas estrictos (Outlook, Gmail mobile)
  • Hex solido (sin rgba con alpha alto)
  • Anchos fijos en px (600 contenedor, 80 imagen)
  • Layouts table-based + inline-styles + role="presentation"

no en email

  • Custom properties (--nos-*) — Outlook las ignora
  • Flexbox / grid CSS — Outlook no, Gmail mobile parcial
  • rgba con alpha > 0.7 — render impredecible
  • SVG inline — Outlook no, Gmail si (parcial)
  • position absolute / sticky — sin soporte
  • JS, animaciones complejas, video

1.2 Paleta email-safe

Mismos tokens del DS, pero resueltos a hex solido. Las variantes ink-soft y ink-muted (rgba) se aproximan a hex (#4a4948 y #6b6b6a). Sin transparencias en backgrounds.

token DSvalor hex emailuso
--nos-bg#fffffffondo body interior
--nos-cream#edebe7header band, gutter exterior
--nos-ink#030302texto principal
--nos-ink-soft#4a4948aprox rgba(3,3,2,.76) sin alpha
--nos-ink-muted#6b6b6aaprox rgba(3,3,2,.55)
--nos-deep#000000footer, arcade
--nos-accent#2e4aa3eyebrow, link, badge sale
--nos-alert#d91d1dstripe, urgencia justificada
--nos-warm-border#d3cec5bordes producto, divisor

1.3 Ancho seguro · 600px

El estandar de la industria desde hace 15 anos. Outlook desktop renderiza fiable hasta 600px (algunos viewport-bugs por encima). Apple Mail / Gmail llegan a 700 sin problema. Mantenemos container max-width 600px para garantizar render universal. Padding lateral interno: 24-28px.

1.4 Escala tipografica email

Recortamos H1 del DS (72px) a 36px desktop / 28px mobile. Email es scrolleable y mas intimo: titulos huge no encajan en la inbox. El peso (600) y el kerning negativo (-1.1px) se mantienen para que el caracter Geist sobreviva.

elementodesktopmobile (≤600)pesokerning
H1 hero36px28px600-1.1px / -0.8px
H2 section28px22px600-0.6px
H320px18px600-0.2px
Eyebrow mono11px11px500+2px (letter-spacing)
Body16px15px400-0.1px
CTA label13px13px500+1.6px tracking
Caption mono11px11px500+1.6px

Tamano minimo body 14px. Por debajo de 12px en eyebrow Gmail mobile aumenta automaticamente — mejor mantenerse en 11px declarado para evitar inflation.

§02Estructura base email

El esqueleto HTML que cualquier email Nostalgic asume. Cabecera con hacks de soporte, body table-based, container 600 centrado. Esto es la "tabla base" — clonar y rellenar.

2.1 HEAD obligatorio

<!doctype html>
<html lang="es" xmlns="http://www.w3.org/1999/xhtml"
      xmlns:v="urn:schemas-microsoft-com:vml"
      xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="x-apple-disable-message-reformatting">
  <meta name="color-scheme" content="light dark">
  <meta name="supported-color-schemes" content="light dark">
  <title>Nostalgic · <!-- subject mirror --></title>

  <!--[if mso]>
  <noscript><xml><o:OfficeDocumentSettings>
    <o:PixelsPerInch>96</o:PixelsPerInch>
  </o:OfficeDocumentSettings></xml></noscript>
  <style type="text/css">
    table, td { border-collapse: collapse; mso-table-lspace:0; mso-table-rspace:0; }
    .fallback-font { font-family: Arial, sans-serif !important; }
  </style>
  <![endif]-->

  <link rel="preconnect" href="https://fonts.gstatic.com">
  <link href="https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=Geist+Mono:wght@400;500&display=swap"
        rel="stylesheet">

  <style>
    /* reset + media queries · ver email-fallback.css */
  </style>
</head>

2.2 Preheader hack (texto invisible para inbox preview)

Lo primero dentro de <body>. Es el texto que Gmail / Apple Mail muestran junto al subject en la inbox. No se ve en el email abierto.

<body id="body" style="margin:0;padding:0;background:#edebe7;">

  <!-- PREHEADER (45-90 caracteres). Espacios zero-width para empujar
       el texto de fallback que Gmail rellenaria automaticamente -->
  <div class="nos-preheader" style="display:none !important;
       visibility:hidden;opacity:0;color:transparent;height:0;width:0;
       max-height:0;max-width:0;overflow:hidden;mso-hide:all;
       font-size:1px;line-height:1px;">
    Pilot episode starts now. Press start whenever.
    &#847; &zwnj; &nbsp; &zwnj; &nbsp; &zwnj; &nbsp; &zwnj;
  </div>

  <!-- WRAPPER OUTER · color del gutter exterior -->
  <table role="presentation" width="100%" cellpadding="0" cellspacing="0"
         border="0" style="background:#edebe7;">
    <tr><td align="center">
      <!-- CONTAINER 600 -->
      <table role="presentation" width="600" cellpadding="0" cellspacing="0"
             border="0" class="nos-container" style="width:600px;max-width:600px;background:#ffffff;">
        <!-- contenido aqui -->
      </table>
    </td></tr>
  </table>
</body>

2.3 Anatomia de un email Nostalgic

Layout vertical estricto. Cinco bloques fijos, dos a tres bloques de contenido en el medio:

┌────────────────────────────────────────────┐ ← stripe 6px (azul 50% / rojo 50%) ├────────────────────────────────────────────┤ [logo wordmark 24px] ← header (bg #edebe7, padding 24) ├────────────────────────────────────────────┤ ▸ EPISODE 01 · 11:00 PM ← eyebrow mono You just joined the late- ← H1 36px Geist 600 night club. Welcome. Press start whenever you're ← body 16px Geist 400 ready. We're here all night. [▸ SEE THE DROP] ← CTA primary (table-based) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ← divider warm-border [product tile] [product tile] ← grid 2x (cae a stack en mobile) ├────────────────────────────────────────────┤ ▸ BUILT FOR LATE NIGHTS ← footer (bg #030302) & OLD GAMES instagram · web · soporte hello@nostalgicapparel.es notify.nostalgicapparel.com unsubscribe · update preferences └────────────────────────────────────────────┘

2.4 Padding rules

§03Componentes email

Pizzas de Lego. Cada uno con preview rendered + codigo HTML copy-paste. Todos table-based, todos inline-styled, todos compat Outlook.

3.1 Stripe signature

Doble franja azul + rojo (6px). En email NO usamos gradient (Outlook lo rompe): dos <td> al 50%.

<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">
  <tr>
    <td width="50%" height="6" style="background:#2e4aa3;height:6px;line-height:6px;font-size:0;">&nbsp;</td>
    <td width="50%" height="6" style="background:#d91d1d;height:6px;line-height:6px;font-size:0;">&nbsp;</td>
  </tr>
</table>

3.2 Header (logo wordmark)

<tr>
  <td style="background:#edebe7;padding:24px;">
    <a href="https://nostalgicapparel.com" style="text-decoration:none;">
      <img src="https://notify.nostalgicapparel.com/logo.png"
           alt="Nostalgic Apparel"
           width="160" height="24"
           style="display:block;height:24px;width:auto;border:0;outline:none;">
    </a>
  </td>
</tr>

3.3 Hero block · text-only

<tr>
  <td style="padding:36px 28px 0 28px;background:#ffffff;">
    <p style="font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
              font-size:11px;font-weight:500;letter-spacing:2px;
              text-transform:uppercase;color:#2e4aa3;margin:0 0 16px 0;">
      &#9656; EPISODE 01 &middot; 11:00 PM
    </p>
    <h1 style="font-family:'Geist','Inter','Helvetica Neue',Helvetica,Arial,sans-serif;
               font-size:36px;font-weight:600;line-height:1.05;
               letter-spacing:-1.1px;color:#030302;margin:0 0 16px 0;">
      You just joined<br>the late-night club.
    </h1>
    <p style="font-family:'Geist','Inter','Helvetica Neue',Helvetica,Arial,sans-serif;
              font-size:16px;line-height:1.55;color:#030302;margin:0 0 24px 0;">
      Welcome. Press start when you're ready — your first 10% lives in this email.
      No countdown, no rush. We're here all night.
    </p>
  </td>
</tr>

3.4 CTA Button (table-based · bulletproof Outlook)

El boton no es un <a> con padding — eso falla en Outlook. Es una tabla con un solo TD y el <a> dentro con display:inline-block + mso-padding-alt.

<table role="presentation" cellpadding="0" cellspacing="0" border="0">
  <tr>
    <td align="center" bgcolor="#030302"
        style="border-radius:2px;background:#030302;mso-padding-alt:14px 28px;">
      <a href="https://nostalgicapparel.com/collections/all"
         style="display:inline-block;
                font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
                font-size:13px;font-weight:500;letter-spacing:1.6px;
                text-transform:uppercase;text-decoration:none;
                color:#ffffff;padding:14px 28px;
                border:1px solid #030302;border-radius:2px;">
        &#9656; See the drop
      </a>
    </td>
  </tr>
</table>

Variante secundaria (radius 0, fondo blanco, borde negro):

<table role="presentation" cellpadding="0" cellspacing="0" border="0">
  <tr>
    <td align="center" bgcolor="#ffffff"
        style="background:#ffffff;border:1px solid #030302;mso-padding-alt:13px 27px;">
      <a href="..." style="display:inline-block;
              font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
              font-size:13px;font-weight:500;letter-spacing:1.6px;
              text-transform:uppercase;text-decoration:none;
              color:#030302;padding:13px 27px;">
        See all drops
      </a>
    </td>
  </tr>
</table>

3.5 Product block · single (horizontal)

<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0"
       style="margin:14px 0;border:1px solid #d3cec5;background:#ffffff;">
  <tr>
    <td width="100" valign="top" style="padding:14px;width:100px;">
      <a href="https://nostalgicapparel.com/products/no-cookies-just-trauma-tee">
        <img src="https://cdn.shopify.com/s/files/1/0608/1422/9668/files/nostalgic-nocookies-us007-nr-xx__standard__b_2026_600x.png?v=1775041745"
             alt="No cookies, just trauma Tee" width="80" height="80"
             style="display:block;width:80px;height:80px;border:0;background:#edebe7;">
      </a>
    </td>
    <td valign="middle" style="padding:14px 14px 14px 0;">
      <p style="font-family:'Geist','Inter','Helvetica Neue',Helvetica,Arial,sans-serif;
                font-size:14px;font-weight:600;color:#030302;margin:0 0 4px 0;
                letter-spacing:-.2px;line-height:1.3;">
        No cookies, just trauma &middot; Tee
      </p>
      <p style="font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
                font-size:12px;color:#6b6b6a;margin:0;">
        &euro;24,90
      </p>
    </td>
  </tr>
</table>

3.6 Product grid · 2x2 (cae a stack en mobile)

<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0"
       class="nos-mobile-stack" style="margin:18px 0;">
  <tr>
    <td valign="top" width="50%" style="padding:0 6px 12px 0;width:50%;">
      <!-- product card 1 -->
      <table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0"
             style="background:#ffffff;border:1px solid #d3cec5;">
        <tr><td>
          <a href="https://nostalgicapparel.com/products/no-cookies-just-trauma-tee">
            <img src="https://cdn.shopify.com/s/files/1/0608/1422/9668/files/nostalgic-nocookies-us007-nr-xx__standard__b_2026_600x.png?v=1775041745"
                 width="270" height="270" alt="No cookies, just trauma Tee"
                 style="display:block;width:100%;max-width:270px;height:auto;
                        border:0;background:#edebe7;">
          </a>
        </td></tr>
        <tr><td style="padding:12px 14px;">
          <p style="font-family:'Geist','Inter','Helvetica Neue',Helvetica,Arial,sans-serif;
                    font-size:13px;font-weight:600;color:#030302;margin:0 0 3px 0;
                    line-height:1.3;letter-spacing:-.1px;">No cookies, just trauma</p>
          <p style="font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
                    font-size:11px;color:#6b6b6a;margin:0;">&euro;24,90</p>
        </td></tr>
      </table>
    </td>
    <td valign="top" width="50%" style="padding:0 0 12px 6px;width:50%;">
      <!-- product card 2 (mismo patron) -->
    </td>
  </tr>
  <!-- segunda fila -->
</table>

3.7 Divider

<tr>
  <td style="padding:24px 28px;">
    <table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">
      <tr><td style="height:1px;line-height:1px;font-size:0;background:#d3cec5;">
        &nbsp;
      </td></tr>
    </table>
  </td>
</tr>

3.8 Text block con eyebrow

<tr>
  <td style="padding:28px 28px 16px 28px;">
    <p style="font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
              font-size:11px;font-weight:500;letter-spacing:2px;
              text-transform:uppercase;color:#2e4aa3;margin:0 0 12px 0;">
      &#9656; PATCH NOTES &middot; v1.0
    </p>
    <h2 style="font-family:'Geist','Inter','Helvetica Neue',Helvetica,Arial,sans-serif;
               font-size:28px;font-weight:600;line-height:1.1;letter-spacing:-.6px;
               color:#030302;margin:0 0 14px 0;">
      Care guide, but readable.
    </h2>
    <p style="font-family:'Geist','Inter','Helvetica Neue',Helvetica,Arial,sans-serif;
              font-size:16px;line-height:1.55;color:#030302;margin:0;">
      Wash cold inside out. Dry low. Iron inverted. Avoid bleach. That's it.
    </p>
  </td>
</tr>

3.9 Social row · footer

<tr>
  <td align="center" style="padding:18px 0;">
    <a href="https://instagram.com/nostalgicapparel"
       style="display:inline-block;margin:0 10px;
              font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
              font-size:11px;letter-spacing:1.6px;text-transform:uppercase;
              color:#b8b7b6;text-decoration:none;">instagram</a>
    <span style="color:#3a3a3a;">&middot;</span>
    <a href="https://nostalgicapparel.com"
       style="display:inline-block;margin:0 10px;
              font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
              font-size:11px;letter-spacing:1.6px;text-transform:uppercase;
              color:#b8b7b6;text-decoration:none;">shop</a>
    <span style="color:#3a3a3a;">&middot;</span>
    <a href="mailto:hello@nostalgicapparel.es"
       style="display:inline-block;margin:0 10px;
              font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
              font-size:11px;letter-spacing:1.6px;text-transform:uppercase;
              color:#b8b7b6;text-decoration:none;">contact</a>
  </td>
</tr>

3.10 Footer block

<!-- stripe top -->
<tr><td style="padding:0;font-size:0;line-height:0;">
  <table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">
    <tr>
      <td width="50%" style="background:#2e4aa3;height:6px;line-height:6px;font-size:0;">&nbsp;</td>
      <td width="50%" style="background:#d91d1d;height:6px;line-height:6px;font-size:0;">&nbsp;</td>
    </tr>
  </table>
</td></tr>
<!-- footer body -->
<tr><td align="center" style="background:#030302;padding:32px 24px;">
  <p style="font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
            font-size:11px;font-weight:500;letter-spacing:1.8px;
            text-transform:uppercase;color:#d91d1d;margin:0 0 8px 0;">
    &#9656; built for late nights & analog dreams
  </p>
  <p style="font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
            font-size:11px;color:#b8b7b6;margin:0 0 16px 0;line-height:1.6;">
    Stay classic &#10024; &mdash; The Nostalgic Team
  </p>
  <!-- social row aqui -->
  <p style="font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
            font-size:10px;color:#6b6b6a;letter-spacing:.8px;line-height:1.6;
            margin:18px 0 0 0;">
    Nostalgic Apparel &middot; nostalgicapparel.com<br>
    notify.nostalgicapparel.com &middot; hello@nostalgicapparel.es<br>
    <a href="{{unsubscribe_url}}" style="color:#6b6b6a;text-decoration:underline;">unsubscribe</a>
    &middot;
    <a href="{{preferences_url}}" style="color:#6b6b6a;text-decoration:underline;">update preferences</a>
  </p>
</td></tr>

3.11 Review block (request)

<tr><td align="left" style="padding:8px 0;">
  <table role="presentation" cellpadding="0" cellspacing="0" border="0">
    <tr>
      <td><a href="{{review_link}}?rating=1" style="font-family:'Geist Mono',monospace;font-size:22px;color:#2e4aa3;text-decoration:none;padding:0 4px;">&#9733;</a></td>
      <td><a href="{{review_link}}?rating=2" style="font-family:'Geist Mono',monospace;font-size:22px;color:#2e4aa3;text-decoration:none;padding:0 4px;">&#9733;</a></td>
      <td><a href="{{review_link}}?rating=3" style="font-family:'Geist Mono',monospace;font-size:22px;color:#2e4aa3;text-decoration:none;padding:0 4px;">&#9733;</a></td>
      <td><a href="{{review_link}}?rating=4" style="font-family:'Geist Mono',monospace;font-size:22px;color:#2e4aa3;text-decoration:none;padding:0 4px;">&#9733;</a></td>
      <td><a href="{{review_link}}?rating=5" style="font-family:'Geist Mono',monospace;font-size:22px;color:#2e4aa3;text-decoration:none;padding:0 4px;">&#9733;</a></td>
    </tr>
  </table>
</td></tr>

3.12 Discount block

<tr><td style="padding:8px 28px;">
  <table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0"
         style="background:#edebe7;border:1px dashed #2e4aa3;">
    <tr><td align="center" style="padding:20px 24px;">
      <p style="font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
                font-size:11px;font-weight:500;letter-spacing:1.8px;
                text-transform:uppercase;color:#1f3677;margin:0 0 6px 0;">
        &#9656; welcome to the late-night club
      </p>
      <p style="font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
                font-size:22px;font-weight:600;letter-spacing:3px;
                color:#030302;margin:0;">LATENIGHT10</p>
      <p style="font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
                font-size:11px;color:#4a4948;margin:10px 0 0 0;letter-spacing:.5px;">
        10% off your first. 7 days.
      </p>
    </td></tr>
  </table>
</td></tr>

3.13 Arcade callback box · uso visual puntual

Regla josé (v0.5): componente reservado a piezas que ya referencien recreativas (drop temático gaming, banner con joystick, packaging especial). Las frases "INSERT COIN", "GAME OVER?", "PRESS START" NO se usan como copy recurrente en winback, welcome, subjects ni captions. El componente existe; su léxico no es léxico común. Ejemplo abajo: drop con thematic arcade real.
<tr><td style="padding:8px 28px;">
  <table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0"
         style="background:#030302;">
    <tr><td align="center" style="padding:32px 24px;">
      <p style="font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
                font-size:18px;font-weight:500;letter-spacing:3.6px;
                text-transform:uppercase;color:#d91d1d;margin:0 0 10px 0;">
        &#9656; DROP 04 · JOYSTICK SERIES &#9666;
      </p>
      <p style="font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
                font-size:13px;color:#ffffff;margin:0;">
        Your cart's still warm. We saved the line.
      </p>
    </td></tr>
  </table>
</td></tr>

3.14 Countdown block (fecha real · sin contador JS)

Nostalgic NO usa countdowns falsos (regla §12 del brand brief). En emails de drop, mostramos la fecha y hora exacta del lanzamiento como elemento informativo, no como urgencia.

<tr><td style="padding:8px 28px;">
  <table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0"
         style="background:#030302;">
    <tr><td align="center" style="padding:18px 24px;">
      <p style="font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
                font-size:14px;font-weight:500;letter-spacing:2.4px;
                text-transform:uppercase;color:#d91d1d;margin:0;">
        &#9656; THU 22 MAY &middot; 23:00 CET
      </p>
    </td></tr>
  </table>
</td></tr>

Regla durable: la fecha que aparece aqui se rellena server-side desde la fecha real del drop. No hay JS countdown, no hay data-countdown. Si la fecha pasa, el email se vuelve archivo historico.

3.15 Pill (etiqueta no-CTA)

Para badges informativos dentro del cuerpo: "late-night club", "patch notes", "episode 02". NO es boton, NO clica.

late-night club   SALE
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="display:inline-block;">
  <tr><td style="border:1px solid #2e4aa3;border-radius:100px;padding:6px 12px;">
    <span style="font-family:'Geist Mono','SF Mono',Menlo,Consolas,monospace;
                  font-size:11px;font-weight:500;letter-spacing:1px;
                  text-transform:uppercase;color:#1f3677;">late-night club</span>
  </td></tr>
</table>

§04Templates completos por flow

Renders visuales de los emails que vamos a programar en crowdence-email-flows. Cada uno tiene asunto + preheader + cuerpo en HTML real. Las imagenes son productos vivos del top10 de Mayo 2026.

4.1 Welcome 1 · "▸ Welcome to the late-night club"

Subject: You just joined the late-night club

Preheader: Pilot episode starts now. Your 10% is inside.

4.2 Welcome 2 · "Episode 02 · the tour"

Subject: Episode 02 — the quick tour

Preheader: Five frases, three categorias, una marca pequena.

4.3 Cart 1 · "║ Paused." (arcade ASCII, 1h despues)

Subject: ║ Paused.

Preheader: Your cart's still warm. We saved the line.

4.4 Cart 3 · "Missed connection · classifieds dept." (48h despues, ultimo)

Subject: Missed connection · classifieds dept.

Preheader: Three nights parked. 48h, then quiet.

Pivot post-feedback josé v0.5: el concepto "INSERT COIN" se retira como copy recurrente. Cart 3 usa ahora el formato classifieds vintage (Missed Connections de periódico) — coherente con anti-marketing §6 del brief y con el formato Winback E1 ya existente.

4.5 Post-purchase 1 · "v1.0 patch notes for your new tee"

Subject: v1.0 patch notes for your new tee

Preheader: Como cuidarla. Como llevarla. Como dormirla.

4.6 Winback 1 · "Missed connections" (classifieds vintage, 60d sin abrir)

Subject: Missed connections — col. 4

Preheader: Te vimos por aqui en marzo. No estamos seguros de si fuiste tu.

4.7 Drop announcement · "▸ New drop · 11:00 pm sharp"

Subject: ▸ New drop · 11:00 pm tonight

Preheader: Five tees, one cropped, zero countdown.

Todos los templates anteriores estan en formato HTML real listo para inlinear en crowdence-email-flows/templates/nostalgic/. Para el codigo HTML completo de cada uno: ver carpeta /templates/ en el directorio del modulo email (pendiente F2).

§05Subject lines & preheaders

15 ejemplos por flow + preheader alineado. Tono late-night, sin signos de exclamacion, sin "DON'T MISS OUT", sin emoji. El preheader EXTIENDE el subject — no lo repite. Voltea, complementa, anticipa.

5.1 Welcome flow

subjectpreheader (45-90c)
You just joined the late-night clubPilot episode starts now. Your 10% is inside.
Episode 01 · 11:00 pmWherever you are, we're up too.
Welcome. Press start when ready.No countdown, no urgency. Just the tour.
The wordless tee you've been thinking ofIt exists. It's on a shelf. Here's the shelf.
A quick tour, then we let you scrollFive frases, three families, one small brand.
▸ Episode 02 · the tourThree families of frases. Pick the one that's loudest.
In case you didn't open the first oneNo pressure. Same 10%, same email. Same us.
Patch notes for the late-night clubHow this works, in three bullets.
Built for late nights & analog dreamsThe tagline isn't a slogan. It's a brief.
Episode 03 · the customers' favoritesTop 5 del mes. Algunos llevan ahi anos.
Issue 01 · what we ship and what we don'tManifesto in 4 tracks. Optional reading.
Pilot episode finale · LATENIGHT10 expiresLast reminder, then we leave you alone.
The frase that started this"Don't grow up, it's a trap" — napkin, diner, 3am.
Hello — this is the welcome emailYes, you signed up. No, we won't spam.
Tonight's top 3Three tees doing most of the talking this month.

5.2 Cart abandonment

subjectpreheader
║ Paused.Your cart's still warm. We saved the line.
Cart status · pausedResume whenever. No timer.
You left mid-gameThe save file is still there. Press continue.
Mid-checkout, somebody knockedWe get it. The cart is right here when you're back.
▸ Still in your cart · one itemSame size, same color. Same shipping window.
Que se te paso · sigue ahiTu carrito espera. Si era el envio, escribe.
Missed connection · classifieds dept.Three nights parked. 48h, then quiet.
Day 02 · 3:00 am · cart statusFinal reminder. We're not going to insist.
Was it the size or the moment?Reply if it was the size. We can help.
Resume cart · 10% on the lineRESUME10 · 24h · then it goes back to full price.
The tee you almost boughtIt's still here. We didn't put it back in the catalog yet.
Checkout, interruptedWe see this a lot. Most people come back later.
▸ Cart still parked · 48hTwo options. Both totally valid.
Three days since the cartFinal email of this thread. After this, silence.
Your cart's still emptyJust letting you know. The late-night club's still open.

5.3 Post-purchase

subjectpreheader
v1.0 patch notes for your new teeComo cuidarla. Como llevarla. Como dormirla.
Order received · tee shipping todayPedido #NA-32831. ETA jueves.
RTFM · your new tee, 3 rulesWash cold inside out. Dry low. Iron inverted.
Pedido en camino · SEUR pickup confirmedTracking abajo. Cualquier cosa, escribenos.
Out for delivery todayEstate cerca del timbre entre 10-14h.
Your order took a detourWe bumped it to priority. New ETA Thursday.
Day 10 · was it worth it?Did the tee survive the first wash? Be honest.
Okay: 10 days in.Five stars or two. Both useful. We patch fast.
Quick check-in · 14 days laterWear count? Wash count? Survivability rate?
Episode 04 · the customer's reviewThree minutes, five stars max. Or two. Or one.
▸ Patch notes · v1.0 follow-upCualquier defecto, te reemplazamos sin preguntar.
Tee survived the wash · here's part 2Las frases que combinan con la tuya.
Did it fit?Cambio gratis 30 dias. No es prueba — es promesa.
Order #NA-32831 · deliveredTee ya en tu casa. Lleva ya el plastico al verde.
A small ask · 30 secondsUna review, cualquier rating. La leemos.

5.4 Winback

subjectpreheader
Missed connections — col. 4We thought we saw you in March. We weren't sure.
Episode 05 · portedFive new frases since you've been gone.
Long time no scrollNo te perdimos. Solo querias mirar otra cosa.
▸ since you've been here lastLo que paso entre marzo y mayo. Mostly tees.
Old save file found · 60 daysTu cuenta sigue. Tu wishlist tambien.
A 5am confessionNo esperamos que vuelvas. Solo te avisamos.
15% off · porque siNo es scarcity, es agradecimiento. 30 dias.
If you ever come backEl catalogo cambio menos de lo que crees.
Episode 02 · the comebackRTFM not required. The club is the same.
Ported · what's differentTres frases nuevas. Mismo algodon GOTS.
Last call · before we let goFinal winback. After this, we move you to monthly only.
20% off · ultimo intento honestoSi no era el momento, no era el momento.
Want to stay, want to leave?Both buttons valid. We won't take it personal.
The frase that's selling this spring"No cookies, just trauma" — 274 unidades en 30 dias.
Three months, no spamPromise kept. One email now, then silence again.

5.5 Drop announcement

subjectpreheader
▸ New drop · 11:00 pm tonightFive tees, one cropped, zero countdown.
Episode 06 · drop tonightLights on at 23:00 CET. Doors open whenever.
Tonight · new collection liveNo scarcity. No timer. Just the drop.
11:00 pm sharp · new frasesLate night club gets new merch tonight.
Drop 03 · "Late Nights Through the Night"Five tees, each with an hour. 11pm / 1am / 3am / 5am.
Preview the drop · 24h earlySubscribers ven la coleccion antes que IG.
Tonight at 11 · press startThe frases. The cropped. The pricing. Same as always.
▸ Drop is live · check insideCinco frases nuevas. Una cropped. Aqui.
Issue 02 · drop release notesThe frases, the references, the patch notes.
Drop 03 sneak · two piecesTwo of the five. Rest at 11pm sharp.
No cookies, just trauma · cropped is backRestock confirmed. Sizes XS-XL.
▸ tonight's lineupFive frases, three families, one tagline.
Drop pre-order openDrop oficial: jueves 22 · Pre-order: ahora hasta entonces.
Drop 03 · the recapLo que ya esta vivo. Lo que se acabo. Lo que repetimos.
Tonight, then we sleepDrop sube a las 23:00. Despues, descanso justo.

5.6 Reglas duras subject + preheader

§06Mobile-first considerations

60-70% de los emails se abren en mobile. Apple Mail iOS (≈ 55% de share global) y Gmail Android dominan. Diseno desktop primero, pero verificado en mobile. Reglas duras.

6.1 Stack on mobile

Cualquier grid de 2+ columnas tiene que caer a una columna vertical en pantallas ≤600px. La tecnica:

<!-- En cada <td> del grid: width="50%" + clase mobile-stack -->
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0"
       class="nos-mobile-stack">
  <tr>
    <td valign="top" width="50%" style="padding:0 6px 12px 0;width:50%;">
      <!-- columna 1 -->
    </td>
    <td valign="top" width="50%" style="padding:0 0 12px 6px;width:50%;">
      <!-- columna 2 -->
    </td>
  </tr>
</table>

<style>
@media only screen and (max-width:600px){
  .nos-mobile-stack,
  .nos-mobile-stack > tbody > tr > td {
    display: block !important;
    width: 100% !important;
    max-width: 100% !important;
    padding-right: 0 !important;
    padding-left: 0 !important;
  }
}
</style>

6.2 Font sizing minimum

6.3 Touch target 44px

Apple HIG y Material Design coinciden: 44px minimo para cualquier elemento clicable. Los botones primary del DS (padding 14px + texto 13px → ≈42px) llegan justo. En mobile, subimos el padding vertical:

@media only screen and (max-width:600px){
  .nos-btn-primary,
  .nos-btn-secondary {
    padding: 16px 20px !important;  /* ≥44px alto */
    display: block !important;       /* full-width */
    width: auto !important;
  }
}

6.4 Imagen mobile

6.5 Tap target spacing

Si hay dos CTAs cerca, separar minimo 8px vertical. Si hay social row de 3-5 enlaces, padding mas generoso (12px entre).

6.6 Hide on mobile

Algunos elementos decorativos (anatomy diagrams, gridded data) NO se ven bien en mobile. Hide con clase:

<style>
@media only screen and (max-width:600px){
  .nos-mobile-hide { display: none !important; }
  .nos-desktop-hide { display: block !important; }
}
</style>

<td class="nos-mobile-hide"><!-- solo desktop --></td>
<td class="nos-desktop-hide" style="display:none;"><!-- solo mobile --></td>

§07Dark mode email

Apple Mail iOS / macOS, Outlook.com, Gmail (parcial) tienen modo oscuro automatico. Sin meta tags, el cliente "auto-darken" puede invertir tu bg cream a un gris feo. Hay que ser explicito.

7.1 Meta tags obligatorios

<meta name="color-scheme" content="light dark">
<meta name="supported-color-schemes" content="light dark">

Esto le dice al cliente: "tengo soporte explicito, no inviertas por tu cuenta". Apple Mail y Outlook.com lo respetan.

7.2 Strategy: tres niveles

nivelcuandonostalgic decision
1. opt-outDisable dark mode reformatNO — perdemos contraste accesibilidad
2. autoDejar que el cliente inviertaNO — bg cream se vuelve gris sucio
3. customDisenar variant dark explicitaSI · default Nostalgic

7.3 Mapping light → dark

lightdarkuso
#ffffff bg#0d0d0dfondo principal
#edebe7 cream#1a1a1aheader band, gutter
#030302 ink#f5f4f1texto principal (invertido)
#4a4948 ink-soft#b8b7b6texto secundario
#2e4aa3 accent#6b85d6azul Klein mas luminoso
#d91d1d alert#ff4444rojo mas luminoso
#d3cec5 warm-border#2a2a2adivisores

7.4 Image swap technique

El logo color (sobre cream) en dark mode no se ve. Tecnica: dos imagenes (light/dark) controladas con CSS media query — Apple Mail aplica prefers-color-scheme:

<!-- Logo (default light) -->
<img src="https://notify.nostalgicapparel.com/logo.png"
     alt="Nostalgic Apparel"
     class="nos-logo-light"
     style="height:24px;display:block;">

<!-- Logo (dark variant, oculto por default) -->
<img src="https://notify.nostalgicapparel.com/logo-white.png"
     alt="Nostalgic Apparel"
     class="nos-logo-dark"
     style="height:24px;display:none;">

<style>
@media (prefers-color-scheme: dark) {
  .nos-logo-light { display: none !important; }
  .nos-logo-dark { display: block !important; }
  .nos-dm-bg-cream { background-color: #1a1a1a !important; }
  .nos-dm-bg-white { background-color: #0d0d0d !important; }
  .nos-dm-text-dark { color: #f5f4f1 !important; }
  .nos-dm-btn-primary {
    background-color: #ffffff !important;
    color: #030302 !important;
    border-color: #ffffff !important;
  }
}
</style>

7.5 Outlook.com (light → dark forcado)

Outlook.com es mas agresivo: en dark mode invierte colores aunque tengas color-scheme declarado. Para forzar tu paleta:

<!-- En cada <td> criticado -->
<td bgcolor="#ffffff" style="background-color:#ffffff !important;
     color:#030302 !important;mso-line-height-rule:exactly;">
  ...
</td>

Outlook desktop (Word engine) NO tiene dark mode automatico. Renderiza siempre light. No hay que hacer nada extra.

7.6 Preview dark

Testear con Litmus o Email on Acid. En desarrollo local: en macOS, Apple Mail → System Settings → Appearance → Dark + click email Nostalgic. Verificar que el footer no se confunde con el body (deep #030302 vs bg dark #0d0d0d — la diferencia es minima pero existe).

§08Client compatibility

Lo que funciona y lo que no en cada cliente. Tabla pragmatica — el render gana al estandar. Si algo no esta soportado por uno de los grandes (Gmail, Outlook, Apple Mail, Yahoo), no lo usamos.

8.1 Capability matrix

feature Gmail Outlook desktop Outlook.com Apple Mail Yahoo
webfonts (Google Fonts) PARCIAL
web SI · app NO
NO
cae a Arial
PARCIAL
Edge SI · IE NO
SI NO
CSS custom properties (--var) parcial NO parcial SI NO
flexbox NO
app · partial web
NO parcial SI NO
CSS grid NO NO NO SI NO
media queries SI NO
solo desktop
SI SI SI
linear-gradient parcial
app no
NO parcial SI parcial
border-radius SI parcial
2010 SI · 2007 NO
SI SI SI
box-shadow SI NO SI SI SI
rgba colors SI parcial
alpha 0.5+ fall
SI SI SI
position absolute NO NO parcial SI NO
SVG inline parcial NO parcial SI NO
prefers-color-scheme parcial NO SI SI parcial
animation/transition NO NO NO SI NO

8.2 Nostalgic strategy

8.3 Quirks especificos

clientequirkworkaround
Outlook desktop Renderiza imagenes a su DPI (96 forzado). Stretching de imagen. Declarar width/height explicito + style="display:block". Usar OfficeDocumentSettings.
Outlook desktop Padding en <a> no funciona. Padding en <td> wrapper + mso-padding-alt en TD + display:inline-block en A.
Gmail web Strips <style> en HEAD si supera 8192 bytes. Minify CSS HEAD. Mantener <8KB. Inlinear todo lo critico.
Gmail mobile Inflates text <14px to 14px automatically. Declarar fuente minimo 14px o usar letter-spacing >1px (Gmail respeta el spacing y no infla).
Apple Mail iOS Auto-links phone numbers, addresses, dates → azul Apple feo. <meta name="format-detection" content="telephone=no, address=no, date=no"> + clase .appleLinks.
Yahoo Strips <link rel="stylesheet">. Solo CSS inline + <style> en HEAD. Sin link externo.
Outlook.com Reescribe <a> con su propio color en algunos casos. Forzar color inline en <a> + !important dentro de @media.

8.4 Testing

§09Export · drop-in en crowdence-email-flows

Tres formas de consumir este modulo email desde codigo de produccion. Resend, Postmark, generic transactional.

9.1 Resend (default Nostalgic)

Resend = Default Nostalgic. notify.nostalgicapparel.com esta verificado SPF/DKIM en Resend. Para enviar:

// Resend SDK (Node/Bun)
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);

await resend.emails.send({
  from: 'Nostalgic Apparel <notify@nostalgicapparel.com>',
  to: ['cliente@example.com'],
  subject: 'You just joined the late-night club',
  headers: {
    'List-Unsubscribe': '<https://nostalgicapparel.com/unsubscribe?u={{token}}>, <mailto:unsubscribe@nostalgicapparel.com>',
    'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click',
  },
  html: welcomeHtml({  // tu template func
    customerName: 'Marta',
    code: 'LATENIGHT10',
    expiresIn: '7 days',
  }),
  tags: [
    { name: 'flow', value: 'welcome' },
    { name: 'step', value: '01' },
  ],
});

9.2 Postmark (fallback transactional)

// Postmark SDK
import { ServerClient } from 'postmark';
const client = new ServerClient(process.env.POSTMARK_TOKEN);

await client.sendEmail({
  From: 'Nostalgic Apparel <notify@nostalgicapparel.com>',
  To: 'cliente@example.com',
  Subject: 'You just joined the late-night club',
  HtmlBody: welcomeHtml({ ... }),
  TextBody: welcomeText({ ... }),  // mandatory para Postmark
  MessageStream: 'broadcast', // o 'outbound' para transactional
  Headers: [{ Name: 'List-Unsubscribe', Value: '<https://...>' }],
});

9.3 Generic SMTP / Nodemailer

// Nodemailer + cualquier SMTP
import nodemailer from 'nodemailer';
const transporter = nodemailer.createTransport({
  host: 'smtp.resend.com',
  port: 465,
  secure: true,
  auth: { user: 'resend', pass: process.env.RESEND_API_KEY },
});

await transporter.sendMail({
  from: '"Nostalgic Apparel" <notify@nostalgicapparel.com>',
  to: 'cliente@example.com',
  subject: 'You just joined the late-night club',
  html: welcomeHtml({ ... }),
});

9.4 Inlining CSS

Antes de enviar, hay que inlinear los estilos. Recomendado:

// juice (default)
import juice from 'juice';
const inlined = juice(rawHtml, {
  preserveMediaQueries: true,
  preserveImportant: true,
  preserveFontFaces: true,
});

// alternativa: premailer (mas estricto)
import { premailer } from 'premailer';
const inlined = await premailer(rawHtml, { removeClasses: false });

9.5 Estructura recomendada en crowdence-email-flows

crowdence-email-flows/
├── shared/
│   ├── tokens.css                 ← copia de nostalgic-design-system/tokens.css
│   ├── email-fallback.css         ← copia de este modulo
│   └── components/
│       ├── header.tsx
│       ├── footer.tsx
│       ├── product-card.tsx
│       ├── cta-button.tsx
│       ├── stripe.tsx
│       ├── arcade.tsx
│       └── discount.tsx
├── templates/
│   └── nostalgic/
│       ├── welcome/
│       │   ├── 01-pilot-episode.tsx
│       │   ├── 02-the-tour.tsx
│       │   ├── 03-favorites.tsx
│       │   └── 04-pilot-finale.tsx
│       ├── cart/
│       │   ├── 01-paused.tsx
│       │   ├── 02-day-1.tsx
│       │   └── 03-insert-coin.tsx
│       ├── post-purchase/
│       │   ├── 01-patch-notes.tsx
│       │   ├── 02-tracking.tsx
│       │   └── 03-review-request.tsx
│       └── winback/
│           ├── 01-missed-connections.tsx
│           ├── 02-ported.tsx
│           └── 03-last-call.tsx
└── send/
    ├── resend.ts                  ← cliente Resend
    ├── postmark.ts                ← fallback
    └── triggers/
        ├── on-signup.ts
        ├── on-cart-abandon.ts
        ├── on-purchase.ts
        └── on-inactive.ts

9.6 React Email (recomendado para crowdence)

Si crowdence-email-flows usa React Email (Resend lo recomienda), los componentes del DS se traducen a JSX. Ejemplo CTA:

// components/cta-button.tsx
import { Button } from '@react-email/components';

export const NosCtaButton = ({ href, children, variant = 'primary' }) => (
  <Button
    href={href}
    style={{
      display: 'inline-block',
      fontFamily: "'Geist Mono','SF Mono',Menlo,monospace",
      fontSize: '13px',
      fontWeight: 500,
      letterSpacing: '1.6px',
      textTransform: 'uppercase',
      textDecoration: 'none',
      backgroundColor: variant === 'primary' ? '#030302' : '#ffffff',
      color: variant === 'primary' ? '#ffffff' : '#030302',
      padding: '14px 28px',
      borderRadius: variant === 'primary' ? '2px' : '0',
      border: '1px solid #030302',
    }}>
    {children}
  </Button>
);

9.7 Tracking pixel

Resend incluye open-tracking nativo (opcional, GDPR-respectful). Para click-tracking: usar UTM + el dashboard de Resend.

// link con UTM
<a href="https://nostalgicapparel.com/products/no-cookies-trauma-tee?utm_source=email&utm_medium=welcome&utm_campaign=pilot-episode">...</a>

// disable open tracking si lo decides (GDPR strict)
await resend.emails.send({
  ...,
  tracking: { opens: false, clicks: false },
});

9.8 Checklist pre-deploy

  1. Subject <50 caracteres · preheader 45-90 · pasa test mobile inbox
  2. CSS inlinado (juice) · media queries preservadas
  3. Imagenes con alt + width/height en pixels
  4. CTA bulletproof (table-based) · mso-padding-alt
  5. Dark mode preview verificado (Apple Mail)
  6. Link unsubscribe en footer (obligatorio · CAN-SPAM, RGPD)
  7. Header List-Unsubscribe + List-Unsubscribe-Post (Gmail bulk sender)
  8. Test envio a Litmus / Email on Acid
  9. Spam score >8/10 en mail-tester.com
  10. From verificado SPF/DKIM/DMARC en notify.nostalgicapparel.com