Rediseño impeccable v2: refresh visual de todo el sistema

Segunda iteración del rediseño (sesión separada con skill impeccable).
Toca prácticamente toda la UI: layout base, tokens (global.css),
todas las páginas de alumno y admin, componentes de solicitudes,
inventario, catálogo, filtros, toaster y modales.

Docs y sistema:
- DESIGN.md y PRODUCT.md actualizados con la nueva iteración.
- .impeccable/design.json refleja tokens vigentes.
- .impeccable/review/ contiene screenshots de la revisión visual.

Dependencias:
- Añade @fontsource-variable/jetbrains-mono (fuente monoespaciada).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-08-16 17:11:20 -07:00
parent d996be5cf8
commit 0247b979ca
36 changed files with 511 additions and 468 deletions
+111 -128
View File
@@ -1,44 +1,38 @@
---
name: LabPréstamos
description: Sistema institucional UABC para préstamo de material de laboratorio — la bitácora de papel y Excel, digitalizada.
description: Sistema institucional UABC para préstamo de material de laboratorio — un ticket de equipo, cruzado con un terminal de desarrollador.
colors:
verde-institucional: "#00723F"
verde-institucional-hover: "#005f34"
dorado-uabc: "#DD971A"
dorado-uabc-hover: "#c78614"
superficie: "#F4F7F5"
tinta: "#2D3748"
peligro: "#C53030"
cream: "#f4efea"
frost: "#ffffff"
chalk: "#f8f8f7"
ice: "#ebf9ff"
ink: "#383838"
pencil: "#a1a1a1"
graphite: "#818181"
primary: "#6fc2ff"
primary-hover: "#56b4f7"
secondary: "#ff9538"
secondary-hover: "#ef8526"
danger: "#f38e84"
danger-hover: "#ec7469"
danger-text: "#a83224"
positive: "#38c1b0"
attention: "#ffde00"
typography:
headline:
fontFamily: "Inter Variable, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
fontSize: "1.5rem (2xl) → 1.875rem (3xl) md+"
fontWeight: 600
lineHeight: 1.25
title:
fontFamily: "Inter Variable, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
fontSize: "1.125rem"
fontWeight: 600
lineHeight: 1.4
body:
fontFamily: "Inter Variable, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
fontFamily: "JetBrains Mono Variable, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace"
fontSize: "0.875rem"
fontWeight: 400
lineHeight: 1.5
letterSpacing: "0.02em"
label:
fontFamily: "Inter Variable, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
fontSize: "0.875rem"
fontWeight: 500
lineHeight: 1.3
caption:
fontFamily: "Inter Variable, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif"
fontFamily: "JetBrains Mono Variable, ui-monospace, monospace"
fontSize: "0.75rem"
fontWeight: 400
lineHeight: 1.4
fontWeight: 500
letterSpacing: "0.05em"
textTransform: uppercase
rounded:
control: "0.5rem"
emphasis: "1rem"
pill: "9999px"
control: "2px"
spacing:
tight: "0.5rem"
base: "1rem"
@@ -46,28 +40,28 @@ spacing:
section: "2rem"
components:
button-primary:
backgroundColor: "{colors.verde-institucional}"
textColor: "#ffffff"
backgroundColor: "{colors.primary}"
textColor: "{colors.ink}"
rounded: "{rounded.control}"
padding: "10px 16px"
button-secondary:
backgroundColor: "{colors.dorado-uabc}"
textColor: "#ffffff"
backgroundColor: "{colors.frost}"
textColor: "{colors.ink}"
rounded: "{rounded.control}"
padding: "10px 16px"
button-ghost:
backgroundColor: "transparent"
textColor: "{colors.tinta}"
textColor: "{colors.ink}"
rounded: "{rounded.control}"
padding: "10px 16px"
card:
backgroundColor: "#ffffff"
textColor: "{colors.tinta}"
backgroundColor: "{colors.frost}"
textColor: "{colors.ink}"
rounded: "{rounded.control}"
padding: "24px"
input:
backgroundColor: "#ffffff"
textColor: "{colors.tinta}"
backgroundColor: "{colors.frost}"
textColor: "{colors.ink}"
rounded: "{rounded.control}"
padding: "10px 12px"
---
@@ -76,151 +70,140 @@ components:
## Overview
**Creative North Star: "La Bitácora Digital"**
**Creative North Star: "The Equipment Tag on a Terminal Readout"**
LabPréstamos is the printed loan sheet and the Excel logbook it used to feed, collapsed into one live surface. Every visual decision defends that lineage: nothing decorative, nothing that would feel out of place next to an official UABC form, but nothing that feels like a cold spreadsheet either. The system is **cálido pero confiable** — warm but reliable — and it earns the "warm" half narrowly: a gold accent, soft rounded corners, and gentle motion sit on top of an otherwise flat, administrative base.
LabPréstamos was rebuilt against a fully pinned external brief (MotherDuck's crayon-terminal-on-cream neobrutalism), translated from a marketing site's vocabulary into an operational lab tool's. The identity keeps the source system's mechanics intact — a warm cream canvas, monospace type standing in for a terminal readout, hard 2px corners, and a flat charcoal-offset shadow that never blurs — while dropping what only belonged to marketing (hand-drawn duck illustrations, scrolling marquees, testimonial cards). What replaces the duck is the product's own mark: a loan tag with a punch-hole, echoing the paper ticket this system replaced.
The page itself stays flat and quiet — white cards on a pale green-grey surface, hairline borders instead of shadows, tabular numbers lined up like a real ledger. Depth is reserved for the two things that are genuinely *floating above* the page: the toast notifications and the mobile navigation dock. That asymmetry is deliberate — it is how the system tells the eye "this is the document" from "this is the chrome."
Depth here is binary, not a hierarchy: an element either sits flat on the page (bordered, no shadow tables, list rows, inputs, the nav) or it's a discrete raised object that "presses" into its own shadow on hover (buttons, standalone cards, modals, the login card). There is no soft, no blur, no ambient glow anywhere in the system — every visual weight decision reads as a hard yes/no.
Two audiences read this bitácora differently. The alumno's default device is the phone — the catalog, the request modal, the pill-shaped floating dock are all tuned for thumbs. The admin's default device is the desktop — dense tables, a persistent sidebar, KPI tiles. Neither view degrades on the other's device; every screen ships both a table and a card-list rendering.
Color plays a stricter role here than in the source brief. Sky Crayon blue is reserved for actionable, filled controls — never for status. A teal (Mint Sketch) was pulled out of the source's decorative rainbow set and fixed as the system's "positive/available" status color, because an operational tool needs that distinction and a marketing site never did. Coral Sketch was likewise fixed as the sole danger color, with a separately darkened text variant (`--color-danger-text`, `#a83224`) for body copy, because the source coral fails AA contrast on white at normal text weight — the fill stays light and loud, the text goes dark and readable.
**Key Characteristics:**
- Flat administrative base (white cards, hairline ink-tinted borders, no ambient shadow)
- Shadow appears only on floating overlay chrome — the mobile dock and toasts — never on the page plane
- Every status is a tinted pill: 1215% color wash background, full-strength text
- Tabular numbers everywhere a quantity, date, or stock figure appears
- One typeface (Inter Variable) carrying every role through weight and size alone
- Motion is a courtesy, not a performance: `motion-safe:`-gated, specific-property transitions, no `transition-all`
- Cream page canvas, white card surfaces, charcoal (`#383838`, never pure black) as the universal line, border, and text color
- Every corner is 2px — buttons, cards, inputs, dialogs, badges, the brand mark's own chip. No pills, no circles, no `rounded-full` anywhere in the system
- One shadow, one behavior: `-6px 6px 0 0 var(--color-ink)`, hard-edged, zero blur, on every button, standalone card, toast, and modal — and it flattens into the element on hover/focus (`translate(-6px, 6px)`)
- JetBrains Mono Variable everywhere, 0.02em tracking, uppercase treatment on nav labels, button labels, section labels, and headlines
- Status pills and count badges are tinted fills with a matching-color 1.5px border and always-charcoal text — color differentiates via background and border, never via colored type
- Dense, repeated surfaces (tables, list-item cards, form inputs) stay flat and bordered; only discrete, single-instance elements carry the shadow
## Colors
Two institutional hues carry the whole palette under a strict 60/30/10 split — green dominant, gold as a deliberately rare accent, everything else neutral ink and white.
The palette is inherited near-verbatim from the pinned MotherDuck brief; only the semantic *assignment* changes to fit an operational tool instead of a marketing site.
### Primary
- **Verde Institucional** (`#00723F`): the UABC green. Primary buttons, the desktop sidebar's entire background, active nav states, focus rings, "healthy/positive" status pills (disponible, aprobado, devuelto), the login mark. This is the color of the system's authority — it appears on anything that confirms, approves, or orients.
- **Sky Crayon** (`#6fc2ff`): the system's only filled-action color. Primary buttons, active nav state, focused/selected chips, "Solicitar"/"Aprobar"/"Filtrar"/"Continuar con Google." Text on it is always Charcoal Ink, never white — matching every other filled control in the system.
### Secondary
- **Dorado UABC** (`#DD971A`): the institutional gold. Used sparingly and only as an accent — secondary buttons, the "en préstamo" KPI tile, "mantenimiento" status pills, the logo-mark square on the sidebar/mobile header. Never the dominant color of a screen.
- **Duck Bill Orange** (`#ff9538`): sparse accent, repurposed from the source's "illustration/marquee" role (this app has neither) into the operational tool's low-emphasis-but-real accent — "Exportar CSV," "Mantenimiento" status tint, the "En préstamo" KPI tone.
### Neutral
- **Superficie** (`#F4F7F5`): the page background — a near-white green-grey, not pure white. Everything else (cards, dialogs, the desktop sidebar's text, dock) sits on top of it.
- **Tinta** (`#2D3748`): body text, and — critically — the **source color for every border in the system**. Borders are never a fixed gray; they're `color-mix(in oklab, var(--color-ink) N%, transparent)` at 820% depending on prominence. This ties every hairline to the same ink token instead of a separate gray scale.
- **Peligro** (`#C53030`): errors, destructive actions, and the one status that is allowed to break the tinted-pill convention (see Named Rules).
- **Cream Paper** (`#f4efea`): the page canvas — every screen's base layer.
- **Frost White** (`#ffffff`): card, dialog, sidebar, and nav surfaces — the raised layer on cream.
- **Chalk Gray** (`#f8f8f7`): hover wash on flat (non-shadowed) interactive rows, and the neutral badge fill for "Baja"/inactive states.
- **Charcoal Ink** (`#383838`): the universal line — every border, every default text color, the shadow color itself. Never pure black.
- **Pencil Gray** (`#a1a1a1`): secondary/muted text (labels under headings, metadata, roles) — a real token, not an opacity trick.
### Status colors (extension beyond the source brief)
- **Mint Sketch → Positive** (`#38c1b0`): "disponible," "aprobado," "devuelto en préstamo" status. Pulled out of the source's decorative rainbow-button palette because the operational tool needs a status color distinct from the primary action color; the source brief, built for a marketing site, never had this problem.
- **Coral Sketch → Danger** (`#f38e84` fill / `#a83224` text): "rechazado," "vencido," destructive actions. Split into two values because the fill color (used for badge backgrounds, borders, button fills) is deliberately light and loud, while body text needs the darker `-text` variant to clear 4.5:1 contrast on white.
### Named Rules
**The Ink-Mix Border Rule.** Every hairline border and divider is `color-mix(in oklab, var(--color-tinta) N%, transparent)`, never a literal gray hex. A border is always "ink, diluted," so it stays coherent with body text at any opacity.
**The Charcoal Text Rule.** No filled or tinted surface ever carries white or colored text — text is always Charcoal Ink, full stop. Color differentiates status and action through background fill and border only. This is a deliberate tightening of the source brief, which used white nav-button text as an exception; LabPréstamos has no exception.
**The Vencido Exception.** Every status pill uses the tinted-fill pattern (see Components → Badges) *except* an overdue loan ("Vencido"), which gets a solid `peligro` fill with white text — on both the table badge and, on mobile, a light danger wash across the entire card background. This is the system's one permitted alarm: reserve a solid semantic fill for the single state that genuinely needs to interrupt a scan, and only that state.
**The One Shadow Rule.** `-6px 6px 0 0 var(--color-ink)` is the only shadow value in the system. It never blurs, never softens, never gets a second variant for "subtle" elevation — an element either has this exact shadow or it has none.
## Typography
**Body & Display Font:** Inter Variable (with `ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif` fallback)
**Body & Display Font:** JetBrains Mono Variable (weights 100800 available; the system uses 400/500/600), with `ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace` fallback. Chosen as the pinned brief's own named substitute for the licensed Aeonik Mono.
**Character:** One typeface for the entire system — hierarchy comes from weight and size, never a second family. It reads as a single, consistent institutional voice rather than a "brand font + UI font" split.
**Character:** One monospace face for the entire system, 0.02em letter-spacing throughout to open up the mechanical density of mono at small sizes. Uppercase tracking is reserved for structural labels (nav items, button text, form labels, section headers, the login headline) — body copy, names, and descriptions stay in normal case so real data (student names, material names) stays legible rather than shouting.
### Hierarchy
- **Headline** (600, 1.5rem → 1.875rem at `md:`, 1.25 line-height): page-level `<h1>`s — "Mis préstamos", "Estadísticas", the login screen's title.
- **Title** (600, 1.125rem, 1.4 line-height): section and card headers — "Inicia sesión", "Inventario", empty-state headings.
- **Body** (400, 0.875rem, 1.5 line-height): the default text size for the whole system — table cells, descriptions, list content. Notably small-scale throughout; this is a dense operational tool, not editorial content.
- **Label** (500, 0.875rem): form field labels (`.label`), rendered at 90% ink opacity.
- **Caption** (400, 0.75rem, opacity 6080%): metadata — matrícula, inventory numbers, timestamps, hint text under fields.
- **Headline** (600, 1.5rem → 1.875rem at `md:`, uppercase): page `<h1>`s, the login screen's title.
- **Title** (600, 1.125rem): section and card headers, dialog titles — not uppercased by default, uppercased where it doubles as a nav/label element.
- **Body** (400, 0.875rem, 1.5 line-height): the default text size — table cells, descriptions, list content.
- **Label** (500, 0.75rem, 0.05em tracking, uppercase): every form field label (`.label`), nav items, badge text.
- **Caption** (400, 0.75rem, Pencil Gray): metadata — matrícula, inventory numbers, timestamps.
### Named Rules
**The Tabular Numbers Rule.** Any figure that represents a count — cantidad, stock (`disponible / total`), KPI values, dates — is rendered with `font-variant-numeric: tabular-nums`. Numbers must align like a ledger column, because that is literally what they replace.
**The Tabular Numbers Rule.** Any figure representing a count — cantidad, stock, KPI values, dates — carries `font-variant-numeric: tabular-nums`, inherited unchanged from the prior system. JetBrains Mono's own distinctive dotted-zero glyph reinforces the "terminal readout" reading at large KPI sizes.
## Layout
The system runs on Tailwind's default breakpoint (`md:` = 768px) as the single hard split between the mobile and desktop layouts — there is no intermediate tablet treatment.
**Desktop (≥768px):** a fixed 256px (`w-64`) left sidebar in solid Verde Institucional, full page height. It is collapsible: a hamburger button above the content toggles a `sidebar-collapsed` class on `<html>`, animated with a 200ms `translateX(-100%)`; the choice persists in `localStorage` and is applied via a blocking inline `<script>` in `<head>` before paint, so there is no collapse flash on reload. Content sits in `max-w-6xl` (data-dense admin views) or `max-w-4xl`/`max-w-md` (narrower alumno views), with `p-8` outer padding.
**Mobile (<768px):** no sidebar. A minimal fixed header (logo mark + user identity) sits at the top; navigation lives instead in a floating pill-shaped dock anchored to the bottom-center of the viewport, respecting `env(safe-area-inset-bottom)`. Content padding drops to `p-4` with `pb-28` to clear the dock.
**The Table/Card Swap Rule.** Every data-dense admin view (solicitudes, inventario, reportes) ships two complete renderings of the same data: a `<table>` for `md:block` and a `<ul>` of `.card` items for `md:hidden`. This is a structural swap, not a responsive squeeze — the mobile version is not a scrolled-sideways table, it is a genuinely different layout for the same rows.
Unchanged from the incumbent structural system — the redesign is a full re-skin, not a re-architecture. `md:` (768px) remains the single hard breakpoint between mobile and desktop. Desktop keeps the fixed 256px collapsible sidebar; mobile keeps a bottom navigation bar, now a flush, flat, full-width strip (not a floating pill) with a 2px charcoal top border and no shadow — matching the source brief's own flat, unshadowed nav-button treatment. Content still ships both a `md:block` table and a `md:hidden` card-list rendering for every data-dense admin view.
## Elevation & Depth
The system is flat by default. Cards, buttons, inputs, and dialogs carry no shadow — only a 1px ink-mix hairline border. Depth is reserved, deliberately, for the two things that are not part of the page: the mobile dock nav and the toast stack, both of which visually float above whatever is scrolling underneath them.
Binary, not graduated. An element is either **flat** (a 1.52px charcoal border, no shadow — the default for anything dense or repeated: tables, list-item cards, inputs, the nav) or **raised** (2px charcoal border plus the one hard shadow — reserved for discrete, single-instance, actionable surfaces: buttons, the login card, modals/dialogs, toasts, KPI tiles, and clickable dashboard tiles). There is no third state, no blur, no soft ambient shadow anywhere in the system.
### Shadow Vocabulary
- **Floating chrome** (`box-shadow: 0 10px 30px -8px rgba(0,0,0,0.25)`): the mobile dock nav — a soft, diffuse shadow that reads as "hovering," combined with `backdrop-blur` and a translucent white background.
- **Overlay notification** (`box-shadow: 0 16px 40px -12px rgba(0,0,0,0.25)`): the toast stack — same diffuse quality, slightly heavier, paired with `backdrop-blur-xl` and `bg-white/85`.
- **Hard** (`box-shadow: -6px 6px 0 0 var(--color-ink)`, token `--shadow-hard`): every raised element at rest.
- **Hard, pressed** (`transform: translate(-6px, 6px)`, shadow reads as `0 0 0 0`): the same element on hover/focus — it visually "presses" into its own shadow. Active state presses halfway (`--shadow-hard-sm`, `-3px 3px`) for a two-stage press.
### Named Rules
**The Flat Page, Floating Chrome Rule.** If an element is part of the document (a card, a table, a form), it stays flat with a hairline border. If an element floats above the document regardless of scroll (the dock, a toast), it gets a soft ambient shadow plus backdrop-blur. Shadow is the visual signal for "this is not part of the page you're reading."
**The Press Rule.** Every raised element's hover state is the same transform: translate exactly the shadow's own offset, so the shadow disappears under the element. No brightness filter, no color darken — motion is the only hover signal on raised elements.
## Shapes
Three radius steps, used by role rather than by component:
- **Control** (`0.5rem`, token `--radius-card`): the default — buttons, cards, inputs, dialogs, table containers. This is the system's baseline corner.
- **Emphasis** (`1rem`, `rounded-2xl`): reserved for two "first impression" surfaces — the login screen's avatar mark and toast notifications. A visibly softer corner than the control radius, used to signal warmth at the exact moments the system greets or interrupts the user.
- **Pill** (`9999px`, `rounded-full`): status badges, the mobile dock and its buttons, the pending-count chip. Anything that is a small, discrete piece of state rather than a container.
Borders are always hairline (1px) and always ink-mix (see Colors → Named Rules); the system has no heavy or decorative border weight.
One radius for the entire system: **2px** (`--radius-card`, and Tailwind's `rounded-lg`/`rounded-2xl`/`rounded-full` are globally overridden to resolve to it). Buttons, cards, inputs, dialogs, badges, the brand mark's chip — everything is a near-square corner. There is no pill, no circle, no soft/emphasis radius tier; the prior system's `rounded-full` nav dock and status pills were converted wholesale. Borders are always 1.52px solid Charcoal Ink (never a tinted or literal-gray border) — the system has no hairline-border convention.
## Components
### Brand Mark
- A single authored glyph (`BrandMark.astro`, 24×24 viewBox) stands in for the system's identity everywhere a mark is needed: the desktop sidebar header, the mobile header, the login screen, and the 403/404 states. It reads as a loan tag with a punch-hole — a quiet nod to the physical préstamo ticket the system replaces.
- It is a solid silhouette (not an outline stroke like the nav icons), rendered via `currentColor` so it can sit white-on-primary or tinted-on-danger without a second asset.
- It is the product's own mark, not an institutional crest — it never stands in for an official UABC or laboratorio seal.
- The favicon (`public/favicon.svg`) is the same glyph, colored Verde Institucional in light mode and Superficie in dark mode.
### Buttons
- **Shape:** Control radius (0.5rem), 44px minimum height, `touch-action: manipulation` — every button is a comfortable tap target regardless of platform.
- **Primary:** Verde Institucional background, white text. The system's default call to action (submit, approve, continuar con Google).
- **Secondary:** Dorado UABC background, white text. Used sparingly — filtering actions, not primary flows.
- **Ghost:** Transparent background, ink text, hairline ink-mix border (15%). Used for "Cancelar" / "Limpiar" — the low-commitment counterpart to Primary.
- **Hover / Focus:** hover is a uniform `motion-safe:hover:brightness-110` filter across all filled variants (not a swap to a separate hover-color token); focus is a 2px solid outline in Verde Institucional, 2px offset. Disabled drops to 50% opacity and disables pointer events.
- **Shape:** 2px radius, 2px Charcoal Ink border, 44px minimum height, `touch-action: manipulation`.
- **Primary:** Sky Crayon fill, Charcoal Ink text, hard shadow. The default call to action.
- **Secondary:** Frost White fill (not a second brand color — the source brief is explicit that Sky Crayon is the sole filled-action color), Charcoal Ink border and text, hard shadow.
- **Ghost:** transparent fill, Charcoal Ink text, a lighter border (35% ink-mix), no shadow. Used for "Cancelar"/"Limpiar."
- **Hover / Focus / Active:** see Elevation → The Press Rule.
### Badges / Status Pills
- **Style:** pill radius, `text-xs`/`text-sm font-semibold`, `px-2` to `px-2.5`, `py-0.5`.
- **The Tinted Pill Rule.** Background = the semantic color at 1215% via `color-mix`; text = the semantic color at full strength. Never a solid fill — with the one confirmed exception below.
- **Semantic mapping:** disponible / aprobado / devuelto → Verde Institucional tint. mantenimiento → Dorado UABC tint (text at the `-hover` shade for contrast). baja / rechazado → ink tint (neutral, ~810%). **Vencido** (overdue) → the sole solid-fill exception: white text on full-strength Peligro, plus a light danger wash across the whole card on mobile.
- **Style:** 2px radius, 1.5px border in the semantic color, uppercase text at 0.03em tracking, always Charcoal Ink.
- **The Tinted-Fill-Bordered Rule.** Background = the semantic color mixed 1825% into white; border = the semantic color at full strength; text = Charcoal Ink always. Count badges (the "N pendientes" chip beside a heading) use a solid semantic fill instead of a tint, bordered in Charcoal Ink — the one place a badge goes solid.
- **Semantic mapping:** disponible / aprobado / devuelto → Positive (mint). mantenimiento / en préstamo (KPI) → Secondary (orange). rechazado / vencido → Danger (coral). baja / neutral counts → Chalk Gray with a graphite border.
### Cards / Containers
- **Corner:** Control radius (0.5rem).
- **Background:** white, always — the one surface color that appears identically on both the pale-green page background and the green sidebar.
- **Border:** hairline ink-mix (10%); no shadow (see Elevation).
- **Internal Padding:** `p-6` for standard cards and forms; `p-4` for dense KPI tiles; `p-0` when the card is a table/list wrapper (the table supplies its own cell padding).
- **Corner:** 2px.
- **Background:** Frost White, always.
- **Flat variant** (`.card-flat`, `.card`): 1.52px Charcoal Ink border, no shadow. Used for tables, list rows, dense repeated content.
- **Raised variant** (`.card-raised`, `.card-link`): adds the hard shadow. Used for the login card, clickable dashboard tiles, KPI tiles — anything discrete and singular rather than part of a repeated list.
- **Internal Padding:** `p-6` standard, `p-4` for dense KPI tiles, `p-0` when the card wraps a table (the table supplies its own cell padding).
### Inputs / Fields
- **Style:** white background, hairline ink-mix border (20%), Control radius, 44px minimum height.
- **Focus:** 2px solid Verde Institucional outline, 2px offset — the same focus treatment as buttons and links, no separate glow or border-color shift.
- **Label:** `.label` class, 0.875rem/500 weight, ink at 90% opacity, always paired via `htmlFor`/`id`.
- **Error:** inline `role="alert"` text in Peligro below the field, not a border-color change.
- **Style:** Frost White background, 2px Charcoal Ink border, 2px radius, 44px minimum height. No shadow — inputs are always flat, matching the source brief's own Text Input spec.
- **Focus:** border color shifts to Sky Crayon; no glow, no ring.
- **Label:** `.label` — uppercase, 0.75rem, 0.05em tracking, Charcoal Ink.
- **Error:** inline `role="alert"` text in Danger-text below the field.
### Navigation
- **Desktop sidebar:** solid Verde Institucional panel, white text at 85% opacity for inactive items, white/15% background wash for the active item, `aria-current="page"`. Collapsible (see Layout).
- **Mobile dock:** floating pill, `backdrop-blur` + `bg-white/95`, icon-only (24×24 heroicons-outline, `stroke-width: 1.8`, `currentColor`), active item = solid Verde Institucional circle. Sign-out is visually separated by a vertical hairline divider and turns Peligro on hover.
- **Desktop sidebar:** Frost White panel (not a colored panel — a deliberate departure from the prior UABC-green sidebar, matching the source brief's flat white nav bar), 2px Charcoal Ink right border. Active item = solid Sky Crayon chip with a 2px Charcoal border; inactive = transparent with a Chalk Gray hover wash. Uppercase labels throughout. Collapsible, same mechanism as before (localStorage + blocking inline script, no flash).
- **Mobile nav:** a flush, full-width bottom bar (not a floating pill), Frost White, 2px Charcoal top border, no shadow — flat, matching the source brief's "nav buttons are flat" rule. Active icon = a 2px-radius Sky Crayon square with Charcoal border.
- **Brand mark chip:** on colored (Sky Crayon) or panel backgrounds, a 2px-radius chip with a 2px Charcoal border; on the white sidebar/mobile header it's a translucent white wash instead, avoiding a third solid color competing with the mark itself.
### Toasts (signature component)
- Fixed top-center overlay, `rounded-2xl`, `bg-white/85` + `backdrop-blur-xl`, floating-chrome shadow.
- A circular color chip (36px) leads each toast: Verde Institucional for success, Peligro for error, Dorado UABC for info — each with a small stroke icon.
- Entrance: 260ms `cubic-bezier(0.22, 1, 0.36, 1)` translate+scale+fade; auto-dismisses at 3.8s; tap anywhere to dismiss early; fully respects `prefers-reduced-motion`.
- Survives a `location.reload()` via a `sessionStorage` queue — the system was built assuming most actions end in a reload, and the toast must not be lost.
### Toasts
- Frost White, 2px Charcoal Ink border, hard shadow, 2px radius (down from the prior system's blurred glass `rounded-2xl` treatment — MotherDuck bans blur and ambient shadow outright).
- A 2px-bordered color chip (36px) leads each toast: Positive for success, Danger for error, Secondary for info — Charcoal Ink stroke icon, not white.
- Entrance: 260ms translate+fade, same timing as before; still respects `prefers-reduced-motion`; still survives `location.reload()` via the sessionStorage queue.
### Modals
- Native `<dialog>` element (no custom overlay library), Control radius, `backdrop:bg-black/40`, width `min(92vw, 28rem)`.
- Focus moves to the first field on open; closes on backdrop click or the close-icon control (a drawn SVG X, never a `×` character); disabled while a submit is in flight.
- Native `<dialog>`, 2px radius, 2px Charcoal Ink border, hard shadow, `backdrop:bg-black/40`. The prior system's borderless, shadowless dialog surface gained both a border and the system's one shadow — modals are a "raised" surface by the binary elevation rule.
- Close controls are always a drawn SVG X (never a `×` character), matching the rest of the icon system.
## Do's and Don'ts
### Do:
- **Do** use `color-mix(in oklab, var(--color-tinta) N%, transparent)` for any new border or divider — never a literal gray.
- **Do** keep shadow exclusive to floating overlay chrome (toasts, the mobile dock). A new floating element earns the same shadow vocabulary; a page element does not.
- **Do** use the tinted-pill pattern (1215% background, full-strength text) for any new status or state indicator.
- **Do** apply `font-variant-numeric: tabular-nums` to any new numeric quantity, stock figure, or date.
- **Do** ship both a `md:block` table and a `md:hidden` card-list rendering for any new data-dense admin view.
- **Do** gate all motion with `motion-safe:` and animate specific properties (`transition-colors`, `transition-[filter,...]`), never `transition-all`.
- **Do** give every interactive control a 44px minimum tap target and `touch-action: manipulation`.
- **Do** draw every icon as an SVG (the shared heroicons-outline language, or the `BrandMark` glyph for identity) — close controls, chevrons, and status glyphs included.
- **Do** use the exact shadow `-6px 6px 0 0 var(--color-ink)` (`--shadow-hard`) for every raised element, and the exact press transform `translate(-6px, 6px)` on its hover/focus state.
- **Do** keep every radius at 2px — buttons, cards, inputs, dialogs, badges, chips. No exceptions, no emphasis tier.
- **Do** keep text Charcoal Ink on every fill, tint, or border color. Never white, never the semantic color itself.
- **Do** reserve Sky Crayon for actionable, filled controls; use Positive (mint), Danger (coral), or Secondary (orange) for status and non-primary accents.
- **Do** keep dense/repeated surfaces (tables, list cards, inputs, nav) flat and bordered; reserve the hard shadow for discrete, singular, actionable surfaces.
- **Do** draw every icon as an SVG in the shared heroicons-outline language (or the `BrandMark` glyph for identity) — never a unicode glyph or emoji standing in for one.
- **Do** apply `font-variant-numeric: tabular-nums` to every numeric quantity, stock figure, or date.
- **Do** ship both a `md:block` table and a `md:hidden` card-list rendering for every data-dense admin view.
### Don't:
- **Don't** stand in a unicode glyph (`×`, ``, `✓`, emoji) for an icon — every icon is a drawn SVG, one consistent stroke and weight.
- **Don't** add a shadow to `.card`, `.btn`, or `.input` — the system's flatness on the page plane is deliberate.
- **Don't** introduce a second typeface. Inter Variable carries every role through weight and size.
- **Don't** give a status pill a solid saturated fill — the tinted wash is the rule, and "Vencido" is the system's one confirmed exception, not a precedent to extend.
- **Don't** reach for `rounded-2xl` outside the login mark and toasts; it is reserved for "first impression / interruption" moments, not a general card radius.
- **Don't** replace the mobile bottom dock with a hamburger drawer, or the desktop sidebar with a top bar — the device-appropriate nav pattern per breakpoint is an established, deliberate split.
- **Don't** use blur, glass, or a soft ambient shadow anywhere — every shadow is the one hard-edged offset value, or there is no shadow.
- **Don't** introduce a radius above 2px, or a pill/circle shape, anywhere in the UI.
- **Don't** use a second filled brand color for "secondary" actions — Secondary buttons are white-filled and charcoal-outlined, never a second solid color.
- **Don't** reuse Sky Crayon for status pillsstatus has its own colors (Positive/Danger/Secondary); Sky Crayon means "you can act on this."
- **Don't** introduce a second typeface. JetBrains Mono Variable carries every role through weight, size, and case.
- **Don't** stand a unicode glyph in for an icon.