200 Mates uses a custom CSS architecture built around CSS custom properties (variables) and a carefully crafted dark theme optimized for the globe visualization.
Single Stylesheet Approach
All styles are contained in a single file: styles/style.css (805 lines)
Benefits:
No build process or CSS preprocessing
Easy to locate and modify styles
Fast loading with a single HTTP request
Clear cascade and specificity
The stylesheet is loaded in the <head> of index.html:16 for optimal rendering performance.
CSS Custom Properties
The design system uses CSS variables defined in :root for consistent theming:
Color Palette
:root {
/* Primary green (mate/yerba inspired) */
--verde : #3d5c35 ;
--verde-light : #5a7d52 ;
--verde-dark : #283d22 ;
--verde-glow : rgba ( 61 , 92 , 53 , 0.35 );
/* Accent colors */
--yerba : #7a9e52 ; /* Bright green for highlights */
--tierra : #b8945e ; /* Earth tone for warnings */
--tierra-light : #d8c5a0 ;
--parchment : #f0e8d8 ; /* Light accent */
/* Dark theme grays */
--dark : #0e100c ; /* Body background */
--dark-2 : #131510 ;
--dark-3 : #1a1e14 ; /* Card backgrounds */
--dark-4 : #1f2419 ;
--mid : #2e332a ;
/* Text hierarchy */
--text : #e2ddd3 ; /* Primary text */
--text-muted : #7a7868 ; /* Secondary text */
--text-faint : #484840 ; /* Tertiary text */
/* Borders */
--border : rgba ( 120 , 158 , 82 , 0.18 ); /* Green tinted */
--border-warm : rgba ( 184 , 148 , 94 , 0.22 ); /* Warm tinted */
}
Layout Variables
:root {
--radius : 8 px ; /* Standard border radius */
--radius-lg : 14 px ; /* Large border radius */
--font : 'DM Sans' , sans-serif ;
}
The green color palette is inspired by mate (yerba mate), creating a cohesive visual connection between the UI and the subject matter.
Typography
Font Family
The entire application uses DM Sans , loaded from Google Fonts:
< link href = "https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;1,9..40,400&display=swap" rel = "stylesheet" >
Weights used:
300 (Light) - Sparingly for subtle elements
400 (Regular) - Body text
500 (Medium) - Secondary headings
600 (Semi-bold) - Labels and buttons
700 (Bold) - Primary headings and emphasis
Type Scale
h1 { font-size : 24 px ; font-weight : 700 ; } /* Header title */
.panel-title { font-size : 16 px ; font-weight : 700 ; } /* Section headings */
.gallery-name { font-size : 16 px ; font-weight : 600 ; } /* Gallery cards */
body { font-size : 13 px ; } /* Base font size */
.field-label { font-size : 12 px ; font-weight : 600 ; } /* Form labels */
.drop-content p { font-size : 11 px ; } /* Menu text */
.hstat-label { font-size : 11 px ; } /* Stat labels */
Font sizes are deliberately small (13px base) to maximize information density while maintaining readability on the compact side panel.
Component Styles
.site-header {
position : sticky ;
top : 0 ;
z-index : 500 ;
background : rgba ( 12 , 13 , 10 , 0.97 );
backdrop-filter : blur ( 20 px ); /* Frosted glass effect */
border-bottom : 1 px solid var ( --border );
padding : 0 24 px ;
}
Features:
Sticky positioning keeps header visible while scrolling
Backdrop blur creates depth
Semi-transparent background
Globe Section (style.css:280-301)
.globe-section {
flex : 1 ;
background : radial-gradient (
ellipse at 50 % 50 % ,
#111608 0 % ,
#080908 100 %
);
}
The background gradient creates a subtle vignette effect that draws attention to the center of the globe.
Side Panel (style.css:303-320)
.side-panel {
width : 340 px ;
height : 100 % ;
overflow-y : auto ;
background : #131510 ;
border-left : 1 px solid rgba ( 122 , 158 , 82 , .12 );
/* Custom scrollbar */
scrollbar-width : thin ;
scrollbar-color : var ( --mid ) transparent ;
}
Fixed width ensures consistent layout across screen sizes (until mobile breakpoint).
.field-input {
background : var ( --dark-3 );
border : 1 px solid rgba ( 122 , 158 , 82 , .18 );
border-radius : 7 px ;
color : var ( --text );
padding : 10 px 12 px ;
transition : border-color .18 s , box-shadow .18 s ;
}
.field-input:focus {
border-color : rgba ( 122 , 158 , 82 , .45 );
box-shadow : 0 0 0 2 px rgba ( 61 , 92 , 53 , .2 ); /* Glow effect */
}
Accessibility: Focus states are prominent with both color and shadow changes.
.btn-submit-main {
background : var ( --verde );
border : none ;
border-radius : 8 px ;
color : #fff ;
padding : 14 px ;
font-size : 17 px ;
font-weight : 600 ;
box-shadow : 0 3 px 16 px rgba ( 61 , 92 , 53 , .3 );
transition : background .2 s , transform .15 s , box-shadow .2 s ;
}
.btn-submit-main:hover:not ( :disabled ) {
background : var ( --verde-light );
transform : translateY ( -1 px ); /* Lift effect */
box-shadow : 0 5 px 22 px rgba ( 61 , 92 , 53 , .42 );
}
Micro-interactions: Buttons lift on hover for tactile feedback.
Gallery Cards (style.css:338-374)
.gallery-card {
display : flex ;
align-items : center ;
gap : 14 px ;
background : #1a1e14 ;
border : 1 px solid rgba ( 122 , 158 , 82 , .14 );
border-radius : 8 px ;
padding : 10 px 12 px ;
animation : cardIn .35 s ease both ;
}
@keyframes cardIn {
from { opacity : 0 ; transform : translateY ( 6 px ); }
to { opacity : 1 ; transform : none ; }
}
Staggered animation creates a pleasant reveal effect when cards load.
Dark Theme for Globe
The color scheme is specifically optimized for the dark globe background:
Dark backgrounds (--dark, --dark-2, --dark-3) prevent UI from competing with the globe
Green accents (--yerba, --verde) complement the earth tones of the globe
Subtle borders use low opacity to avoid harsh edges
Warm accents (--tierra) provide contrast for warnings and secondary actions
Visual Effects
Noise Texture
body ::before {
content : '' ;
position : fixed ;
inset : 0 ;
background-image : url ( "data:image/svg+xml,..fractalNoise.." );
pointer-events : none ;
opacity : 0.4 ;
}
A subtle fractal noise overlay adds texture and depth to the entire interface.
Backdrop Blur
Used throughout for depth and layering:
.site-header { backdrop-filter : blur ( 20 px ); }
.drop-backdrop { backdrop-filter : blur ( 3 px ); }
.lightbox-bg { backdrop-filter : blur ( 8 px ); }
Shadows
Shadows create hierarchy and elevation:
/* Subtle elevation */
box-shadow : 0 3px 16px rgba(61,92,53, .3 );
/* Prominent modals */
box-shadow : 0 20px 60px rgba(0,0,0, .95 );
/* Glow effects */
box-shadow : 0 0 14px rgba(122,158,82, .3 );
Animations
Success Modal (style.css:617-710)
Elaborate animation sequence:
.smodal-mate-emoji {
animation : mateWobble .6 s ease .1 s both ;
}
@keyframes mateWobble {
0% { transform : scale ( .5 ) rotate ( -8 deg ); opacity : 0 ; }
60% { transform : scale ( 1.1 ) rotate ( 3 deg ); opacity : 1 ; }
80% { transform : scale ( .95 ) rotate ( -1 deg ); }
100% { transform : scale ( 1 ) rotate ( 0 deg ); }
}
Sequenced animations:
Mate emoji wobbles in
Title fades up (.2s delay)
Body text fades up (.28s delay)
Divider fades up (.32s delay)
Button fades up (.42s delay)
Hamburger Icon (style.css:96-124)
.ham-btn.is-open .ham-bar:nth-child ( 1 ) {
transform : translateY ( 8 px ) rotate ( 45 deg );
}
.ham-btn.is-open .ham-bar:nth-child ( 2 ) {
opacity : 0 ;
transform : scaleX ( 0 );
}
.ham-btn.is-open .ham-bar:nth-child ( 3 ) {
transform : translateY ( -8 px ) rotate ( -45 deg );
}
Classic three-bar to X transformation.
Responsive Design
Mobile Breakpoint (style.css:714-736)
@media ( max-width : 768 px ) {
.main-layout {
flex-direction : column ; /* Stack vertically */
height : auto ;
}
.globe-section {
height : 55 vw ; /* Proportional height */
min-height : 260 px ;
max-height : 380 px ;
}
.side-panel {
width : 100 % ; /* Full width */
border-left : none ;
border-top : 1 px solid var ( --border );
}
.header-stats { display : none ; } /* Hide stats on small screens */
}
Small Mobile (style.css:774-778)
@media ( max-width : 380 px ) {
h1 { font-size : 13 px ; }
.emoji-big { font-size : 22 px ; }
.lang-btn { font-size : 10 px ; padding : 2 px 4 px ; }
}
Customization Tips
Change the color scheme
Modify the CSS custom properties in :root (lines 5-26): :root {
--verde : #your-color;
--yerba : #your-accent;
}
All components will automatically update.
Adjust spacing
Update padding and gap values in component classes: .side-panel { width : 400 px ; } /* Wider panel */
.panel-block { padding : 24 px ; } /* More breathing room */
Modify animations
Change animation durations and easing: .gallery-card {
animation : cardIn .5 s cubic-bezier ( .34 , 1.4 , .64 , 1 ) both ;
}
Add a light theme
Create a class or media query with updated custom properties: @media (prefers-color-scheme: light) {
:root {
--dark : #ffffff ;
--text : #1a1e14 ;
/* ... */
}
}
Be careful when changing the dark theme colors - the globe visualization is optimized for dark backgrounds. A light theme would require significant adjustments to the globe rendering code in modules/globe.js.
Next: Deployment Learn how to deploy 200 Mates to production.