Files
labre-web/DESIGN.md
T
LakG 57b07b9b82 Rediseño impeccable: brand mark, páginas 403/404, DESIGN.md + PRODUCT.md
Rediseño hecho en sesión aparte con el skill impeccable. Se registran
las especificaciones y ajustes visuales al sistema ya en producción.

Añade:
- BrandMark.astro con el escudo/logo del laboratorio.
- Favicon actualizado (svg + ico).
- Páginas propias 403 y 404 consistentes con el sistema visual.
- DESIGN.md y PRODUCT.md documentando decisiones.
- .impeccable/design.json con el design system tokenizado.

Ajusta componentes existentes (modales, autocomplete, layout, login,
solicitudes, mis-préstamos, middleware) para alinearse a los tokens
del design system.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-16 15:19:57 -07:00

227 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: LabPréstamos
description: Sistema institucional UABC para préstamo de material de laboratorio — la bitácora de papel y Excel, digitalizada.
colors:
verde-institucional: "#00723F"
verde-institucional-hover: "#005f34"
dorado-uabc: "#DD971A"
dorado-uabc-hover: "#c78614"
superficie: "#F4F7F5"
tinta: "#2D3748"
peligro: "#C53030"
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"
fontSize: "0.875rem"
fontWeight: 400
lineHeight: 1.5
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"
fontSize: "0.75rem"
fontWeight: 400
lineHeight: 1.4
rounded:
control: "0.5rem"
emphasis: "1rem"
pill: "9999px"
spacing:
tight: "0.5rem"
base: "1rem"
loose: "1.5rem"
section: "2rem"
components:
button-primary:
backgroundColor: "{colors.verde-institucional}"
textColor: "#ffffff"
rounded: "{rounded.control}"
padding: "10px 16px"
button-secondary:
backgroundColor: "{colors.dorado-uabc}"
textColor: "#ffffff"
rounded: "{rounded.control}"
padding: "10px 16px"
button-ghost:
backgroundColor: "transparent"
textColor: "{colors.tinta}"
rounded: "{rounded.control}"
padding: "10px 16px"
card:
backgroundColor: "#ffffff"
textColor: "{colors.tinta}"
rounded: "{rounded.control}"
padding: "24px"
input:
backgroundColor: "#ffffff"
textColor: "{colors.tinta}"
rounded: "{rounded.control}"
padding: "10px 12px"
---
# Design System: LabPréstamos
## Overview
**Creative North Star: "La Bitácora Digital"**
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.
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."
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.
**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`
## 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.
### 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.
### 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.
### 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).
### 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 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.
## Typography
**Body & Display Font:** Inter Variable (with `ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif` fallback)
**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.
### 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.
### 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.
## 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.
## 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.
### 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`.
### 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."
## 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.
## 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.
### 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.
### 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).
### 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.
### 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.
### 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.
### 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.
## 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.
### 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.