--- version: "1.0" name: "Amie" description: "Sistema visual de Amie: calendario y note-taker de IA construido sobre un casi-blanco (#FAFAFA) que nunca llega a ser blanco, y un azul cielo (#11A8FF) que es el único color de acción. Su firma no es el color: es la SOMBRA. Una rampa de siete capas con spread negativo que dobla en cada escalón (1→3→6→12→24), que produce una elevación tan suave que parece luz real y no CSS. Segunda firma: el marcador de rotulador, un con fondo de color al 30% y radio 4px que resalta media frase dentro de un titular de 56px. Escala de grises de 21 pasos, radios de 4/8/12, hairlines de negro al 4%, y una única Inter variable en dos pesos. Light mode, silencioso, de precisión." colors: primary: "#11A8FF" primary-hover: "#218FCD" primary-light: "#41BAFF" primary-soft: "#CFEEFF" primary-deep: "#2C76A0" secondary: "#FFD700" secondary-ink: "#D48F00" accent: "#FD2B38" amie-pink: "#F6A6A6" canvas: "#FAFAFA" surface: "#FFFFFF" surface-alt: "#F2F2F2" surface-sunk: "#EBEBEB" ink: "#171717" ink-strong: "#000000" foreground: "#262626" text-secondary: "#5C5C5C" text-tertiary: "#A0A0A0" text-quiet: "#737373" gray-950: "#0F0F0F" gray-900: "#171717" gray-850: "#222222" gray-800: "#2E2E2E" gray-700: "#454545" gray-600: "#5C5C5C" gray-500: "#737373" gray-400: "#919191" gray-350: "#A0A0A0" gray-300: "#AFAFAF" gray-200: "#CDCDCD" gray-150: "#DCDCDC" gray-100: "#EBEBEB" gray-75: "#F2F2F2" gray-50: "#FAFAFA" green-500: "#01CA45" green-100: "#CCF4DA" orange-500: "#FE6600" purple-500: "#A050FF" pink-500: "#FF329A" rose-500: "#FF2B5F" yellow-500: "#F4AF00" red-500: "#FD2B38" hair: "#0000000A" hair-strong: "#0000001A" ring: "#0000000D" background: "#FAFAFA" text-primary: "#171717" text-on-primary: "#FFFFFF" border: "#0000000A" success: "#01CA45" success-bg: "#CCF4DA" info: "#11A8FF" info-bg: "#CFEEFF" error: "#FD2B38" error-bg: "#FFD5D7" warning: "#F4AF00" warning-bg: "#FDEFCC" typography: display: fontFamily: "Inter" fontSize: "56px" fontWeight: 700 lineHeight: "1.143" letterSpacing: "-0.0125em" headline: fontFamily: "Inter" fontSize: "40px" fontWeight: 700 lineHeight: "1.36" letterSpacing: "-0.0125em" title: fontFamily: "Inter" fontSize: "20px" fontWeight: 600 lineHeight: "1.40" letterSpacing: "-0.025em" lead: fontFamily: "Inter" fontSize: "18px" fontWeight: 500 lineHeight: "1.56" letterSpacing: "-0.0002em" body: fontFamily: "Inter" fontSize: "16px" fontWeight: 400 lineHeight: "1.75" letterSpacing: "-0.0002em" ui: fontFamily: "Inter" fontSize: "14px" fontWeight: 500 lineHeight: "1.43" letterSpacing: "-0.0002em" body-sm: fontFamily: "Inter" fontSize: "14px" fontWeight: 400 lineHeight: "1.50" letterSpacing: "-0.0002em" caption: fontFamily: "Inter" fontSize: "12px" fontWeight: 500 lineHeight: "1.32" letterSpacing: "-0.0002em" quirk: fontFamily: "Averia Serif Libre" fontSize: "20px" fontWeight: 400 lineHeight: "1.40" letterSpacing: "normal" rounded: xs: "4px" sm: "6px" md: "8px" lg: "12px" xl: "16px" panel: "32px" full: "9999px" spacing: micro: "2px" xxs: "4px" xs: "6px" sm: "8px" md: "12px" base: "16px" lg: "20px" xl: "24px" 2xl: "28px" 3xl: "32px" 4xl: "40px" 5xl: "48px" components: button-primary: backgroundColor: "{colors.primary}" textColor: "{colors.text-on-primary}" typography: "{typography.lead}" fontWeight: 600 rounded: "{rounded.lg}" padding: "12px 28px" height: "49.6px" boxShadow: "none" hover: "background-color: {colors.primary-hover}" transition: "background-color 150ms cubic-bezier(0.4, 0, 0.2, 1)" button-secondary: backgroundColor: "{colors.surface}" textColor: "{colors.text-secondary}" typography: "{typography.lead}" fontWeight: 600 rounded: "{rounded.lg}" padding: "12px 28px" height: "49.6px" gap: "8px" boxShadow: "0 0 0 1px rgba(0,0,0,0.06), 0 1px 1px -0.5px rgba(0,0,0,0.06), 0 3px 3px -1.5px rgba(0,0,0,0.06)" hover: "background-color: {colors.canvas}" button-nav: backgroundColor: "{colors.primary}" textColor: "{colors.text-on-primary}" typography: "{typography.ui}" rounded: "{rounded.md}" padding: "6px 16px" height: "32px" hover: "background-color: {colors.primary-hover}" button-nav-ghost: backgroundColor: "transparent" textColor: "{colors.ink-strong}" typography: "{typography.ui}" rounded: "{rounded.md}" padding: "6px 10px" height: "32px" hover: "background-color: rgba(0,0,0,0.05)" card: backgroundColor: "{colors.surface}" rounded: "{rounded.lg}" padding: "20px" gap: "8px" boxShadow: "0 0 0 1px rgba(0,0,0,0.06), 0 1px 1px -0.5px rgba(0,0,0,0.06), 0 3px 3px -1.5px rgba(0,0,0,0.06)" card-hero: backgroundColor: "{colors.surface}" rounded: "{rounded.lg}" padding: "0px" boxShadow: "0 0 0 1px rgba(0,0,0,0.06), 0 1px 1px -0.5px rgba(0,0,0,0.06), 0 3px 3px -1.5px rgba(0,0,0,0.06), 0 6px 6px -3px rgba(0,0,0,0.06), 0 12px 12px -6px rgba(0,0,0,0.04), 0 24px 24px -12px rgba(0,0,0,0.04), 0 24px 24px 2px rgba(0,0,0,0.1)" marker: backgroundColor: "rgba(255, 215, 0, 0.30)" textColor: "{colors.secondary-ink}" rounded: "{rounded.xs}" padding: "0 4px" marker-blue: backgroundColor: "{colors.primary-soft}" textColor: "{colors.primary-deep}" rounded: "{rounded.xs}" padding: "0 4px" pill: backgroundColor: "{colors.text-quiet}" textColor: "{colors.text-on-primary}" typography: "{typography.ui}" rounded: "{rounded.full}" padding: "12px 24px" height: "44px" ring: boxShadow: "inset 0 0 0 1px rgba(0,0,0,0.05)" --- # DESIGN.md - Amie > Sistema de diseño extraído de `https://amie.so` (home, julio 2026) siguiendo el skill `url-inspiration-styleguide`. > Colores, familias, tamaños, radios y sombras medidos sobre el sitio en vivo con Puppeteer a 1600×900. Amie es el caso opuesto a un sitio de Framer: expone su sistema entero en el `:root` con nombres humanos (`--color-gray-600: 92,92,92`, `--color-blue-500: 17,168,255`), en formato de triplete RGB para poder componer opacidades con Tailwind. Hay **21 pasos de gris** y **13 rampas de color** declaradas. Lo que el sitio no expone (estados con superficie, breakpoints como tokens) va marcado como *(derivado para completar el sistema)*. --- ## 1. Tema Visual y Atmósfera Amie es un calendario que graba tus reuniones y las convierte en notas. Podría haberse vestido de dashboard. En cambio se viste de **papel**. El lienzo es `#FAFAFA`, y ese detalle importa: **no es blanco**. Es `gray-50`, el primer escalón de una rampa de 21 grises, y sobre él las tarjetas sí son `#FFFFFF`. Esa diferencia de cinco puntos de luminancia es toda la profundidad que el sistema necesita para separar "el fondo" de "las cosas". Nada más. Bueno, casi nada más. Porque la firma real de Amie no es un color: **es la sombra**. ```css box-shadow: 0 0 0 1px rgba(0,0,0,0.06), 0 1px 1px -0.5px rgba(0,0,0,0.06), 0 3px 3px -1.5px rgba(0,0,0,0.06), 0 6px 6px -3px rgba(0,0,0,0.06), 0 12px 12px -6px rgba(0,0,0,0.04), 0 24px 24px -12px rgba(0,0,0,0.04), 0 24px 24px 2px rgba(0,0,0,0.10); ``` Siete capas. El desenfoque dobla en cada escalón (1 → 3 → 6 → 12 → 24) y el **spread negativo dobla con él** (−0.5 → −1.5 → −3 → −6 → −12). Eso hace que cada capa "recorte" a la anterior por los lados, y lo que queda es una caída de opacidad casi continua en lugar de un borrón gris. El resultado es una elevación que se lee como **luz real**, no como un `box-shadow`. La versión de tres capas (las tres primeras) es la que llevan todas las tarjetas y el botón secundario; la de siete, solo el marco del producto. La segunda firma es un truco de papelería: **el marcador de rotulador**. Media frase dentro de un titular de 56px va envuelta en un `` con fondo de color al 30%, radio 4px y `padding: 0 4px`. "AI Note Taker without a bot". Hay tres variantes reales en la home: **oro** (`rgba(255,215,0,0.30)` con tinta `#D48F00`), **azul** (`#CFEEFF` con tinta `#2C76A0`) y **gris** (`#EBEBEB` con tinta `#737373`). No es una decoración: es el mecanismo con el que Amie te dice dónde mirar en una página que por lo demás es toda gris. El azul `#11A8FF` es el **único color de acción**. Ningún otro elemento clicable del sistema tiene color. Los botones de nav son texto negro sobre nada; el secundario es blanco con sombra; solo el primario se pinta de azul. Y la paleta completa (verde `#01CA45`, naranja `#FE6600`, morado `#A050FF`, rosa `#FF329A`, rojo `#FD2B38`…) existe declarada en el `:root` pero vive **dentro del producto**, en las etiquetas del calendario, nunca en la landing. Tipografía: **Inter variable**, y ya. Dos pesos de trabajo (400 y 600), uno de titular (700). Con una particularidad que casi nadie usa: el `line-height` del body es **28px sobre 16px = 1.75**. Eso es muchísimo aire para un párrafo. Amie escribe párrafos largos y quiere que se lean como un artículo, no como copy de landing. **Palabras clave de personalidad**: silencioso, preciso, de papel, tipográfico, sin ruido, íntimo **Densidad del layout**: aireada en el texto (line-height 1.75), compacta en la UI (gap base 8px, botones de nav de 32px) **Modo preferido**: claro. El `:root` declara la rampa de gris invertible (950 → 50) y todos los colores traen sus variantes 900-100, así que el modo oscuro está *preparado* pero no está *activo* en la home. **Nivel de ornamentación**: bajísimo. Cero gradientes de fondo, cero blobs, cero ilustraciones. Los únicos "efectos" son la sombra y el marcador. **Audiencia visual objetivo**: gente que vive en su calendario y quiere que la herramienta desaparezca --- ## 2. Paleta de Colores y Roles Semánticos ### La estructura del `:root` Amie declara sus colores como **tripletes RGB sin envolver**, para poder hacer `rgb(var(--color-blue-500), 0.5)` en Tailwind: ```css :root { --color-blue-500: 17, 168, 255; --color-gray-600: 92, 92, 92; --color-primary: var(--color-gray-900); --color-secondary: var(--color-gray-600); --color-tertiary: var(--color-gray-350); --color-accent: var(--color-red-500); --color-background: var(--color-gray-50); --color-separator: var(--color-black); } ``` Fíjate en la capa de indirección: hay una rampa cruda (`gray-600`) y hay un **rol semántico** (`secondary`) que apunta a ella. Los componentes usan el rol, nunca la rampa. Esa es la razón por la que el sistema es invertible sin tocar un solo componente. ### Colores de marca | Token | Hex | Rol real medido | |---|---|---| | `primary` (blue-500) | `#11A8FF` | **el único color de acción**. Botón primario, links activos | | `primary-hover` (blue-600) | `#218FCD` | hover real del botón, medido en vivo | | `primary-light` (blue-400) | `#41BAFF` | parada alta del gradiente de la sección azul | | `primary-soft` (blue-100) | `#CFEEFF` | fondo del marcador azul, superficie de info | | `primary-deep` (blue-700) | `#2C76A0` | tinta sobre el marcador azul | | `secondary` | `#FFD700` | el oro del marcador. Solo existe al 30% | | `secondary-ink` | `#D48F00` | tinta sobre el marcador de oro (declarada en display-p3) | | `accent` (red-500) | `#FD2B38` | declarado como `--color-accent`: el botón de grabar | | `amie-pink` | `#F6A6A6` | único color con nombre propio de marca en el `:root` | ### La rampa de gris (21 pasos, el esqueleto del sistema) | Token | Hex | | Token | Hex | |---|---|---|---|---| | `gray-950` | `#0F0F0F` | | `gray-450` | `#828282` | | `gray-900` | `#171717` | | `gray-400` | `#919191` | | `gray-885` | `#191919` | | `gray-350` | `#A0A0A0` | | `gray-870` | `#1B1B1B` | | `gray-300` | `#AFAFAF` | | `gray-850` | `#222222` | | `gray-250` | `#BEBEBE` | | `gray-800` | `#2E2E2E` | | `gray-200` | `#CDCDCD` | | `gray-750` | `#3A3A3A` | | `gray-150` | `#DCDCDC` | | `gray-740` | `#313131` | | `gray-100` | `#EBEBEB` | | `gray-700` | `#454545` | | `gray-75` | `#F2F2F2` | | `gray-650` | `#515151` | | `gray-50` | `#FAFAFA` | | `gray-600` | `#5C5C5C` | | | | | `gray-550` | `#686868` | | | | | `gray-500` | `#737373` | | | | Veintiún pasos es mucho, y hay medios pasos raros (`885`, `870`, `740`) que solo tienen sentido en el modo oscuro del producto, donde separar `#171717` de `#191919` sí importa. En la landing se usan **seis**: 950, 900, 600, 350, 100 y 50. ### Colores de texto | Rol | Token | Hex | Contraste sobre `#FAFAFA` | |---|---|---|---| | titulares | `text-black` | `#000000` | 20.12:1 · AAA | | ink (rol `primary`) | `gray-900` | `#171717` | 17.18:1 · AAA | | foreground | — | `#262626` | 13.9:1 · AAA | | párrafos (rol `secondary`) | `gray-600` | `#5C5C5C` | 6.41:1 · AA | | quiet | `gray-500` | `#737373` | 4.54:1 · AA (justo) | | iconos (rol `tertiary`) | `gray-350` | `#A0A0A0` | **2.51:1 · nunca texto** | `gray-350` es el color de los iconos dentro del botón secundario y de los metadatos. Con 2.51:1 **no se puede usar para texto**, y el sitio lo respeta: solo lo pone en glifos decorativos. Detalle notable: los titulares no usan el token `primary` (`#171717`), usan **negro puro**. La escala de texto de Amie tiene un escalón extra por encima de su propio rol semántico. ### Colores de superficie | Token | Hex | Uso | |---|---|---| | `canvas` | `#FAFAFA` | fondo del sitio. Área 2.2M | | `surface` | `#FFFFFF` | tarjetas y botón secundario. Área 999K | | `surface-alt` | `#F2F2F2` | superficie hundida suave | | `surface-sunk` | `#EBEBEB` | fondo del marcador gris, chips inactivos | | velo | `rgba(0,0,0,0.20)` | el velo sobre la captura del producto. Área 190K | | velo suave | `rgba(250,250,250,0.80)` | la barra de nav pegajosa (con blur) | El sistema entero se construye con **dos superficies**: `#FAFAFA` y `#FFFFFF`. La diferencia entre ellas es de apenas 2% de luminancia, y eso obliga a que la sombra haga todo el trabajo de separación. Es exactamente la decisión inversa a la de un sistema oscuro. ### El marcador (componente firma, tres variantes reales) | Variante | Fondo | Tinta | Contraste tinta/fondo | |---|---|---|---| | oro | `rgba(255, 215, 0, 0.30)` | `#D48F00` | 2.5:1 — **solo a ≥40px** | | azul | `#CFEEFF` | `#2C76A0` | 4.12:1 — AA texto grande | | gris | `#EBEBEB` | `#737373` | 3.6:1 — AA texto grande | Los tres viven a 40-56px con peso 700, así que pasan AA como texto grande. **A tamaño de cuerpo ninguno de los tres pasa.** Si necesitas el marcador en 16px, sube la tinta: `#A06B00` sobre el oro da 4.6:1. ### Contraste verificado | Combinación | Ratio | Veredicto | |---|---|---| | `#000000` sobre `#FAFAFA` | 20.12:1 | AAA | | `#5C5C5C` sobre `#FAFAFA` | 6.41:1 | AA | | `#5C5C5C` sobre `#FFFFFF` | 6.69:1 | AA | | `#A0A0A0` sobre `#FAFAFA` | 2.51:1 | solo glifos | | `#FFFFFF` sobre `#11A8FF` | **2.60:1** | **falla AA, incluso en texto grande** | | `#FFFFFF` sobre `#218FCD` (hover) | 3.57:1 | AA solo texto grande | | `#2C76A0` sobre `#CFEEFF` | 4.12:1 | AA texto grande | Este es el agujero real del sistema y hay que decirlo claro: **el botón primario de Amie no es accesible.** Blanco sobre `#11A8FF` da 2.60:1, muy por debajo del 4.5:1 de AA. El texto es de 16px/600, así que ni siquiera se salva por la excepción de texto grande. Curiosamente el **hover** (`#218FCD`) está mejor: 3.57:1. Si reconstruyes este sistema y te importa la accesibilidad, la corrección mínima es usar `blue-600` (`#218FCD`) como color de reposo y `blue-700` (`#2C76A0`, 4.78:1 con blanco) como hover. El azul se ve casi igual y el sistema pasa AA. ### Colores de estado *(derivados; la home no tiene banners ni toasts)* Amie declara rampas completas de 13 colores. El mapeo semántico natural: | Rol | 500 | 100 (superficie) | |---|---|---| | success | `#01CA45` | `#CCF4DA` | | info | `#11A8FF` | `#CFEEFF` | | error | `#FD2B38` | `#FFD5D7` | | warning | `#F4AF00` | `#FDEFCC` | ### Hairlines | Token | Valor | Uso | |---|---|---| | `hair` | `rgba(0,0,0,0.04)` | separadores de sección y de footer (6 nodos) | | `ring` | `rgba(0,0,0,0.05)` | anillo interior de superficies (`inset 0 0 0 1px`) | | `hair-strong` | `rgba(0,0,0,0.10)` | borde de la ventana de email, anillo del marco | Los bordes de Amie **son negro con alpha**, nunca un gris sólido. Un `#EBEBEB` sólido se ve gris sucio sobre `#FFFFFF` y gris sucio sobre `#FAFAFA`; un `rgba(0,0,0,0.04)` se adapta a las dos. --- ## 3. Reglas de Tipografía ### Familias reales | Rol | Familia real | Origen | |---|---|---| | Todo | **Inter** (variable, `Inter var`) | Google Fonts | | Quirk | **Averia Serif Libre** | Google Fonts | ### Nota sobre sustitución tipográfica **No hace falta sustituir nada.** Las dos familias que Amie carga están en Google Fonts: - **Inter** — la fuente de toda la interfaz y todo el texto. Amie carga la versión variable (`Inter var`) vía la optimización de fuentes de Next.js, con su fallback métrico generado (`Inter Fallback`). En Google Fonts se pide con `family=Inter:wght@400..700`. - **Averia Serif Libre** — una serif de trazo tembloroso, dibujada como el "promedio" de muchas tipografías escaneadas a mano. Está **cargada** en la home pero **no se usa en ningún nodo visible**: probablemente vive en el blog o en la página de historia. Se documenta porque forma parte del sistema declarado, y se reserva para el mismo rol que tendría ahí: una nota manuscrita, un aparte, algo que no es interfaz. Esa es toda la tipografía. Sin fuente propietaria, sin self-hosting, sin display de marca. Amie confía en que Inter, bien espaciada, es suficiente. Y en la home, con `line-height: 1.75` en el cuerpo, lo es. ### Escala tipográfica | Rol | Size real | Weight | Line-height | Letter-spacing | |---|---|---|---|---| | display (h1) | 56px | 700 | 64px (1.143) | -0.7px (-0.0125em) | | headline (h4) | 40px | 700 | 54.4px (1.36) | -0.5px (-0.0125em) | | title (h3/h4) | 20px | 600 | 28px (1.40) | -0.5px (-0.025em) | | lead | 18px | 500 | 28px (1.56) | -0.003px | | body | 16px | 400 | **28px (1.75)** | -0.003px | | ui | 14px | 500 | 20px (1.43) | -0.003px | | body sm | 14px | 400 | 21px (1.50) | -0.003px | | caption | 12px | 500 | 15.84px (1.32) | -0.003px | Dos cosas que definen la voz: **El `line-height: 28px` del body sobre 16px = 1.75.** Es un valor de tipografía editorial, no de producto. La consecuencia es que un párrafo de Amie ocupa un 20% más de alto que el mismo párrafo en un SaaS normal, y se lee como un artículo. **El `28px` se repite.** Body (16px), lead (18px) y title (20px) tienen **todos** `line-height: 28px`. Eso significa que puedes mezclar los tres en una misma columna y las líneas base siguen alineando. Es una rejilla baseline de 28px escondida a plena vista. ### Letter spacing ``` display / headline (≥40px): -0.0125em (tracking-[-0.0125em] en el código real) title (20px): -0.025em todo lo demás: -0.003px (prácticamente cero) ``` Solo los titulares se comprimen. El texto va a tracking natural de Inter. Es lo opuesto a un sistema que aprieta todo. ### Pesos tipográficos - **700** — solo h1 y h4 grandes (56px y 40px) - **600** — títulos de 20px y **todos los botones** - **500** — UI de 14px, lead de 18px, captions - **400** — párrafos Cuatro pesos, cada uno con un trabajo claro. El 500 es el peso de la interfaz; el 400, el del contenido. --- ## 4. Estilos de Componentes ### La sombra, primero Antes que ningún componente, hay que entender las tres recetas de sombra, porque el 90% de los componentes de Amie **solo** se distinguen por cuál llevan. ```css /* shadow-natural — 3 capas. La que llevan TODAS las tarjetas y el botón secundario. Es la sombra por defecto del sistema. */ --shadow-natural: 0 0 0 1px rgba(0, 0, 0, 0.06), 0 1px 1px -0.5px rgba(0, 0, 0, 0.06), 0 3px 3px -1.5px rgba(0, 0, 0, 0.06); /* shadow-natural-lg — 7 capas. Solo el marco del producto. Blur: 1, 3, 6, 12, 24 (dobla). Spread: -0.5, -1.5, -3, -6, -12 (dobla). */ --shadow-natural-lg: 0 0 0 1px rgba(0, 0, 0, 0.06), 0 1px 1px -0.5px rgba(0, 0, 0, 0.06), 0 3px 3px -1.5px rgba(0, 0, 0, 0.06), 0 6px 6px -3px rgba(0, 0, 0, 0.06), 0 12px 12px -6px rgba(0, 0, 0, 0.04), 0 24px 24px -12px rgba(0, 0, 0, 0.04), 0 24px 24px 2px rgba(0, 0, 0, 0.10); /* ring — anillo interior. La alternativa cuando el objeto no debe elevarse. */ --shadow-ring: inset 0 0 0 1px rgba(0, 0, 0, 0.05); ``` Por qué funciona la rampa: la **primera capa es un borde** (`0 0 0 1px`, sin blur), no una sombra. Después, cada capa desenfoca el doble y se encoge el doble. Como cada una está más recortada que la anterior, la que asoma por los bordes es siempre la más grande y la más tenue. La caída de opacidad resultante es suave y continua, y el ojo la lee como penumbra, no como un rectángulo gris difuminado. Es un truco caro de hacer a mano y trivial de copiar; cópialo. ### Botones #### Primario ```css .btn-primary { background-color: #11A8FF; color: #FFFFFF; font-family: Inter, sans-serif; font-size: 16px; font-weight: 600; line-height: 25.6px; letter-spacing: -0.0125em; padding: 12px 28px; /* px-7 py-3 */ height: 49.6px; /* medido */ border: 0; border-radius: 12px; /* rounded-xl */ box-shadow: none; /* SIN sombra: es el único componente elevado que no la lleva */ transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1), color 150ms cubic-bezier(0.4, 0, 0.2, 1); cursor: pointer; } .btn-primary:hover { background-color: #218FCD; } /* blue-600, medido en vivo */ ``` Lo interesante: **el botón primario no tiene sombra**. En un sistema donde todo lo elevado lleva `shadow-natural`, el CTA es plano. El color hace todo el trabajo, y como es el único color de la página, no necesita más. El hover no mueve, no escala, no crece: solo oscurece el fondo un escalón de la rampa. #### Secundario ```css .btn-secondary { background-color: #FFFFFF; color: #5C5C5C; /* gray-600, NO negro */ font-size: 16px; font-weight: 600; padding: 12px 28px; height: 49.6px; gap: 8px; /* para el icono */ border: 0; border-radius: 12px; box-shadow: var(--shadow-natural); /* aquí SÍ */ transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1); } .btn-secondary:hover { background-color: #FAFAFA; } .btn-secondary svg { color: #A0A0A0; width: 24px; height: 24px; } /* tertiary */ ``` Los dos botones tienen **exactamente el mismo padding, el mismo radio, la misma altura y el mismo peso**. La única diferencia es: uno tiene color y no tiene sombra; el otro tiene sombra y no tiene color. Es una simetría perfecta y es la razón por la que la pareja se ve tan bien junta. El icono va en `gray-350` (`#A0A0A0`), un escalón más claro que el texto. Nunca en el color del texto: el icono acompaña, no compite. #### Nav ```css .btn-nav-primary { background-color: #11A8FF; color: #FFFFFF; font-size: 14px; font-weight: 500; padding: 6px 16px; /* px-4 py-1.5 */ height: 32px; border-radius: 8px; /* rounded-lg — más pequeño que el hero */ transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1); } .btn-nav-primary:hover { background-color: #218FCD; } .btn-nav-ghost { background: transparent; color: #000000; font-size: 14px; font-weight: 500; padding: 6px 10px; /* px-2.5 py-1.5 */ height: 32px; border-radius: 8px; transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1); } .btn-nav-ghost:hover { background-color: rgba(0, 0, 0, 0.05); } /* hover:bg-black/5 */ ``` El radio baja de 12px a 8px cuando el control baja de 49.6px a 32px de alto. La proporción radio/altura se mantiene en torno a 1:4. Esa es la regla implícita: **el radio escala con el control**. ### El marcador (componente firma) ```css .mark { background-color: rgba(255, 215, 0, 0.30); color: #D48F00; border-radius: 4px; padding: 0 4px; /* hereda tamaño y peso del titular que lo contiene */ } .mark-blue { background-color: #CFEEFF; color: #2C76A0; } .mark-gray { background-color: #EBEBEB; color: #737373; } ``` Cuatro píxeles de radio y cuatro de padding lateral. Nada más. El fondo del oro va **al 30% de opacidad** para que el color del papel se siga viendo a través: es un rotulador, no un rectángulo de color. Los otros dos van a opacidad plena porque ya son colores claros (`blue-100`, `gray-100`). Uso real: **una vez por titular, sobre las 2-4 palabras que llevan el argumento**. "AI Note Taker `without a bot`". "Within `47 seconds`:". "in just `7 days`". ### Cards ```css .card { background-color: #FFFFFF; border: 0; border-radius: 12px; padding: 20px; gap: 8px; box-shadow: var(--shadow-natural); } ``` Radio 12px (28 nodos, el más repetido), padding 20px (13 nodos), gap 8px (53 nodos: el gap más usado del sitio con diferencia). Sin borde: el borde es la primera capa de la sombra (`0 0 0 1px rgba(0,0,0,0.06)`). **Jerarquía interna** (gap 8px): 1. Icono o etiqueta 2. Título 20px/600, `line-height: 28px`, `#000000` 3. Párrafo 16px/400, `line-height: 28px`, `#5C5C5C` Como título y párrafo comparten `line-height: 28px`, dos tarjetas de distinto contenido siguen alineando sus líneas base. Ese es el efecto de la rejilla de 28px. **Hover**: las tarjetas de contenido de Amie **no tienen hover**. Son estáticas. Las que sí son clicables usan `hover:border-gray-200` o `hover:bg-gray-50` (visto en el CSS de Tailwind del sitio). Nunca elevan la sombra. ### Marco de producto ```css .frame { background-color: #FFFFFF; border-radius: 12px; box-shadow: var(--shadow-natural-lg); /* las 7 capas */ } /* el anillo va en un pseudo-elemento superpuesto, no en el mismo nodo */ .frame::after { content: ""; position: absolute; inset: 0; border-radius: 12px; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.10); pointer-events: none; } ``` Medida real: 976×630px. Amie separa la sombra (en el contenedor) del anillo (en un `::after` con `ring-1 ring-inset ring-black/10`). Eso permite que el anillo quede **por encima** del contenido con `overflow: hidden`, así que el borde del marco no se pierde bajo la captura. ### Pills ```css .pill { background-color: #737373; /* gray-500 activo */ color: #FFFFFF; font-size: 14px; font-weight: 500; padding: 12px 24px; height: 44px; border-radius: 9999px; } .pill-inactive { background-color: #CDCDCD; } /* gray-200 */ ``` Curioso: las pills de "Today / Day 3 / Day 7" no usan azul. El estado activo es **gris oscuro**, el inactivo es **gris claro**. Amie reserva el azul con tanta disciplina que ni siquiera lo gasta en un selector de pestañas. ### Inputs *(derivados; la home no tiene formularios)* ```css .input { background-color: #FFFFFF; border: 0; border-radius: 8px; padding: 10px 12px; font-size: 14px; color: #000000; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.10); transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1); } .input::placeholder { color: #A0A0A0; } .input:focus-visible { outline: none; box-shadow: inset 0 0 0 1px #11A8FF, 0 0 0 3px rgba(17, 168, 255, 0.20); } ``` Coherente con el sistema: el borde es un **anillo interior**, no un `border`. Así el input no cambia de tamaño al enfocarse. ### Navegación Barra pegajosa con `background: rgba(250,250,250,0.80)` y `backdrop-filter: blur(12px)`. Links en 14px/500 negro, con `hover:bg-black/5` y radio 8px. A la derecha, "Login" en `gray-600` y "Get started" como el botón primario compacto. --- ## 5. Principios de Layout ### Escala de espaciado Base 4, con un uso muy concentrado. Los números son nodos medidos. | Token | Valor | Nodos (gap) | Uso | |---|---|---|---| | micro | 2px | 5 | separación de glifos | | xxs | 4px | 25 | metadata, listas densas | | xs | 6px | 10 | interior de chips | | **sm** | **8px** | **53** | **el gap por defecto de todo** | | md | 12px | 13 | gap de fila | | base | 16px | 7 | gap de bloque | | lg | 20px | — | **padding de tarjeta** (13 nodos de padding) | | xl | 24px | 3 | — | | 2xl | 28px | 3 | el módulo de la rejilla baseline | | **3xl** | **32px** | **18** | **separación entre bloques** | | 4xl | 40px | 2 | — | | 5xl | 48px | 2 | padding vertical del footer | Dos números hacen casi todo: **8px por dentro, 32px por fuera.** ### Rejilla - Ancho de contenido: **976px** (el marco del producto, las secciones de texto) - Tarjeta de email/detalle: **600px** - Rejilla de features: 3 columnas (`md:grid-cols-3`) con divisores `divide-black/5` ### La rejilla baseline oculta `line-height: 28px` en body, lead y title. `28px` también aparece como token de espaciado. No está declarado como rejilla, pero funciona como tal: **todo el texto de Amie cae en múltiplos de 28**. ### Filosofía de espaciado Aire vertical en el texto (1.75 de interlínea), densidad en la interfaz (gap 8px). Amie separa claramente "esto se lee" de "esto se usa", y les da ritmos opuestos. --- ## 6. Profundidad y Elevación ### Niveles de elevación | Nivel | Objeto | Receta | |---|---|---| | 0 | lienzo `#FAFAFA` | nada | | 0.5 | superficie hundida `#F2F2F2` / `#EBEBEB` | nada | | 1 | anillo interior | `inset 0 0 0 1px rgba(0,0,0,0.05)` | | 2 | **tarjeta, botón secundario** | `--shadow-natural` (3 capas) | | 3 | pequeña | `0 1px 3px rgba(0,0,0,.1), 0 1px 2px -1px rgba(0,0,0,.1)` | | 4 | **marco de producto** | `--shadow-natural-lg` (7 capas) | | — | botón primario | **ninguna** (el color es la elevación) | ### Radios de borde | Token | Valor | Nodos | Uso | |---|---|---|---| | xs | 4px | 14 | **el marcador**, checkboxes, iconos pequeños | | sm | 6px | 6 | tiles internas del producto | | md | 8px | 22 | controles de 32px, inputs, nav | | **lg** | **12px** | **28** | **tarjetas, botones de 49.6px, marco** | | xl | 16px | 1 | contenedor de sección | | panel | 32px (top only) | 5 | paneles que suben desde el borde | | full | 9999px | 17 | pills, avatares | La regla implícita: **el radio escala con la altura del control**, en torno a 1:4. Un botón de 32px lleva 8px; uno de 49.6px lleva 12px; un marcador de 20px de alto lleva 4px. --- ## 7. Lo que Sí y lo que No ### Sí hacer - Copia **la rampa de sombra de 7 capas**. Blur 1/3/6/12/24 con spread −0.5/−1.5/−3/−6/−12. Es la firma del sistema y es lo único que hace que dos superficies separadas por 2% de luminancia se lean como planos distintos. - Empieza la sombra con un **borde falso**: `0 0 0 1px rgba(0,0,0,0.06)` como primera capa. Nunca uses `border` en una tarjeta. - Deja que el lienzo sea `#FAFAFA` y las tarjetas `#FFFFFF`. **Nunca al revés.** - Reserva el azul `#11A8FF` para **una sola cosa**: la acción principal. Ni pestañas, ni links, ni iconos. - Da al primario **color sin sombra** y al secundario **sombra sin color**, con el mismo padding, radio y altura. Esa simetría es lo que hace que la pareja funcione. - Usa el **marcador** una vez por titular, sobre las palabras que llevan el argumento. Fondo al 30% si el color es saturado; opacidad plena si ya es claro. - Mantén `line-height: 28px` en body, lead y title. Es una rejilla baseline gratis. - Escala el radio con el control: 4px para el marcador, 8px para 32px de alto, 12px para 50px. - Haz los hairlines con **negro con alpha** (`rgba(0,0,0,0.04)`), nunca con un gris sólido. ### No hacer - No pongas **sombra al botón primario**. Es el único elemento elevado del sistema que va plano, y romperlo desequilibra la pareja de CTAs. - No uses **blanco de 16px sobre `#11A8FF`**: da 2.60:1 y falla AA sin excepción posible. Usa `#218FCD` de reposo y `#2C76A0` de hover. - No pongas el **marcador a tamaño de cuerpo**. A 16px la tinta `#D48F00` sobre el oro al 30% no pasa AA. Sube la tinta a `#A06B00`. - No uses **`gray-350` (`#A0A0A0`) para texto**. 2.51:1. Es color de glifo. - No colapses el **`line-height: 1.75`** del body a 1.5 "para que quepa más". Es la voz del sitio. - No gastes el **azul en pestañas o chips**. Amie los pinta de gris a propósito. - No sustituyas la rampa de 7 capas por **`box-shadow: 0 20px 40px rgba(0,0,0,.1)`**. Es la diferencia entre luz y borrón. - No añadas **gradientes de fondo**. El único gradiente real del sitio es `linear-gradient(to right top, #CFEEFF, #41BAFF)` y vive en una sola sección. - No uses **`border`** en las tarjetas. El borde es la capa 1 de la sombra. --- ## 8. Comportamiento Responsive ### Breakpoints (Tailwind por defecto, confirmados en las clases del sitio) | Nombre | Ancho | |---|---| | sm | 640px | | md | 768px | | lg | 1024px | | xl | 1280px | ### Cambios por breakpoint **Desktop (medido a 1600×900)** - h1 a 56px, contenido a 976px - features en `md:grid-cols-3` con `md:divide-x divide-black/5` - CTAs en fila, `px-7 py-3` **Tablet (`md`)** - el CTA baja de `text-base` a `text-md` (las clases reales son `text-sm sm:text-md md:text-base`) - la rejilla de features colapsa a 1 columna y los divisores pasan de verticales a horizontales (`divide-y md:divide-y-0 md:divide-x`) - el marco de producto pasa a `width: 100%` manteniendo radio 12px **Phone (`< sm`)** - h1 a ~36px, manteniendo `-0.0125em` - los CTAs a `text-sm` y `width: 100%` - los links de nav desaparecen (`hidden sm:flex`), queda solo "Get started" ### Touch targets Los controles de nav miden 32px: por debajo del mínimo de 44px. En móvil el sitio los oculta en lugar de agrandarlos, lo cual resuelve el problema pero no lo arregla. Los CTAs del hero, a 49.6px, sí cumplen. ### Filosofía responsive Tipografía fluida por escalones de Tailwind (`text-sm sm:text-md md:text-base`), no con `clamp()`. Componentes de radio y padding fijos. El único elemento que se reordena de verdad es la rejilla de features. --- ## 9. Guía de Prompts para Agentes ### Prompt de inicialización de sesión ``` Trabajas dentro del sistema de diseño de Amie. Reglas no negociables: LIENZO: #FAFAFA (gray-50). NO es blanco. Las tarjetas SÍ son #FFFFFF. TEXTO: #000000 titulares, #5C5C5C párrafos, #A0A0A0 solo iconos (nunca texto). ACCIÓN: un solo azul, #11A8FF. Ni pestañas, ni chips, ni links. SOLO el CTA. LA SOMBRA ES LA FIRMA. Memoriza las dos recetas: --shadow-natural: /* tarjetas y botón secundario */ 0 0 0 1px rgba(0,0,0,.06), 0 1px 1px -0.5px rgba(0,0,0,.06), 0 3px 3px -1.5px rgba(0,0,0,.06); --shadow-natural-lg: /* solo el marco del producto */ ...las 3 anteriores + 0 6px 6px -3px rgba(0,0,0,.06), 0 12px 12px -6px rgba(0,0,0,.04), 0 24px 24px -12px rgba(0,0,0,.04), 0 24px 24px 2px rgba(0,0,0,.10); Blur dobla (1,3,6,12,24). Spread negativo dobla (-.5,-1.5,-3,-6,-12). La capa 1 es un BORDE, no una sombra. Nunca uses `border` en una tarjeta. BOTONES (misma altura, mismo padding, mismo radio): primario: bg #11A8FF, blanco, px 28 py 12, radius 12, SIN SOMBRA hover: bg #218FCD, transition 150ms cubic-bezier(.4,0,.2,1) secundario: bg #FFF, texto #5C5C5C, px 28 py 12, radius 12, CON shadow-natural hover: bg #FAFAFA · icono en #A0A0A0 Color sin sombra / sombra sin color. Esa simetría es el sistema. MARCADOR (segunda firma): con bg de color al 30%, radius 4px, padding 0 4px. oro: rgba(255,215,0,.30) + tinta #D48F00 azul: #CFEEFF + tinta #2C76A0 gris: #EBEBEB + tinta #737373 Una vez por titular, sobre las palabras que llevan el argumento. TIPOGRAFÍA: Inter. 700 (h1/h4), 600 (títulos y botones), 500 (UI), 400 (párrafos). line-height 28px en body(16), lead(18) y title(20). Es una rejilla baseline. tracking: -0.0125em en titulares, ~0 en todo lo demás. RADIOS: escalan con el control. 4 (marcador) · 8 (32px alto) · 12 (50px alto) · 9999 (pills). ESPACIADO: 8px por dentro, 32px por fuera. Padding de tarjeta 20px. ``` ### Prompt: Crear nueva pantalla ``` Diseña [PANTALLA] con el sistema de Amie. 1. Fondo #FAFAFA. Todo lo que sea "una cosa" va en #FFFFFF con shadow-natural. 2. Un solo botón azul por vista. Todo lo demás es blanco-con-sombra o texto. 3. Si hay un titular grande, mete UN marcador sobre las palabras del argumento. 4. Párrafos en 16px/400 con line-height 28px. No lo bajes. 5. Espacia con 8 (dentro) y 32 (fuera). Padding de tarjeta 20px. 6. Cero gradientes de fondo, cero blobs, cero ilustraciones. El sistema es de papel. 7. Si algo necesita separarse pero NO elevarse, usa el anillo: box-shadow: inset 0 0 0 1px rgba(0,0,0,.05); ``` ### Prompt: Añadir componente al UI kit ``` Añade [COMPONENTE] al kit de Amie. - ¿Se eleva? -> shadow-natural (3 capas). NUNCA una sombra de una sola capa. - ¿Se separa sin elevarse? -> inset 0 0 0 1px rgba(0,0,0,.05). - ¿Es la acción principal? -> azul #11A8FF, sin sombra. - ¿Es una acción secundaria? -> blanco, con sombra, texto #5C5C5C. - Radio: 4 si mide <24px, 8 si mide ~32px, 12 si mide ~50px, 9999 si es pill. - Padding: 20px si es tarjeta, 12px 28px si es botón grande, 6px 16px si es botón chico. - Transición: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1). Nada más. - Los iconos van SIEMPRE un escalón de gris más claro que el texto que acompañan. ``` ### Prompt: Revisión de consistencia ``` Audita este CSS contra Amie. Marca como ERROR: - box-shadow de una sola capa en una tarjeta (debe ser la rampa de 3) - `border: 1px solid ...` en una tarjeta (debe ser la capa 1 de la sombra) - box-shadow en el botón primario (va plano) - background-color: #11A8FF en algo que no sea la acción principal - color #A0A0A0 aplicado a texto (solo glifos) - line-height < 1.75 en un párrafo de 16px - border-radius que no escale con la altura del control - gradiente de fondo en cualquier sección que no sea la banda azul - un marcador a tamaño de cuerpo (16px) con la tinta #D48F00 - un gris sólido (#EBEBEB) usado como borde (debe ser rgba(0,0,0,.04)) ``` ### Prompt: Variante de campaña ``` Haz una variante de campaña de Amie. Lo que PUEDES mover: - el color del marcador: cualquiera de las rampas 100/700 declaradas (rose, orange, purple, pink, fuchsia, teal, cyan, indigo, violet, amber, lime). Fondo = el 100, tinta = el 700. - el azul del CTA por otro 500 de la paleta, si mantienes la pareja color-sin-sombra / sombra-sin-color. Lo que NO puedes mover: - el lienzo #FAFAFA y las tarjetas #FFFFFF - las dos recetas de sombra - el line-height 28px - la disciplina de un solo color de acción por vista ``` --- ## 10. Movimiento (Motion) | Propiedad | Valor real medido | |---|---| | easing | `cubic-bezier(0.4, 0, 0.2, 1)` (el `ease-in-out` de Tailwind) | | duración | `150ms` | | propiedades animadas | `color`, `background-color` (`transition-colors`) | | hover de botón | cambio de un escalón en la rampa | | hover de tarjeta | ninguno | Amie **solo anima color**. No hay `transform`, no hay `translateY`, no hay `scale` en los componentes de la interfaz. Las clases `hover:scale-105`, `hover:rotate-3` y `hover:scale-[1.15]` existen en el CSS de Tailwind del sitio, pero se usan en la ilustración del calendario, no en los controles. Es la decisión coherente con todo lo demás: un sistema que quiere desaparecer no debe moverse. Con `prefers-reduced-motion: reduce` no hay nada que desactivar, porque no hay nada que se mueva. Ese es, probablemente, el mejor cumplido que se le puede hacer a un sistema de motion. --- ## Anexo: Stack técnico detectado - **Framework**: Next.js con Tailwind CSS. Las utilidades `hover:bg-blue-600`, `shadow-natural`, `ring-1 ring-inset ring-black/10`, `tracking-[-0.0125em]` y `rounded-xl` aparecen literalmente en el DOM. - **Tipografía**: `Inter var` (variable) servida por `next/font` con fallback métrico generado (`Inter Fallback`). Más `Averia Serif Libre`, cargada pero sin uso visible en la home. Ambas están en Google Fonts. - **Sistema de color**: declarado en el `:root` como tripletes RGB (`--color-blue-500: 17, 168, 255`) para poder componer opacidades. 21 pasos de gris + 13 rampas de color de 9 pasos cada una = **138 tokens de color**. Encima, una capa de roles semánticos (`--color-primary`, `--color-secondary`, `--color-tertiary`, `--color-accent`, `--color-background`, `--color-separator`) que apunta a la rampa. Los componentes usan el rol, no la rampa. - **Tokens de producto**: `--nav-width: 74px`, `--inbox-width: 200px`, `--grid-row-height: 60px`, `--grid-timezone-width: 42px`, `--grid-allday-event-height: 24px`. Son las medidas del calendario, filtradas a la landing desde la app. - **Radios reales**: 12px (28 nodos), 8px (22), 9999px (17), 4px (14), 6px (6), 16px (1), 32px solo-arriba (5). - **Sombras reales**: `shadow-natural` (3 capas, 7 nodos), `shadow-natural-lg` (7 capas, 1 nodo), anillo interior al 5% (9 nodos) y al 10% (4 nodos), más las dos por defecto de Tailwind (`shadow` y `shadow-sm`). - **Gradientes**: exactamente uno visible, `linear-gradient(to right top, #CFEEFF, #41BAFF)`, en una sola banda. - **Color space**: la tinta del marcador de oro se declara en `color(display-p3 0.792 0.573 0.188)`; el hex `#D48F00` es su mapeo a sRGB. - **(no detectado)**: modo oscuro activo (la rampa está preparada, pero no hay `.dark` en la home), formularios, banners de estado, tipografía mono, motion de layout.