Overview
The project uses a component-based CSS architecture with a centralized custom properties system. All styles are written in vanilla CSS with no preprocessors or CSS-in-JS frameworks.
CSS Custom Properties (Variables)
All color values are defined as CSS custom properties in css/style.css:1-31:
Color System
:root {
/* Colores del header y del footer */
--header-yellow : #ffce00 ;
--footer-background-blue : #1f2937 ;
/* Colores principales del sitio */
--primary-blue : #003366 ;
--primary-blue-dark : #002244 ;
--background-gray : #f5f5f5 ;
--white : #ffffff ;
/* Colores de texto */
--text-gray-light : #6a6f7b ;
--text-gray : #374151 ;
--text-gray-dark : #1f2937 ;
/* Colores de bordes y fondos */
--border-light : #e5e7eb ;
--border-lighter : #f3f4f6 ;
--bg-blue-light : #eff6ff ;
--bg-blue-lighter : #dbeafe ;
--border-blue : #bfdbfe ;
/* Colores de estado */
--success-green : #059669 ;
--success-green-dark : #047857 ;
/* Colores neutros */
--neutral-light : #f3f4f6 ;
--neutral-dark : #d1d5db ;
}
Why Custom Properties?
Single source of truth: Change a color once, update everywhere
Easy theming: Swap out the color scheme by changing the :root values
Better maintainability: Semantic names like --primary-blue instead of #003366
Color Usage Patterns
Variable Usage Examples --primary-bluePrimary actions, headings, links Button backgrounds, h1-h3 titles --primary-blue-darkHover states for primary actions Button hover effects --header-yellowHeader background Top navigation bar --footer-background-blueFooter background Bottom section --background-grayPage background Body background color --text-gray-lightSecondary text, descriptions Paragraph text, labels --text-grayPrimary text Body copy --border-lightDividers, input borders Form field borders --bg-blue-lightInfo boxes, highlights Information panels --success-greenSuccess states, confirm buttons Confirmation actions
CSS Reset
The project includes a minimal CSS reset in css/style.css:33-59:
/* CSS Reset */
* {
margin : 0 ;
padding : 0 ;
border : 0 ;
box-sizing : border-box ;
}
body {
width : 100 % ;
font-family : Arial , Helvetica , sans-serif ;
}
ol , ul {
list-style : none ;
}
table {
border-collapse : collapse ;
border-spacing : 0 ;
}
a {
text-decoration : none ;
color : inherit ;
}
This reset is intentionally minimal to:
Remove browser default styles
Set box-sizing: border-box globally (makes width calculations easier)
Normalize margins and padding
Remove list bullets
Remove link underlines (added back via hover states)
Global Styles
Base layout and typography styles are defined in css/style.css:61-123:
Body & Layout
body {
background-color : var ( --background-gray );
}
main {
display : flex ;
flex-direction : column ;
margin : 0 px auto ;
max-width : 900 px ;
}
Key points:
Light gray background for visual separation
Main content container centered with max-width of 900px
Flexbox column layout for vertical stacking
Typography
The project uses Arial, Helvetica, sans-serif as the font stack:
body {
font-family : Arial , Helvetica , sans-serif ;
}
No custom fonts are loaded. This keeps the project lightweight and ensures fast loading times. If you want to add custom fonts, see the Customization guide .
Title Sections
#titulo {
margin : 20 px 0 px ;
}
#titulo > h1 {
color : var ( --primary-blue );
}
#titulo > p {
margin-top : 20 px ;
color : var ( --text-gray-light );
}
Every page has a title section with:
Blue h1 heading
Gray descriptive paragraph
20px spacing
Info Boxes
.info {
margin-block : 30 px ;
display : flex ;
flex-direction : column ;
justify-content : center ;
gap : 10 px ;
background-color : var ( --bg-blue-light );
text-align : left ;
padding : 30 px ;
border-radius : 10 px ;
}
.info > h3 {
display : flex ;
flex-direction : row ;
gap : 15 px ;
align-items : center ;
color : var ( --primary-blue );
margin-bottom : 15 px ;
}
Consistent information panels across all pages with:
Light blue background
Icon + heading combination
10px border radius
30px padding
Component Styles
header {
background-color : var ( --header-yellow );
display : flex ;
flex-direction : row ;
justify-content : space-between ;
flex-wrap : wrap ;
padding : 25 px 100 px ;
align-content : center ;
}
header img {
height : 55 px ;
aspect-ratio : 445 / 103 ;
}
Responsive behavior:
Desktop (>1024px)
Tablet (480-1024px)
Mobile (≤480px)
Horizontal layout with flex
Logo on left, navigation on right
100px horizontal padding
Menu button hidden
Reduced padding (45px)
Navigation wraps below logo
Full-width navigation
Hamburger menu button visible
Navigation hidden by default
Toggle via .visible-nav class
Vertical navigation list
Mobile Navigation
@media ( width <= 480 px ) {
#menu-toggle {
display : flex ;
flex-direction : row ;
align-items : center ;
background-color : transparent ;
}
nav {
display : none ;
width : 100 % ;
background : var ( --header-yellow );
}
nav ul {
flex-direction : column ;
gap : 10 px ;
padding : 15 px 0 ;
}
}
JavaScript toggles the visible-nav class:
.visible-nav {
display : block ;
}
footer {
background-color : var ( --footer-background-blue );
color : var ( --white );
padding : 0 50 px ;
}
footer > #content {
display : flex ;
flex-direction : row ;
gap : 5 % ;
padding : 30 px 50 px ;
}
footer > #content > div {
width : 30 % ;
}
Three-column layout:
Logo + government info (30%)
Enlaces de interés (30%)
Contacto y ayuda (30%)
5% gaps between columns
On mobile (≤480px), switches to vertical stacking:
@media ( width <= 480 px ) {
footer > #content {
display : flex ;
flex-direction : column ;
width : 100 % ;
gap : 10 px ;
padding-inline : 0 ;
}
footer > #content > div {
width : 100 % ;
}
}
Option Cards (css/index.css, css/iniciar-solicitud.css)
Both the homepage and start request page use similar card layouts:
#opciones-cita {
display : flex ;
flex-direction : row ;
justify-content : center ;
gap : 25 px ;
}
#opciones-cita > div {
width : 50 % ;
background-color : var ( --white );
display : flex ;
flex-direction : column ;
justify-content : center ;
padding : 50 px ;
border-radius : 10 px ;
}
Card buttons:
.opcion-cita > a {
display : flex ;
flex-direction : row ;
justify-content : center ;
align-items : center ;
gap : 10 px ;
padding : 20 px 40 px ;
border-radius : 10 px ;
background-color : var ( --primary-blue );
color : var ( --white );
font-size : 15 px ;
font-weight : bold ;
cursor : pointer ;
transition : all 0.3 s ease ;
}
.opcion-cita > a :hover {
opacity : .9 ;
scale : .99 ;
}
Hover Effect Pattern:
Reduce opacity to 0.9
Slightly scale down to 0.99
0.3s ease transition
This creates a subtle “press” effect that’s used throughout the application.
Primary vs Secondary Buttons:
/* Primary button (first card) */
.opcion-cita > a {
background-color : var ( --primary-blue );
color : var ( --white );
}
/* Secondary button (second card) */
.opcion-cita:nth-child ( 2 ) > a {
background-color : var ( --border-light );
color : var ( --text-gray-dark );
}
#formulario-cita {
background-color : var ( --white );
border-radius : 10 px ;
padding : 30 px ;
margin-bottom : 30 px ;
box-shadow : 0 1 px 3 px rgba ( 0 , 0 , 0 , 0.1 );
}
Subtle shadow for depth (1px offset, 3px blur, 10% opacity).
.seccion-formulario h2 {
display : flex ;
align-items : center ;
gap : 10 px ;
color : var ( --primary-blue );
font-size : 1.3 rem ;
margin-bottom : 20 px ;
padding-bottom : 10 px ;
border-bottom : 2 px solid var ( --border-light );
}
Section headings include:
Inline SVG icon
10px gap between icon and text
Bottom border for visual separation
.campo-formulario input ,
.campo-formulario select ,
.campo-formulario textarea {
width : 100 % ;
padding : 12 px 16 px ;
border : 2 px solid var ( --border-light );
border-radius : 8 px ;
font-size : 16 px ;
transition : border-color 0.3 s ease ;
box-sizing : border-box ;
font-family : Arial , Helvetica , sans-serif ;
}
Focus states:
.campo-formulario input :focus ,
.campo-formulario select :focus ,
.campo-formulario textarea :focus {
outline : none ;
border-color : var ( --primary-blue );
box-shadow : 0 0 0 3 px rgba ( 0 , 51 , 102 , 0.1 );
}
Accessibility: The blue focus ring (3px with 10% opacity) provides clear visual feedback while maintaining the design aesthetic.
Invalid states:
.campo-formulario input :invalid {
border-color : #ef4444 ;
}
Two-Column Layout
.campos-fila {
display : flex ;
gap : 20 px ;
flex-wrap : wrap ;
}
.campos-fila .campo-formulario {
flex : 1 ;
min-width : 200 px ;
}
Flexible grid that:
Displays fields side-by-side on desktop
Wraps to single column when space is tight
Maintains 200px minimum width per field
.botones-formulario {
display : flex ;
gap : 20 px ;
justify-content : center ;
margin-top : 30 px ;
flex-wrap : wrap ;
}
.botones-formulario a ,
.botones-formulario button {
display : flex ;
align-items : center ;
gap : 8 px ;
padding : 15 px 30 px ;
border : none ;
border-radius : 8 px ;
font-size : 16 px ;
font-weight : 600 ;
cursor : pointer ;
transition : all 0.3 s ease ;
min-width : 150 px ;
justify-content : center ;
}
Button variants:
Button Background Text Color Use Case #btn-volver--border-light--text-grayBack/Cancel #btn-continuar--primary-blue--whiteSubmit/Continue
Summary Styles (css/resumen.css)
Status Badge
.estado-cita {
text-align : center ;
padding : 30 px ;
margin-bottom : 40 px ;
background : linear-gradient ( 135 deg , var ( --bg-blue-light ) 0 % , var ( --bg-blue-lighter ) 100 % );
border-radius : 12 px ;
border : 2 px solid var ( --border-blue );
}
Gradient background from light to lighter blue (135° diagonal).
Summary Tables
.tabla-resumen {
width : 100 % ;
border-collapse : collapse ;
margin-top : 10 px ;
}
.tabla-resumen td {
padding : 12 px 0 ;
border-bottom : 1 px solid var ( --border-lighter );
vertical-align : top ;
}
.tabla-resumen td :first-child {
color : var ( --text-gray-light );
font-weight : 500 ;
width : 35 % ;
padding-right : 20 px ;
}
.tabla-resumen td :last-child {
color : var ( --text-gray );
font-weight : 400 ;
}
Layout:
First column (labels): 35% width, gray, medium weight
Second column (values): 65% width, darker, normal weight
Bottom borders between rows
No border on last row
#btn-modificar {
background-color : var ( --neutral-light );
color : var ( --text-gray );
border : 2 px solid var ( --border-light );
}
#btn-confirmar {
background-color : var ( --success-green );
color : var ( --white );
}
#btn-imprimir {
background-color : var ( --primary-blue );
color : var ( --white );
}
Three distinct button styles:
Modify: Neutral with border (secondary action)
Confirm: Green (primary success action)
Print: Blue (utility action)
Responsive Design Strategy
The project uses mobile-first breakpoints with @media queries:
Breakpoints
Breakpoint Target Key Changes Default Mobile-first base Optimized for small screens 481px - 1024px Tablets Reduced padding, adjusted layouts >1024px Desktop Full layout with max-width constraints
≤480px
481-1024px
>1024px
Single column layouts
Hamburger menu
Stacked footer
Reduced padding
Touch-friendly targets (min 44x44px)
Two-column grids where appropriate
Visible navigation
Reduced horizontal padding
Optimized for tablets
Full desktop layout
Max-width container (900px)
Generous padding
Multi-column layouts
Common Responsive Patterns
Padding reduction:
@media ( width <= 1024 px ) {
main {
padding-inline : 1 rem ;
}
}
Layout switching:
@media ( width <= 1024 px ) {
#opciones-cita {
flex-wrap : wrap ;
width : 100 % ;
}
#opciones-cita > div {
width : 100 % ;
}
}
Font size adjustments:
@media ( width <= 480 px ) {
.estado-cita h2 {
font-size : 1.3 rem ;
}
}
SVG Icons
All icons are inline SVG elements, not external files:
< svg xmlns = "http://www.w3.org/2000/svg" width = "24" height = "24" viewBox = "0 0 24 24"
fill = "none" stroke = "currentColor" stroke-width = "2"
stroke-linecap = "round" stroke-linejoin = "round" >
< path stroke = "none" d = "M0 0h24v24H0z" fill = "none" />
< path d = "M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0" />
< path d = "M9 12l2 2l4 -4" />
</ svg >
Benefits of Inline SVG:
No extra HTTP requests
Icons inherit currentColor (text color)
Easy to style with CSS
Scalable at any size
The stroke="currentColor" attribute ensures icons match the text color of their parent element.
Animations & Transitions
Subtle animations enhance the user experience:
Transition Pattern
transition: all 0 .3s ease;
Used consistently across:
Button hover states
Input focus states
Link hover effects
Hover Effects
Buttons:
.opcion-cita > a :hover {
opacity : .9 ;
scale : .99 ;
}
Links:
header a :hover {
text-decoration : underline ;
}
.enlaces-footer > a :hover {
opacity : .8 ;
}
All transitions are kept to 0.3 seconds with ease timing for smooth, natural motion.
No Build Step Vanilla CSS loads instantly with no compilation required
Minimal CSS Total CSS size < 10KB (all files combined)
No External Dependencies No CSS frameworks or libraries to download
Modern Features CSS custom properties, flexbox, modern selectors
Best Practices
Use Custom Properties
Always reference color variables instead of hardcoding hex values: /* Good */
color: var(--primary-blue);
/* Bad */
color: #003366 ;
Follow BEM-like Naming
Use descriptive class names:
.seccion-formulario (section)
.campo-formulario (field)
.botones-formulario (buttons)
Keep Specificity Low
Avoid deeply nested selectors: /* Good */
.tabla-resumen td { }
/* Bad */
.contenedor-resumen .seccion-resumen .tabla-resumen tbody tr td { }
Mobile-First Approach
Write base styles for mobile, then enhance for larger screens: /* Base (mobile) */
.elemento { width : 100 % ; }
/* Enhanced (desktop) */
@media ( width > 1024 px ) {
.elemento { width : 50 % ; }
}
Next Steps
Project Structure Learn about the file and folder organization
Customization Guide Customize colors, fonts, and layout to match your needs