Moléculas
Átomos combinados en algo con una función concreta: una tarjeta, una tabla, un indicador, un buscador. Es el nivel donde se resuelve la mayoría de las pantallas.
Tarjeta de contenido
El contenedor por defecto de cualquier bloque: título a la izquierda, acción a la derecha.
styles/app-shell.css
<div class="content-card">
<div class="content-card-header">
<h2 class="content-card-title mb-0">Últimos movimientos</h2>
<button class="btn btn-gm-primary btn-sm"><i class="fas fa-plus me-1"></i> Nuevo</button>
</div>
<div class="content-card-body">
<p class="mb-0 text-muted">El contenido del bloque va acá.</p>
</div>
</div>
Indicador (KPI)
La fila de cifras que abre casi todas las pantallas de listado.
GrupoMecsaProyectos/pages/clientes.php
<div class="row g-3">
<div class="col-md-4">
<div class="card kpi-card border-0 shadow-sm h-100">
<div class="card-body d-flex align-items-center">
<div class="icon-circle bg-primary bg-opacity-10 text-primary me-3"><i class="fas fa-users"></i></div>
<div>
<div class="kpi-label">Total Clientes</div>
<div class="kpi-value" data-counter="184">0</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card kpi-card border-0 shadow-sm h-100">
<div class="card-body d-flex align-items-center">
<div class="icon-circle bg-success bg-opacity-10 text-success me-3"><i class="fas fa-user-check"></i></div>
<div>
<div class="kpi-label">Activos</div>
<div class="kpi-value text-success" data-counter="167">0</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card kpi-card border-0 shadow-sm h-100">
<div class="card-body d-flex align-items-center">
<div class="icon-circle bg-danger bg-opacity-10 text-danger me-3"><i class="fas fa-user-slash"></i></div>
<div>
<div class="kpi-label">Inactivos</div>
<div class="kpi-value text-danger" data-counter="17">0</div>
</div>
</div>
</div>
</div>
</div>
data-counter. Tres o cuatro por fila; más que eso ya no se lee.Encabezado de pantalla
Título, bajada y acciones. Va arriba del contenido, después del topbar.
styles/app-shell.css
<div class="inner-page-header">
<div class="inner-page-titles">
<h1 class="inner-page-title">Clientes</h1>
<p class="inner-page-subtitle">Registro maestro de clientes y su estado comercial.</p>
</div>
<div class="inner-page-actions">
<button class="btn btn-outline-primary btn-sm"><i class="fas fa-file-excel me-1"></i> Exportar</button>
<button class="btn btn-gm-primary btn-sm"><i class="fas fa-plus me-1"></i> Nuevo cliente</button>
</div>
</div>
Buscador de tabla
Filtra la tabla de abajo y muestra cuántos registros quedaron.
GrupoMecsaProyectos/pages/clientes.php
<div class="search-pill-container">
<div class="input-group-pill shadow-none border bg-light bg-opacity-50">
<input class="form-control" placeholder="Buscar clientes por nombre, identificación o tipo...">
<button class="btn-search" type="button"><i class="fa fa-search"></i></button>
</div>
<span class="search-count text-muted">Mostrando <span class="fw-bold text-dark">184</span> registros</span>
</div>
Tabla de datos
Cabecera navy, filas con hover, estado como badge y acciones al final.
GrupoMecsaProyectos/pages/clientes.php
<div class="table-gm-container shadow-none border-0">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="colors-gm-primary text-white">
<tr>
<th class="ps-4 border-0 py-3">ID</th>
<th class="border-0 py-3">PROYECTO</th>
<th class="border-0 py-3">RESPONSABLE</th>
<th class="border-0 py-3">ESTADO</th>
<th class="text-end pe-4 border-0 py-3">ACCIONES</th>
</tr>
</thead>
<tbody>
<tr>
<td class="ps-4">1042</td>
<td>Mantenimiento planta norte</td>
<td><div class="d-flex align-items-center gap-2"><div class="gm-avatar-table">MR</div> M. Rodríguez</div></td>
<td><span class="badge-gm bg-success-soft">Completado</span></td>
<td class="text-end pe-4">
<button class="btn btn-sm btn-outline-primary"><i class="fas fa-eye"></i></button>
</td>
</tr>
<tr>
<td class="ps-4">1043</td>
<td>Instalación de bombas</td>
<td><div class="d-flex align-items-center gap-2"><div class="gm-avatar-table">JS</div> J. Sánchez</div></td>
<td><span class="badge-gm bg-warning-soft">En proceso</span></td>
<td class="text-end pe-4">
<button class="btn btn-sm btn-outline-primary"><i class="fas fa-eye"></i></button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
.table-responsive: en móvil la tabla scrollea sola en vez de romper la página.Paginación
Va debajo de la tabla, con el conteo a la izquierda y la navegación a la derecha.
GrupoMecsaProyectos/pages/clientes.php
<div class="pagination-gm">
<div class="pagination-info">
<span>Mostrando 1 - 25 de 184 registros</span>
<span class="page-indicator">Página 1</span>
</div>
<div class="pagination-nav">
<a href="#" class="btn-page arrow disabled">«</a>
<a href="#" class="btn-page active">1</a>
<a href="#" class="btn-page">2</a>
<a href="#" class="btn-page">3</a>
<a href="#" class="btn-page arrow">»</a>
</div>
</div>
Resumen de ficha
Las cifras clave de un registro dentro de su detalle: monto, facturado, saldo.
GrupoMecsaProyectos/pages/proyecto.php
<div class="pd-stats">
<div class="pd-stat">
<div class="pd-stat-label">Monto del proyecto</div>
<div class="pd-stat-value">₡12.450.000</div>
<div class="pd-stat-foot">Tipo de cambio 515,00</div>
</div>
<div class="pd-stat">
<div class="pd-stat-label">Facturado</div>
<div class="pd-stat-value">₡8.400.000</div>
</div>
<div class="pd-stat">
<div class="pd-stat-label">Saldo pendiente</div>
<div class="pd-stat-value">₡4.050.000</div>
</div>
</div>
Bitácora
Quién cambió qué y cuándo. Aparece en el detalle de cualquier registro auditado.
GrupoMecsaProyectos/pages/proyecto.php
<div class="pd-timeline">
<div class="pd-tl-item">
<span class="pd-tl-dot"></span>
<div class="pd-tl-body">
<div class="pd-tl-head"><strong>M. Rodríguez</strong> cambió el estado <span class="pd-muted">· hace 2 h</span></div>
<div class="pd-tl-diff">En ejecución → Pendiente informe</div>
</div>
</div>
<div class="pd-tl-item">
<span class="pd-tl-dot"></span>
<div class="pd-tl-body">
<div class="pd-tl-head"><strong>J. Sánchez</strong> agregó una factura <span class="pd-muted">· ayer</span></div>
<div class="pd-tl-diff">FE-00001482 · ₡1.250.000</div>
</div>
</div>
</div>
Aviso y atajo
El aviso ámbar del panel de ayuda y la representación de una tecla.
starter/components/help.php
<div class="help-tip mb-3">
<i class="fas fa-lightbulb"></i>
<div>Los proyectos no se borran de verdad: se marcan como eliminados y dejan de aparecer.</div>
</div>
<div class="help-kbd-row">
<span><span class="help-kbd">Ctrl</span> + <span class="help-kbd">K</span></span>
<span>Ir al buscador</span>
</div>
Alertas
Resultado de una acción o advertencia dentro del flujo. No las uses para ayuda permanente.
styles/app-shell.css
<div class="alert alert-success"><i class="fas fa-circle-check me-1"></i> El cliente se guardó correctamente.</div>
<div class="alert alert-warning"><i class="fas fa-triangle-exclamation me-1"></i> Hay facturas vencidas de este cliente.</div>
<div class="alert alert-danger mb-0"><i class="fas fa-circle-xmark me-1"></i> No se pudo guardar: revisá los campos marcados.</div>
Migas de pan
Ubicación dentro del sitio. Va debajo del encabezado en las páginas internas.
GrupoMecsa/components/breadcrumb.php
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="#">Inicio</a></li>
<li class="breadcrumb-item"><a href="#">Servicios</a></li>
<li class="breadcrumb-item active" aria-current="page">Protección contra rayos</li>
</ol>
</nav>
Tarjeta de producto
La tarjeta de la tienda: imagen cuadrada, acciones al pasar el mouse, estrellas y precio.
GrupoMecsa/scripts/maintienda.js
<div class="row g-3" style="max-width:640px">
<div class="col-6">
<div class="h-100 product-card product-hover-card" tabindex="0">
<div class="ratio ratio-1x1 card-img-wrap">
<img src="../../assets/ph-square.svg" class="card-img-top" alt="Producto">
<button class="wishlist-toggle" title="Agregar a Wish List"><i class="fa-regular fa-heart"></i></button>
<button class="quick-view-btn cart-btn" title="Añadir al carrito"><i class="fa-solid fa-cart-shopping"></i></button>
<span class="badge product-category-badge">Pararrayos</span>
</div>
<div class="card-body d-flex flex-column align-items-center justify-content-end product-card-body">
<div class="product-title text-center">Pararrayos Franklin 4 puntas</div>
<span class="product-stock-status mb-1 text-success">Disponibles: 12</span>
<div class="product-rating text-warning my-1 small">
<i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i>
<i class="fa-solid fa-star"></i><i class="fa-regular fa-star"></i>
<span class="text-muted ms-1" style="font-size:.75rem;">(8)</span>
</div>
<div class="product-price">₡84.500</div>
</div>
</div>
</div>
</div>
<span class="badge bg-warning text-dark">Cotizar</span>.Tarjeta de blog
Entrada del blog en el listado: portada, categorías, extracto y metadatos.
GrupoMecsa/pages/blog.php
<div class="row gm-posts-row" style="max-width:400px">
<div class="col-12">
<div class="card h-100 gm-card">
<a href="#" class="text-decoration-none">
<img src="../../assets/ph-wide.svg" class="card-img-top gm-card-cover" alt="Portada" loading="lazy">
</a>
<div class="card-body d-flex flex-column">
<a href="#" class="text-decoration-none">
<h5 class="card-title gm-card-title">Cómo saber si tu edificio necesita pararrayos</h5>
</a>
<div class="gm-card-categories-container mb-2">
<a href="#" class="gm-card-category me-2 text-decoration-none">Seguridad</a>
<a href="#" class="gm-card-category text-decoration-none">Protección contra rayos</a>
</div>
<p class="card-text gm-card-excerpt">Cuatro señales de que la instalación actual quedó corta frente a la norma vigente...</p>
<div class="mt-auto pt-3">
<div class="gm-card-author d-flex align-items-center">
<div class="author-avatar-small me-2"></div>
<div class="d-flex flex-column">
<span class="author-name">Grupo Mecsa</span>
<span class="post-date text-muted small">Ago 12 · 5 min read</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Tarjeta de vacante
Puesto abierto en Trabaja con Nosotros. El contenido lo administra KoraCMS.
GrupoMecsa/pages/trabaja-con-nosotros.php
<div style="max-width:420px">
<div class="card h-100 shadow-sm border-0 card-vacante-gm">
<div class="card-body">
<div class="d-flex justify-content-between mb-2">
<span class="badge bg-primary-light text-primary">Operaciones</span>
<span class="text-muted small"><i class="fa-solid fa-location-dot me-1"></i>San José</span>
</div>
<h4 class="card-title h4-gm fw-bold">Técnico electromecánico</h4>
<p class="card-text text-truncate-3 p-gm mb-3">Mantenimiento preventivo y correctivo de sistemas industriales en sitio, con disponibilidad para giras.</p>
<div class="mt-auto">
<div class="d-flex justify-content-between align-items-center">
<span class="small text-muted">Tiempo completo</span>
<a href="#" class="btn btn-primary btn-gm-primary">Ver Detalles</a>
</div>
</div>
</div>
</div>
</div>
Alertas del sitio
Confirmaciones y errores de los formularios públicos (contacto, cuenta, checkout).
GrupoMecsa/scripts/account.js
<div class="alert alert-gm-success">
<i class="fa-solid fa-check-circle"></i>
<div>Contraseña actualizada correctamente.</div>
<button class="alert-close" aria-label="Cerrar">×</button>
</div>
<div class="alert alert-gm-error mb-0">
<i class="fa-solid fa-triangle-exclamation"></i>
<div>No pudimos procesar el pago. Revisá los datos de la tarjeta.</div>
<button class="alert-close" aria-label="Cerrar">×</button>
</div>
.alert es obligatoria: sola, .alert-gm-success no pinta nada. El icono y el <div> son parte del layout flex.Filtros de la tienda
Columna izquierda del catálogo. Cada sección se pliega y recuerda su estado.
GrupoMecsa/scripts/maintienda.js
<div style="max-width:280px">
<div class="filter-section">
<div class="filter-header">
<span class="filter-title">Categorías</span>
<button class="filter-toggle" aria-expanded="true">−</button>
</div>
<ul class="filter-list filter-content">
<li class="filter-item"><label><input type="checkbox" checked> Pararrayos</label></li>
<li class="filter-item"><label><input type="checkbox"> Puestas a tierra</label></li>
<li class="filter-item"><label><input type="checkbox"> Señalización</label></li>
</ul>
<button class="filter-show-more">Ver más</button>
</div>
</div>
Autocompletado del buscador
Sugerencias mientras se escribe en el buscador del encabezado: producto, servicio o artículo.
GrupoMecsa/components/header.php
<div class="gm-search-autocomplete position-relative" style="max-width:460px">
<input class="form-control form-control-gm-search w-100" type="search" value="pararrayos" aria-label="Buscar">
<div class="gm-search-suggestions shadow-lg" style="position:relative;display:block;">
<div class="gm-search-feedback small text-muted px-3 py-2">3 resultados</div>
<div class="gm-search-results">
<a href="#" class="gm-search-item">
<span class="gm-search-item__icon"><i class="fa-solid fa-magnifying-glass"></i></span>
<span class="gm-search-item__title">Pararrayos Franklin 4 puntas</span>
<span class="gm-search-item__type">producto</span>
</a>
<a href="#" class="gm-search-item">
<span class="gm-search-item__icon"><i class="fa-solid fa-magnifying-glass"></i></span>
<span class="gm-search-item__title">Protección contra rayos</span>
<span class="gm-search-item__type">servicio</span>
</a>
<a href="#" class="gm-search-item">
<span class="gm-search-item__icon"><i class="fa-solid fa-magnifying-glass"></i></span>
<span class="gm-search-item__title">¿Cada cuánto se revisa un pararrayos?</span>
<span class="gm-search-item__type">artículo</span>
</a>
</div>
<button type="button" class="gm-search-view-all btn btn-link w-100 text-start">Ver todos los resultados</button>
</div>
</div>
hidden) y lo abre el JS del buscador; acá se muestra desplegado. El endpoint es pages/api/search-suggestions.php.Selector de variantes
Opciones de un producto (medida, color, material) con su indicador de existencias.
GrupoMecsa/scripts/product.js
<div class="variant-selectors" style="max-width:380px">
<div class="variant-group mb-3">
<label class="form-label small fw-semibold" for="variant-select-0">Altura</label>
<select class="form-select variant-select" id="variant-select-0">
<option>1,5 m</option>
<option>3,0 m</option>
</select>
</div>
<div class="variant-group mb-3">
<label class="form-label small fw-semibold" for="variant-select-1">Material</label>
<select class="form-select variant-select" id="variant-select-1">
<option>Cobre</option>
<option>Acero inoxidable</option>
</select>
</div>
<div class="variant-stock-indicator text-success">
<i class="fa-solid fa-circle-check me-1"></i> 12 disponibles
</div>
</div>
Resumen de reseñas
Promedio y reparto por cantidad de estrellas en la ficha de producto.
GrupoMecsa/scripts/product.js
<div style="max-width:420px">
<div class="review-avg-box mb-4">
<span class="rating-number">4,2</span>
<div class="rating-stars">
<i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i>
<i class="fa-solid fa-star"></i><i class="fa-regular fa-star"></i>
</div>
<div class="rating-count">38 reseñas</div>
</div>
<div class="review-distribution mb-0">
<div class="dist-row">
<div class="dist-star-label">5 <i class="fa-solid fa-star small text-warning"></i></div>
<div class="progress"><div class="progress-bar" role="progressbar" style="width:60%"></div></div>
<div class="dist-count">23</div>
</div>
<div class="dist-row">
<div class="dist-star-label">4 <i class="fa-solid fa-star small text-warning"></i></div>
<div class="progress"><div class="progress-bar" role="progressbar" style="width:24%"></div></div>
<div class="dist-count">9</div>
</div>
<div class="dist-row">
<div class="dist-star-label">3 <i class="fa-solid fa-star small text-warning"></i></div>
<div class="progress"><div class="progress-bar" role="progressbar" style="width:10%"></div></div>
<div class="dist-count">4</div>
</div>
<div class="dist-row">
<div class="dist-star-label">2 <i class="fa-solid fa-star small text-warning"></i></div>
<div class="progress"><div class="progress-bar" role="progressbar" style="width:5%"></div></div>
<div class="dist-count">2</div>
</div>
<div class="dist-row">
<div class="dist-star-label">1 <i class="fa-solid fa-star small text-warning"></i></div>
<div class="progress"><div class="progress-bar" role="progressbar" style="width:0%"></div></div>
<div class="dist-count">0</div>
</div>
</div>
</div>
Entradas populares
Lista lateral del blog: miniatura, título, etiqueta y tiempo de lectura.
GrupoMecsa/pages/blog.php
<div style="max-width:360px">
<div class="gm-popular-post d-flex align-items-start mb-3">
<a href="#" class="flex-shrink-0 me-3">
<img src="../../assets/ph-wide.svg" alt="Portada" class="gm-popular-img rounded" loading="lazy">
</a>
<div class="gm-popular-content">
<a href="#" class="text-decoration-none">
<h6 class="gm-popular-title mb-1 text-dark">Cómo saber si tu edificio necesita pararrayos</h6>
</a>
<div class="gm-popular-meta d-flex align-items-center">
<span class="badge bg-light text-primary rounded-pill px-2 py-1 me-2 small fw-normal">Seguridad</span>
<span class="text-muted small">5 min read</span>
</div>
</div>
</div>
<div class="gm-popular-post d-flex align-items-start">
<a href="#" class="flex-shrink-0 me-3">
<img src="../../assets/ph-wide.svg" alt="Portada" class="gm-popular-img rounded" loading="lazy">
</a>
<div class="gm-popular-content">
<a href="#" class="text-decoration-none">
<h6 class="gm-popular-title mb-1 text-dark">Demarcación vial: qué pide la norma en Costa Rica</h6>
</a>
<div class="gm-popular-meta d-flex align-items-center">
<span class="badge bg-light text-primary rounded-pill px-2 py-1 me-2 small fw-normal">Vialidad</span>
<span class="text-muted small">5 min read</span>
</div>
</div>
</div>
</div>
Temas del blog
Filtro de categorías del blog. Las subcategorías se pintan recursivamente.
GrupoMecsa/pages/blog.php
<div style="max-width:320px">
<div class="card gm-categories-card border-0">
<div class="card-body">
<h5 class="card-title fw-bold mb-3">Temas:</h5>
<div class="gm-categories-list">
<a href="#" class="gm-category-item active">Todos</a>
<a href="#" class="gm-category-item">Protección contra rayos</a>
<a href="#" class="gm-category-item">Asfalto y demarcación</a>
<a href="#" class="gm-category-item">Mantenimiento industrial</a>
</div>
</div>
</div>
</div>
Paginación del sitio
La del blog y la del catálogo. Es la paginación de Bootstrap con la piel de la marca.
GrupoMecsa/pages/blog.php
<nav aria-label="Navegación del blog">
<ul class="pagination justify-content-center gm-pagination">
<li class="page-item disabled">
<a class="page-link" href="#" aria-label="Anterior"><span aria-hidden="true">« Anterior</span></a>
</li>
<li class="page-item active"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item">
<a class="page-link" href="#" aria-label="Siguiente"><span aria-hidden="true">Siguiente »</span></a>
</li>
</ul>
</nav>
Horarios de atención
Bloque de la página de contacto. Los días cerrados llevan la clase cerrado.
GrupoMecsa/pages/contactenos.php
<div class="card-horarios-gm" style="max-width:420px">
<h3 class="titulo-horarios-gm">Horarios de la Empresa</h3>
<ul class="lista-horarios-gm">
<li><span class="dia">Lunes</span><span class="hora">07:00 AM - 05:00 PM</span></li>
<li><span class="dia">Martes</span><span class="hora">07:00 AM - 05:00 PM</span></li>
<li><span class="dia">Miércoles</span><span class="hora">07:00 AM - 05:00 PM</span></li>
<li><span class="dia">Jueves</span><span class="hora">07:00 AM - 05:00 PM</span></li>
<li><span class="dia">Viernes</span><span class="hora">07:00 AM - 05:00 PM</span></li>
<li><span class="dia">Sábado</span><span class="hora cerrado">Cerrado</span></li>
<li><span class="dia">Domingo</span><span class="hora cerrado">Cerrado</span></li>
</ul>
</div>
Resumen del pedido
La columna derecha del pago con Onvo: líneas, impuestos y total.
GrupoMecsa/ecommerce/onvo_payment.php
<div class="onvo-order-summary-card" style="max-width:420px">
<h3>Resumen del Pedido</h3>
<div class="onvo-items-list">
<div class="onvo-summary-item-v2">
<div>
<div class="fw-semibold">Pararrayos Franklin 4 puntas</div>
<div class="text-muted small">1 × ₡74.779</div>
</div>
<div class="fw-semibold">₡74.779</div>
</div>
<div class="onvo-summary-item-v2">
<div>
<div class="fw-semibold">Cable de bajada 50 mm²</div>
<div class="text-muted small">2 × ₡18.500</div>
</div>
<div class="fw-semibold">₡37.000</div>
</div>
</div>
<div class="onvo-summary-totals">
<div class="d-flex justify-content-between"><span>Subtotal</span><span>₡111.779</span></div>
<div class="d-flex justify-content-between"><span>IVA (13%)</span><span>₡14.531</span></div>
<div class="d-flex justify-content-between fw-bold"><span>Total</span><span>₡126.310</span></div>
</div>
<div class="onvo-secure-badge"><i class="fa-solid fa-lock me-1"></i> Pago seguro procesado por Onvo</div>
</div>