Files
labre-web/.impeccable/design.json
T
LakG 0247b979ca 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>
2026-08-16 17:11:20 -07:00

137 lines
11 KiB
JSON

{
"schemaVersion": 2,
"generatedAt": "2026-08-16T00:00:00.000Z",
"title": "Design System: LabPréstamos",
"extensions": {
"colorMeta": {
"cream": { "role": "neutral", "displayName": "Cream Paper", "canonical": "#f4efea" },
"frost": { "role": "neutral", "displayName": "Frost White", "canonical": "#ffffff" },
"chalk": { "role": "neutral", "displayName": "Chalk Gray", "canonical": "#f8f8f7" },
"ink": { "role": "neutral", "displayName": "Charcoal Ink", "canonical": "#383838" },
"pencil": { "role": "neutral", "displayName": "Pencil Gray", "canonical": "#a1a1a1" },
"primary": { "role": "primary", "displayName": "Sky Crayon", "canonical": "#6fc2ff" },
"secondary": { "role": "secondary", "displayName": "Duck Bill Orange", "canonical": "#ff9538" },
"danger": { "role": "danger", "displayName": "Coral Sketch (fill)", "canonical": "#f38e84" },
"danger-text": { "role": "danger", "displayName": "Coral Sketch (text, AA-darkened)", "canonical": "#a83224" },
"positive": { "role": "success", "displayName": "Mint Sketch", "canonical": "#38c1b0" }
},
"typographyMeta": {
"body": { "displayName": "Body / Mono", "purpose": "Universal voice — every role through weight, size, and case." },
"label": { "displayName": "Label", "purpose": "Uppercase structural labels: nav, buttons, form labels, headers." }
},
"shadows": [
{ "name": "hard", "value": "-6px 6px 0 0 #383838", "purpose": "The system's only shadow — every raised element at rest." },
{ "name": "hard-sm", "value": "-3px 3px 0 0 #383838", "purpose": "Active/pressed state of a raised element (halfway press)." }
],
"motion": [
{ "name": "press", "value": "transform: translate(-6px, 6px); transition: transform 100ms ease-out;", "purpose": "Hover/focus on any raised element — presses into its own shadow." }
],
"breakpoints": [
{ "name": "md", "value": "768px" }
]
},
"components": [
{
"name": "Primary Button",
"kind": "button",
"refersTo": "button-primary",
"description": "The system's default call to action.",
"html": "<button class=\"ds-btn ds-btn-primary\">Solicitar</button>",
"css": ".ds-btn { display:inline-flex; align-items:center; justify-content:center; gap:8px; min-height:44px; padding:10px 16px; border-radius:2px; border:2px solid #383838; font-family:'JetBrains Mono Variable',monospace; letter-spacing:0.02em; font-weight:500; box-shadow:-6px 6px 0 0 #383838; transition:transform 100ms ease-out; } .ds-btn:hover, .ds-btn:focus-visible { transform:translate(-6px,6px); box-shadow:0 0 0 0 transparent; } .ds-btn-primary { background:#6fc2ff; color:#383838; }"
},
{
"name": "Secondary Button",
"kind": "button",
"refersTo": "button-secondary",
"description": "White-filled, charcoal-outlined — never a second brand color.",
"html": "<button class=\"ds-btn ds-btn-secondary\">Exportar CSV</button>",
"css": ".ds-btn-secondary { background:#ffffff; color:#383838; }"
},
{
"name": "Ghost Button",
"kind": "button",
"refersTo": "button-ghost",
"description": "Low-commitment counterpart — Cancelar/Limpiar.",
"html": "<button class=\"ds-btn-ghost\">Cancelar</button>",
"css": ".ds-btn-ghost { display:inline-flex; align-items:center; justify-content:center; gap:8px; min-height:44px; padding:10px 16px; border-radius:2px; border:2px solid rgba(56,56,56,0.35); background:transparent; color:#383838; font-family:'JetBrains Mono Variable',monospace; letter-spacing:0.02em; font-weight:500; } .ds-btn-ghost:hover { background:#f8f8f7; border-color:#383838; }"
},
{
"name": "Raised Card",
"kind": "card",
"refersTo": "card",
"description": "Discrete, singular, actionable surface — login card, dashboard tile, KPI tile.",
"html": "<a class=\"ds-card-raised\" href=\"#\"><h2>Catálogo</h2><p>Ver material disponible.</p></a>",
"css": ".ds-card-raised { display:block; background:#ffffff; border:2px solid #383838; border-radius:2px; padding:24px; box-shadow:-6px 6px 0 0 #383838; transition:transform 100ms ease-out; } .ds-card-raised:hover, .ds-card-raised:focus-visible { transform:translate(-6px,6px); box-shadow:0 0 0 0 transparent; } .ds-card-raised h2 { font-family:'JetBrains Mono Variable',monospace; text-transform:uppercase; letter-spacing:0.02em; font-size:1.125rem; margin:0 0 4px; color:#383838; } .ds-card-raised p { color:#a1a1a1; font-family:'JetBrains Mono Variable',monospace; font-size:0.875rem; margin:0; }"
},
{
"name": "Flat Card / Table Wrapper",
"kind": "card",
"refersTo": "card",
"description": "Dense, repeated content — tables, list rows. Bordered, no shadow.",
"html": "<div class=\"ds-card-flat\">Fila de tabla o lista</div>",
"css": ".ds-card-flat { background:#ffffff; border:1.5px solid #383838; border-radius:2px; padding:24px; font-family:'JetBrains Mono Variable',monospace; color:#383838; }"
},
{
"name": "Text Input",
"kind": "input",
"refersTo": "input",
"description": "Flat, bordered, no shadow, no glow focus.",
"html": "<input class=\"ds-input\" type=\"text\" placeholder=\"Nombre o Nº inventario…\" />",
"css": ".ds-input { width:100%; min-height:44px; padding:10px 12px; border-radius:2px; border:2px solid #383838; background:#ffffff; font-family:'JetBrains Mono Variable',monospace; color:#383838; } .ds-input:focus { outline:none; border-color:#6fc2ff; }"
},
{
"name": "Status Badge",
"kind": "chip",
"refersTo": "badge",
"description": "Tinted fill, semantic-color border, always charcoal text.",
"html": "<span class=\"ds-badge ds-badge-positive\">Disponible</span>",
"css": ".ds-badge { display:inline-flex; align-items:center; border-radius:2px; padding:2px 8px; font-family:'JetBrains Mono Variable',monospace; font-size:0.75rem; font-weight:600; text-transform:uppercase; letter-spacing:0.03em; color:#383838; } .ds-badge-positive { background:color-mix(in oklab, #38c1b0 18%, white); border:1.5px solid #38c1b0; } .ds-badge-danger { background:color-mix(in oklab, #f38e84 18%, white); border:1.5px solid #f38e84; }"
},
{
"name": "Nav Item (desktop sidebar)",
"kind": "nav",
"refersTo": "nav-item",
"description": "Uppercase mono label; active = solid Sky Crayon chip with charcoal border.",
"html": "<a class=\"ds-nav-item ds-nav-item-active\" href=\"#\">Catálogo</a>",
"css": ".ds-nav-item { display:flex; align-items:center; gap:12px; padding:10px 12px; border-radius:2px; border:2px solid transparent; font-family:'JetBrains Mono Variable',monospace; text-transform:uppercase; letter-spacing:0.02em; font-size:0.875rem; color:#383838; } .ds-nav-item-active { background:#6fc2ff; border-color:#383838; } .ds-nav-item:not(.ds-nav-item-active):hover { background:#f8f8f7; }"
}
],
"narrative": {
"northStar": "The Equipment Tag on a Terminal Readout",
"overview": "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. Depth here is binary, not a hierarchy: an element either sits flat on the page or it's a discrete raised object that presses into its own shadow on hover. Color plays a stricter role than in the source brief: Sky Crayon blue is reserved for actionable, filled controls; Mint Sketch was pulled from the source's decorative rainbow set and fixed as the positive-status color; Coral Sketch was fixed as the sole danger color, split into a light fill and a separately darkened AA-compliant text variant.",
"keyCharacteristics": [
"Cream page canvas, white card surfaces, charcoal (never pure black) as the universal line, border, and text color",
"Every corner is 2px — no pills, no circles, no rounded-full anywhere",
"One shadow, one behavior: -6px 6px 0 0 charcoal, hard-edged, flattens into the element on hover/focus",
"JetBrains Mono Variable everywhere, 0.02em tracking, uppercase on structural labels only",
"Status pills are tinted fills with a matching-color border and always-charcoal text",
"Dense, repeated surfaces stay flat and bordered; only discrete, single-instance elements carry the shadow"
],
"rules": [
{ "name": "The Charcoal Text Rule", "body": "No filled or tinted surface ever carries white or colored text — text is always Charcoal Ink. Color differentiates status and action through background fill and border only.", "section": "colors" },
{ "name": "The One Shadow Rule", "body": "-6px 6px 0 0 var(--color-ink) is the only shadow value in the system. It never blurs, never softens, never gets a second 'subtle' variant.", "section": "colors" },
{ "name": "The Tabular Numbers Rule", "body": "Any figure representing a count carries font-variant-numeric: tabular-nums.", "section": "typography" },
{ "name": "The Press Rule", "body": "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.", "section": "elevation" },
{ "name": "The Tinted-Fill-Bordered Rule", "body": "Badge background = the semantic color mixed 18-25% into white; border = the semantic color at full strength; text = Charcoal Ink always.", "section": "components" }
],
"dos": [
"Do use the exact shadow -6px 6px 0 0 var(--color-ink) for every raised element, and the exact press transform translate(-6px, 6px) on hover/focus.",
"Do keep every radius at 2px — buttons, cards, inputs, dialogs, badges, chips.",
"Do keep text Charcoal Ink on every fill, tint, or border color.",
"Do reserve Sky Crayon for actionable, filled controls; use Positive/Danger/Secondary for status.",
"Do keep dense/repeated surfaces flat and bordered; reserve the hard shadow for discrete, singular surfaces.",
"Do draw every icon as an SVG — never a unicode glyph or emoji.",
"Do apply font-variant-numeric: tabular-nums to every numeric quantity, stock figure, or date.",
"Do ship both a table and a card-list rendering for every data-dense admin view."
],
"donts": [
"Don't use blur, glass, or a soft ambient shadow anywhere.",
"Don't introduce a radius above 2px, or a pill/circle shape, anywhere.",
"Don't use a second filled brand color for secondary actions.",
"Don't reuse Sky Crayon for status pills.",
"Don't introduce a second typeface.",
"Don't stand a unicode glyph in for an icon."
]
}
}